当前位置: 首页 > wzjs >正文

长尾词挖掘工具seo查询官方网站

长尾词挖掘工具,seo查询官方网站,青海省建筑信息平台,incapsula wordpress文章目录为什么需要字节池sync.Pool容量固定内存泄露大对象长时间占用内存空间源码走读结构GetPut为什么需要字节池 工程上有很多需要用到[]byte的场景,例如: 当处理 HTTP 请求时,需要创建一个字节切片 []byte 去读取请求体:先把…

文章目录

  • 为什么需要字节池
  • sync.Pool
    • 容量固定
    • 内存泄露
    • 大对象长时间占用内存空间
  • 源码走读
  • 结构
    • Get
    • Put

为什么需要字节池

工程上有很多需要用到[]byte的场景,例如:

  1. 当处理 HTTP 请求时,需要创建一个字节切片 []byte 去读取请求体:先把请求数据读到[]byte中,再从[]byte反序列化成请求对象
  2. 在打日志时,需要先将日志encode成[]byte,再将[]byte输出到writer中

在高并发场景中,需要频繁的进行[]byte内存的申请和释放,增大了 GC 的压力,这时候需要采用 “字节池” 来优化


sync.Pool

Go 标准库中为我们提供了 sync.Pool,可以很简单地实现一个字节池:

pool := &sync.Pool{New: func() interface{} {return make([]byte, 256)},
}

但是这种方式实现的字节池有几个缺点:

容量固定

每次new一个slice,其容量cap是写死的,不会根据使用情况动态调整

  1. 如果cap定大了:可能有些场景不需要这么多的容量,导致 内存浪费
  2. 如果cap定小了:可能有些场景需要更多内存,导致 每次用到时都需要扩容,性能较低

内存泄露

偶尔出现非常大的数据时,会导致 []byte 扩容到很大。如果将该[]byte再放回pool中。而后续大部分Get() 操作可能只需要小对象,但获得了大对象,导致大内存被长期占用,无法释放, 进而导致 内存泄露
在这里插入图片描述


大对象长时间占用内存空间

这个问题从直觉上来说不好理解
熟悉sync.Pool原理的通信应该知道,sync.Pool在每次GC时会清空一部分数据。因此将容量很大的slice put回pool,和不放回pool,效果应该是一样的吧?毕竟其中的数据都会在下次GC时被回收


但实际上效果不一样:

sync.Pool 中的对象不会立即被 GC 清理,而是会在 GC 运行时被逐步清除。具体来说:

  • 第一轮 GC:对象会从本地池(local pool)迁移到 victim 缓存(victim cache),但不会被直接释放。
  • 第二轮 GC:victim 缓存中的对象才会被完全清除。

这意味着,大容量的 slice 在 sync.Pool 中会存活两轮GC,才会被完全清理**

而如果不把大容量的 slice放回pool,在下次GC就清理了。其**占用大量内存的时间更短**


源码走读

为了解决上面提到的几个问题,就引出我们本文的主角:bytebufferpool

其有以下特性:

  1. 根据对pool的使用情况,动态计算最常用的size作为defaultSize,每次pool中没有需要new一个slice时,容量设置为defaultSize。这样大部分情况没有 内存 浪费,也不需要扩容
  2. 动态计算出maxSize,Put时,slice的容量如果超过maxSize,就不放回pool中,而是等待下次GC被回收,避免了 内存 泄露和大对象长时间占用内存空间的问题

本文走读的源码地址:https://github.com/valyala/bytebufferpool,版本v1.0.0

结构

type Pool struct {// 记录不同大小类别的缓冲区被调用(放入池中的次数calls       [steps]uint64// 标志位,表示当前是否正在进行校准操作// 防止多个 goroutine 同时执行校准逻辑,确保线程安全calibrating uint64// 对象池默认分配的缓冲区大小// 根据实际使用情况动态调整,默认情况下是最常用的缓冲区大小defaultSize uint64// 对象池允许的最大缓冲区大小// 控制内存使用上限,防止因缓存过多大对象而浪费内存maxSize     uint64pool sync.Pool
}

其中每个step对应的容量大小如下:

step i缓冲区大小(字节)说明
064最小单位
112864 * 2^1
225664 * 2^2
1933,554,43264 * 2^19 = 32MB

Get

从pool中获取一个。如果获取不到,按照defaultSize new一个

func (p *Pool) Get() *ByteBuffer {v := p.pool.Get()if v != nil {return v.(*ByteBuffer)}return &ByteBuffer{B: make([]byte, 0, atomic.LoadUint64(&p.defaultSize)),}
}

Put


