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

网站建设电销照片一键生成视频的软件

网站建设电销,照片一键生成视频的软件,24小时免费资源在线观看,营销软文推广平台最近学习golang的时候,看到golang并发编程中有一个sync.pool,即对象池,猛地一看这不跟linux的slab分配器类似嘛,赶紧学习记录下 这里先总结下设计sync.pool和slab的目的 sync.pool 为了缓解特定类型的对象频繁创建和销毁&#x…

最近学习golang的时候,看到golang并发编程中有一个sync.pool,即对象池,猛地一看这不跟linux的slab分配器类似嘛,赶紧学习记录下

这里先总结下设计sync.pool和slab的目的

  • sync.pool
    • 为了缓解特定类型的对象频繁创建和销毁,导致gc压力大的问题
  • slab
    • linux使用伙伴系统管理内存,伙伴系统分配内存时以页Page(4K byte)为单位进行分配,而linux内核中,会频繁的创建struct page, struct fd,struct task的实例,这些结构体对象的size通常只有几十个字节,如果每次都从伙伴系统分配内存,将造成极大的内存浪费

sync.pool

参考了:

基本用法:https://geektutu.com/post/hpg-sync-pool.html

基本用法+源码分析:https://www.cnblogs.com/qcrao-2018/p/12736031.html

底层分析更全面:https://www.cyhone.com/articles/think-in-sync-pool/

sync.pool的特点

并发安全并且lock-free,sync.pool之所以能做到lock-free,跟golang的GMP调度模型有关系,下面再进行详细介绍

sync.pool的使用场景

当存在对象被频繁的重复分配时,可以使用sync.pool避免对象重复创建和销毁,减轻gc的压力

sync.pool的基本用法

创建对象池

var studentPool = sync.Pool{New: func() interface{} { return new(Student) },
}

理解:创建一个sync.pool对象,命名为studentPool,创建sync.pool对象时,传入的New成员是一个函数,该函数定义了创建student对象的行为。需要注意的是,sync.pool在初始化时只会创建一个对象,后续调用Get发现没有对象时,才会继续创建对象

向对象池添加/获取一个对象

stu := studentPool.Get().(*Student)
json.Unmarshal(buf, stu)
studentPool.Put(stu)

完整的例子

package mainimport ("fmt""sync"
)var pool *sync.Pooltype Person struct {Name string
}func initPool() {pool = &sync.Pool{New: func() interface{} {fmt.Println("Creating a new Person")return new(Person)},}
}func main() {initPool()p := pool.Get().(*Person)fmt.Println("首次从 pool 里获取:", p)p.Name = "first"fmt.Printf("设置 p.Name = %s\n", p.Name)pool.Put(p)fmt.Println("p.name:", p.Name) // p仍然有效p1 := pool.Get().(*Person)fmt.Println("p1.name:", p1.Name)fmt.Println("Pool 没有对象了,调用 Get: ", pool.Get().(*Person))
}

输出

Creating a new Person
首次从 pool 里获取: &{}
设置 p.Name = first
p.name: first
p1.name: first
Creating a new Person
Pool 没有对象了,调用 Get:  &{}

从这个例子可以看出,当p被存入pool后,p仍然是有效的,并且p的字段并没有因为p存入pool而被清空

sync.pool底层实现

sync.pool结构体

type Pool struct {noCopy noCopy// 每个 P 的本地队列,实际类型为 [P]poolLocallocal     unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal// [P]poolLocal的大小localSize uintptr        // size of the local arrayvictim     unsafe.Pointer // local from previous cyclevictimSize uintptr        // size of victims array// 自定义的对象创建回调函数,当 pool 中无可用对象时会调用此函数New func() interface{}
}

上文提到,sync.pool是lock-free的,关键就在于这里的local是一个[GOMAXPROCS]poolLocal数组,由于每个 P 都有自己的一个本地对象池 poolLocal,Get 和 Put 操作都会优先存取本地对象池。由于 P 的特性,操作本地对象池的时候整个并发问题就简化了很多,可以尽量避免并发冲突

poolLocal定义如下

type poolLocal struct {poolLocalInternal// 将 poolLocal 补齐至两个缓存行的倍数,防止 false sharing,// 每个缓存行具有 64 bytes,即 512 bit// 目前我们的处理器一般拥有 32 * 1024 / 64 = 512 条缓存行// 伪共享,仅占位用,防止在 cache line 上分配多个 poolLocalInternalpad [128 - unsafe.Sizeof(poolLocalInternal{})%128]byte
}// Local per-P Pool appendix.
type poolLocalInternal struct {// P 的私有缓存区,使用时无需要加锁private interface{}// 公共缓存区。本地 P 可以 pushHead/popHead;其他 P 则只能 popTailshared  poolChain
}

poolChain 是一个双端队列的实现

type poolChain struct {// 只有生产者会 push to,不用加锁(Get不会触发对象窃取)head *poolChainElt// 读写需要原子控制。 pop fromtail *poolChainElt
}type poolChainElt struct {poolDequeue// next 被 producer 写,consumer 读。所以只会从 nil 变成 non-nil// prev 被 consumer 写,producer 读。所以只会从 non-nil 变成 nilnext, prev *poolChainElt
}type poolDequeue struct {// The head index is stored in the most-significant bits so// that we can atomically add to it and the overflow is// harmless.// headTail 包含一个 32 位的 head 和一个 32 位的 tail 指针。这两个值都和 len(vals)-1 取模过。// tail 是队列中最老的数据,head 指向下一个将要填充的 slot// slots 的有效范围是 [tail, head),由 consumers 持有。headTail uint64// vals 是一个存储 interface{} 的环形队列,它的 size 必须是 2 的幂// 如果 slot 为空,则 vals[i].typ 为空;否则,非空。// 一个 slot 在这时宣告无效:tail 不指向它了,vals[i].typ 为 nil// 由 consumer 设置成 nil,由 producer 读vals []eface
}

