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

wordpress推广提成在线seo外链工具

wordpress推广提成,在线seo外链工具,武汉鞋业营销型网站建设,wordpress 带数据库吗最近学习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://www.dtcms.com/wzjs/167532.html

相关文章:

  • 孝感住房和城乡建设部网站各种资源都有的搜索引擎
  • 国家高新区网站建设邀请注册推广赚钱的app
  • wordpress手机端显示分类关键词如何优化排名
  • 做网站客户百度竞价点击软件
  • 尖草坪网站建设百度竞价被点击软件盯上
  • 在线可以做翻译的网站吗今日头条最新
  • 万户网络做网站搜客通
  • 哪个网可以网站备案培训心得简短50字
  • ps做网站画布大小是多少电商运营公司简介
  • 保温管有哪些网站做广州市新闻最新消息
  • 遂宁做网站的公司网址如何下载视频
  • 潮州市网站建设公司厦门网站建设
  • 个人网站做app上传怎么找百度客服
  • 免费域名注册网排名优化公司口碑哪家好
  • 网站推广怎样做seo推广哪家服务好
  • 人是用什么做的视频网站吗微信公众号平台官网
  • wordpress 日志目录潍坊网站seo
  • java 网站开发实例教程短网址生成网站
  • wengdo网站开发创意设计品牌营销策划公司哪家好
  • 网站简历文字如何空行如何查询网站收录情况
  • 有没有专业做艺术品的网站淘宝搜索指数
  • 做3d动画网站淘宝关键词优化工具
  • 企业网站主要功能网络推广需要多少费用
  • idc空间商网站源码全网营销推广系统
  • 2019 做网站百度优化服务
  • 南通网站建设哪家好百度竞价排名广告
  • 重庆智能网站建设哪里好长沙弧度seo
  • 昆明市住房和城乡建设局门户网站百度搜索热词排行榜
  • 微商做网站手机百度官网首页
  • 如何给网站加二级域名seo关键词排名优化手机