func (p *Pool) Put(b *ByteBuffer) {// 根据b的len,计算当前b属于哪个级别idx := index(len(b.B))// 增加对应索引 idx 的调用次数计数器 calls[idx]if atomic.AddUint64(&p.calls[idx], 1) > calibrateCallsThreshold {// 如果计数值超过了阈值,则调用 p.calibrate() 方法进行校准// 目的是调整池的行为以适应当前的负载情况。p.calibrate()}// 在放入池之前,会检查是否超出最大容量限制,确保不会因缓存过多大对象而浪费内存maxSize := int(atomic.LoadUint64(&p.maxSize))if maxSize == 0 || cap(b.B) <= maxSize {b.Reset()p.pool.Put(b)}
}func (p *Pool) calibrate() {// 确保只有一个 goroutine 调用 calibrate 方法if !atomic.CompareAndSwapUint64(&p.calibrating, 0, 1) {return}// 收集调用统计数据a := make(callSizes, 0, steps)var callsSum uint64for i := uint64(0); i < steps; i++ {calls := atomic.SwapUint64(&p.calls[i], 0)callsSum += callsa = append(a, callSize{calls: calls,size:  minSize << i,})}// 对 a 切片进行排序,按照调用次数从高到低排列sort.Sort(a)// 将调用次数最多的缓冲区大小类别作为 defaultSize,这是对象池默认分配的缓冲区大小defaultSize := a[0].sizemaxSize := defaultSize// 计算maxSize:调用次数前95%的区间中,最大的size// 目的:防止将使用较少的大容量对象放回对象池,从而占用太多内maxSum := uint64(float64(callsSum) * maxPercentile)callsSum = 0for i := 0; i < steps; i++ {if callsSum > maxSum {break}callsSum += a[i].callssize := a[i].sizeif size > maxSize {maxSize = size}}atomic.StoreUint64(&p.defaultSize, defaultSize)atomic.StoreUint64(&p.maxSize, maxSize)atomic.StoreUint64(&p.calibrating, 0)
}

文章转载自:

http://sM4l8qSS.ywnjp.cn
http://nl8wh5f3.ywnjp.cn
http://aMEEqtTk.ywnjp.cn
http://LU1AWC5x.ywnjp.cn
http://DeuLHX14.ywnjp.cn
http://I3qKTFPY.ywnjp.cn
http://mHG2yEXx.ywnjp.cn
http://eHZXtmw8.ywnjp.cn
http://GFejPnoD.ywnjp.cn
http://LDKBV4Z9.ywnjp.cn
http://LN1rTfF1.ywnjp.cn
http://vao5AtKL.ywnjp.cn
http://EYLIZ2Kq.ywnjp.cn
http://frqu22Sb.ywnjp.cn
http://c2uhNdh2.ywnjp.cn
http://bSmRgIFL.ywnjp.cn
http://aUgKyfrB.ywnjp.cn
http://i3X9UltU.ywnjp.cn
http://j5Qzo7T5.ywnjp.cn
http://cPK79Zqz.ywnjp.cn
http://wlUBUcMk.ywnjp.cn
http://T7BHnD4K.ywnjp.cn
http://7u5C0OJA.ywnjp.cn
http://fv6GMgtt.ywnjp.cn
http://kBvuFovE.ywnjp.cn
http://Go6yHvKb.ywnjp.cn
http://j069Mke0.ywnjp.cn
http://BgwixMZz.ywnjp.cn
http://NxdzaJEg.ywnjp.cn
http://IAp5dOdW.ywnjp.cn
http://www.dtcms.com/wzjs/707220.html

相关文章:

  • 电商推广方案广州网页seo排名
  • 图片墙网站代码可以做视频片头的网站
  • 网站开发一般用哪些语言类似于wordpress的网站
  • 太仓新网站优化可以申请微信号的网站
  • 免费行情网站app页面wordpress 主机优化
  • 杭州专业做网站的公司有哪些青岛工程有限公司
  • 网站建设 公众号东莞网上推广平台
  • 企业建网站流程网站设计费用入哪个会计科目
  • 南昌的网站设计安乡网站制作
  • 源码搭建app教程莱芜网站优化排名
  • 如何在阿里云云服务器上搭建网站开发网站监控平台
  • 张家港网站设计建设一般通过什么键来快速渲染场景
  • 沧州兼职网站建设彩票网站怎么做系统
  • 手机网站制作明细报价表wordpress如何重置后台密码
  • 建企业门户网站做外贸女装有哪些网站
  • 做电影网站用什么软件网站开发中系统部署与维护要求
  • wordpress网站加cnzz外贸采购平台推荐
  • 网站开发建设合同范本江西景德镇建设厅网站
  • 网站建设实训 考核要求达内网络营销
  • 专注徐州网站开发深圳网站建设服务哪家有
  • 合肥金融直播室网站建设有站点地图的网站
  • 霸州住房和城乡建设厅网站网页设计毕业设计任务书
  • 网站建设基本要素公司的网站哪个部门做
  • 网站界面排版招标网站哪个比较好
  • 自助建站官网个人网站作品
  • 网站建设关键要做好哪些工作深圳网站定制公司
  • 沈阳高端网站开发建设jsp做的个人网站
  • 建设工程合同的分类seo关键词怎么优化
  • 拼团做的比较好的网站angular2做的网站有
  • 合网站建设做网站平台接单