sync.pool Get接口调用时,可能会触发对象窃取,poolDeque可能被多个P访问,sync.pool内部使用CAS原子操作保证并发安全性

slab分配器

参考:https://segmentfault.com/a/1190000043626203

为什么需要slab分配器

linux伙伴系统管理内存的最小单位是物理内存页page,如果为几十个或者几百个字节的分配请求分配一整个页,将造成大量内存

slab分配器在内核代码中使用

对于用户空间,glibc的malloc内部维护一个空闲链表

使用slab分配器的好处

缓存友好

利用 CPU 高速缓存提高访问速度。当一个对象被直接释放回 slab 对象池中的时候,这个内核对象还是“热的”,仍然会驻留在 CPU 高速缓存中。如果这时,内核继续向 slab 对象池申请对象,slab 对象池会优先把这个刚刚释放 “热的” 对象分配给内核使用,因为对象很大概率仍然驻留在 CPU 高速缓存中,所以内核访问起来速度会更快

弥补伙伴系统调用路径长和只能按照整个物理页分配的缺点

伙伴系统只能分配 2 的次幂个完整的物理内存页,这会引起占用高速缓存以及 TLB 的空间较大,导致一些不重要的数据驻留在 CPU 高速缓存中占用宝贵的缓存空间,而重要的数据却被置换到内存中。 slab 对象池针对小内存分配场景,可以有效的避免这一点

slab分配器使用场景

主要是分配如下结构体对象的场景

  • struct task_struct

  • struct mm_struct

  • struct fd

  • struct page

  • struct socket

对于每种结构体,内核会创建一个专属的slab分配器

slab底层原理

暂时只需要了解slab是什么,和slab的基本概念。前面的区域,后面再探索吧~


文章转载自:

http://6OT8FqoJ.yqhdy.cn
http://yddFA50M.yqhdy.cn
http://LBwWZsUo.yqhdy.cn
http://31vsI1IA.yqhdy.cn
http://YqU2XJOF.yqhdy.cn
http://CBGnvtAU.yqhdy.cn
http://Uy6QyfDt.yqhdy.cn
http://0zmMjANp.yqhdy.cn
http://X2rSi9Lh.yqhdy.cn
http://1FcECOrT.yqhdy.cn
http://eE60ZlU0.yqhdy.cn
http://WNuGcHbJ.yqhdy.cn
http://yUlFuwXQ.yqhdy.cn
http://vmcSqbOW.yqhdy.cn
http://CrXogaNj.yqhdy.cn
http://DNgw2t1W.yqhdy.cn
http://KH5SHq7U.yqhdy.cn
http://n98phpaS.yqhdy.cn
http://Gppki0iX.yqhdy.cn
http://jTUHXrJf.yqhdy.cn
http://a7FatEkw.yqhdy.cn
http://t1ro4VHZ.yqhdy.cn
http://yNjTj08f.yqhdy.cn
http://mSXQ9sPE.yqhdy.cn
http://VzhD0qk3.yqhdy.cn
http://5mSED9lG.yqhdy.cn
http://IoacQKa5.yqhdy.cn
http://hNoiWV6V.yqhdy.cn
http://20OB4pbv.yqhdy.cn
http://G7Wrtusx.yqhdy.cn
http://www.dtcms.com/wzjs/657190.html

相关文章:

  • 营销型企业网站分析与诊断的步骤wordpress 多站点错误
  • 海南住房和城乡建设厅网站首页广州免费钓鱼地点50个
  • vps做网站的环境app系统开发费用
  • 网站没有域名永康建设局网站
  • 深圳便宜做网站织梦后台做的网站怎么绑定域名
  • 网站英文版是怎么做的好的h5制作网站模板
  • 网站建设托管公司苏宁易购网站建设的思路
  • vi设计基础部分都有哪些郑州seo团队
  • 广州网站推广公司哪个网站有做阿里巴巴流量
  • 漂亮的数据型网站备案信息在哪里查
  • 互联网网站制作公司哪家好万网域名指向网站
  • 高端网站建设公司大于二高端网站建设
  • 网站建设税收编码广州制作外贸网站公司简介
  • 宣讲家网站美丽乡村建设大连哪家公司做网站好
  • 旅游网站开发报价单怎样开发公司的网站建设
  • 做网站优化哪家好网架公司的螺丝是不是公司安好
  • 局域网建网站的详细步骤如何自建公司网站
  • 常德市做网站联系电话微信软件如何开发
  • 做的不好的网站网站开发流程人物
  • 免费的黄冈网站有哪些平台可以用微信支付远象建设 网站
  • 什么网站可以做软件有哪些内容百度网站服务器
  • 吉林网站建设公司新织梦官网
  • 买域名后 怎么做网站wordpress管理员登陆不上
  • 物流网站开发项目书住房和城乡建设部网站建筑电工
  • 网站建设公司怎么找业务动漫设计与制作难吗
  • 品划做网站网站后台网址在哪输入
  • 网站建设需要具备哪些知识五屏网站建设哪家有
  • 穿衣搭配的网站如何做如何把网站一个栏目做301跳转
  • 网站下载链接打不开以下哪个选项不属于网络营销的特点
  • 线上做图的网站怎样把网站上传到服务器上