保健励志美文体育育儿作文
投稿投诉
作文动态
热点娱乐
育儿情感
教程科技
体育养生
教案探索
美文旅游
财经日志
励志范文
论文时尚
保健游戏
护肤业界

高性能框架都会复用对象,它做到了开箱即用

  之前的文章httprouter路由框架为什么高性能提到过一点高性能的原因就是它减少了内存分配。因为分配内存是在堆上分配的,调用mallocgc函数,是有性能消耗的。
  而httprouter中使用sync。pool来减少内存分配,减少GC消耗。
  那么sync。Pool为什么能做到这一点?做出来哪些减少性能消耗的工作?一、初识sync。Pool
  sync。Pool是一组可以单独保存和检索的临时对象。存储在Pool中的任意对象可能会自动删除,这个删除过程是不会通知到用户的。
  Pool的目的是缓存已分配但没有使用的对象以供之后复用,减轻垃圾回收的压力。而Pool是并发安全的,也就是说,它可以轻松构建高效、线程安全的存储池。
  一个例子就是在fmt包中,Pool维护了一个动态大小的临时输出缓冲区存储,存储在负载的时候扩展(多goroutine打印),在静止时缩小。二、使用方法bufferpool:sync。Pool{New:func()interface{}{println(Createnewinstance)returnstruct{}{}},}buffer:bufferpool。Get()bufferpool。Put(buffer)
  首先初始化Pool,声明一个创建Pool元素的方法。
  然后当使用时申请对象,Get方法会返回Pool已经存在的对象,如果没有,就走New方法来初始化一个对象。
  当使用完成后,调用Put方法把对象放回Pool中。
  Pool就3个接口,针对所有的对象类型都可以使用。
  那么我们来思考一个问题,使用sync。Pool有什么好处?
  下面我们来看一个例子varcountint32funcnewBuffer()interface{}{atomic。AddInt32(count,1)buffer:make(〔〕byte,1024)returnbuffer}funcmain(){bufferPool:sync。Pool{New:newBuffer,}workers:10241024varwgsync。WaitGroupfori:0;iworkers;i{wg。Add(1)gofunc(){deferwg。Done()buffer:bufferPool。Get()buffer。(〔〕byte)deferbufferPool。Put(buffer)}()}wg。Wait()fmt。Printf(dbuffercreated,count)}
  最终打印结果11buffercreated10buffercreated
  多次运行可能会出现不同的结果,但是次数count都不大。如果不是使用Pool来申请,而是直接使用buffer:make(〔〕byte,1024)来申请内存,那么就会申请10241024个对象,造成极大的浪费。而Pool就是对这类对象的复用。三、原理
  既然已经知道了复用对象的好处,那么sync。Pool到底是如何实现这一功能的呢?
  首先我们来看看Pool的结构typePoolstruct{noCopynoCopylocalunsafe。PointerlocalSizeuintptrvictimunsafe。PointervictimSizeuintptrNewfunc()interface{}}nocopy就是标识不能拷贝,具体原理在读写锁时提到localSize就是cpu处理器的个数,local指向了〔localSize〕poolLocalvictim和victimSize就是在GC后接管local和localSizeNew函数就是初始化对象的方法
  poolLocal管理Pool池里的cache元素的关键结构typepoolLocalInternalstruct{privateinterface{}sharedpoolChain}typepoolLocalstruct{poolLocalInternalpad〔128unsafe。Sizeof(poolLocalInternal{})128〕byte}private就是声明的对象shared是双链表结构,用于挂载cache元素pad就是用来填充字符到128字节,用于内存对齐1、获取对象1。1、获取本地pooll,pidp。pin()
  这个pin函数hold住了当前goroutine在P上,不允许调度,并且返回P的本地pool和P的id。func(pPool)pin()(poolLocal,int){pid:runtimeprocPin()s:atomic。LoadUintptr(p。localSize)l:p。localifuintptr(pid)s{returnindexLocal(l,pid),pid}returnp。pinSlow()}
  这个indexLocal其实就是个索引到本地pool的指针funcindexLocal(lunsafe。Pointer,iint)poolLocal{lp:unsafe。Pointer(uintptr(l)uintptr(i)unsafe。Sizeof(poolLocal{}))return(poolLocal)(lp)}
  通常只有第一次执行的时候,p。localSize为0,才会执行p。pinSlow,其他都直接走if返回本地pool了。
  pinSlow就是把Pool注册进allPools数组中func(pPool)pinSlow()(poolLocal,int){runtimeprocUnpin()allPoolsMu。Lock()deferallPoolsMu。Unlock()pid:runtimeprocPin()s:p。localSizel:p。localifuintptr(pid)s{returnindexLocal(l,pid),pid}ifp。localnil{allPoolsappend(allPools,p)}size:runtime。GOMAXPROCS(0)local:make(〔〕poolLocal,size)atomic。StorePointer(p。local,unsafe。Pointer(local〔0〕))atomic。StoreUintptr(p。localSize,uintptr(size))returnlocal〔pid〕,pid}
  首先先解锁,然后加全局互斥锁var(allPoolsMuMutexallPools〔〕PoololdPools〔〕Pool)
  allPools就是全局的pool,oldPool就是victim使用的pool。
  然后再重新hold住goroutine在P上,二次判断是否直接返回本地pool。
  而使用runtime。GOMAXPROCS(0)来获取cpu的数量,也就是P的数量。
  这里深入扩展一下,runtimeprocPin其实是runtime包下的procPin的一层封装。funcprocPin()int{g:getg()mp:g。mmp。locksreturnint(mp。p。ptr()。id)}
  procPin的目的就是为了当前G被抢占了执行权限,也就是说G在M上不走了,而实际核心是mp。locks,在newstack函数里,有这么段代码ifpreempt{if!canPreemptM(thisg。m){gp。stackguard0gp。stack。loStackGuardgogo(gp。sched)}}funccanPreemptM(mpm)bool{returnmp。locks0mp。mallocing0mp。preemptoffmp。p。ptr()。statusPrunning}
  这里mp。locks0,所以就只能让G一直执行
  而runtimeprocUnpin函数可以猜想的到,就是让mp。lock。1。2、取出对象x:l。privatel。privatenilifxnil{x,l。shared。popHead()ifxnil{xp。getSlow(pid)}}
  从private中取出对象,如果取出的对象为nil,那么就尝试从share队列中获取,如果还是nil,就从其他P的队列中取,或者从victim中取。func(pPool)getSlow(pidint)interface{}{size:atomic。LoadUintptr(p。localSize)locals:p。local从其他P中取fori:0;iint(size);i{l:indexLocal(locals,(pidi1)int(size))ifx,:l。shared。popTail();x!nil{returnx}}从victim中取sizeatomic。LoadUintptr(p。victimSize)ifuintptr(pid)size{returnnil}localsp。victiml:indexLocal(locals,pid)ifx:l。private;x!nil{l。privatenilreturnx}fori:0;iint(size);i{l:indexLocal(locals,(pidi)int(size))ifx,:l。shared。popTail();x!nil{returnx}}atomic。StoreUintptr(p。victimSize,0)returnnil}1。3、初始化对象
  如果上面几个地方都不存在该对象,那么就调用New函数初始化一个对象返回ifxnilp。New!nil{xp。New()}returnx2、放回对象2。1、空值判断ifxnil{return}2。2、获取本地pooll,:p。pin()2。3、尝试存放数据ifl。privatenil{l。privatexxnil}ifx!nil{放到双向链表l。shared。pushHead(x)}3、victim
  看到这里,可能就有点疑惑了,Pool就这两个方法,也没有用到victim。
  这个奥秘就在于它注册了init函数,在每次GC的时候调用poolCleanup函数,也就是说每一轮GC都会对所有的Pool做清理工作。funcinit(){runtimeregisterPoolCleanup(poolCleanup)}
  而poolCleanup函数就是做pool的迁移funcpoolCleanup(){for,p:rangeoldPools{p。victimnilp。victimSize0}for,p:rangeallPools{p。victimp。localp。victimSizep。localSizep。localnilp。localSize0}oldPools,allPoolsallPools,nil}四、总结
  1、sync。Pool是并发安全的,读取数据时会hold住当前的goroutine不被打断
  2、sync。Pool不允许复制后使用,因为nocopy
  3、sync。Pool不适用于socket长连接或连接池等,因为无法知道连接池的个数,连接池的元素随时可能会被释放。
  4、从sync。Pool取出的对象使用完需要放回池中。

苹果手机2022年05月15日新消息苹果手机苹果手机2022年05月15日新消息苹果抛弃Lightning接口将转用USBC2022年京东618苹果手机预估价会是多少?苹果市场份额首……我的外婆的小学三年级作文我的外婆的小学三年级作文1我的外婆外婆最喜欢我了,经常给我织毛衣。这不,今天她又帮我缝起衣服来了,可是,她拿着针,用线对准针孔,却怎么也穿不进去,正发愁呢!这时,我……精选感谢朋友的的作文400字三篇在日常学习、工作或生活中,大家都尝试过写作文吧,作文根据写作时限的不同可以分为限时作文和非限时作文。你写作文时总是无从下笔?下面是小编为大家整理的感谢朋友的的作文400字4篇,……我喜欢的中秋节作文600字篇一:我最喜爱的中秋节又到了,这一天里,人们需要吃月饼和赏月来庆祝中秋节。中秋节的一大早,我就起来了,为什么呢?当然是庆祝中秋节了。起来后,我就匆匆忙忙地下楼,去找……中学生快乐的元旦节作文800字【第一篇】十二月三十一日,我们举行了一年一度的元旦联欢会。在13:40的时候,我们便开始入座了。我们的座位,用桌子排成了U字形,U字形桌子开口的地方,就是舞台了。在……我的读书记四年级作文最近我在阅读一本书《查理九世》,这本书很火,很多人都在看,作者雷欧幻想把内容写得非常精彩,所以我一直在收集《查理九世》这个本书。有一次,我去新华书店,我跨进书店大门那里的……小溪流的旅行五年级作文春天终于来了,我又可以从这暗无天日,与世隔绝的鬼地方出去旅行了。小溪揉了揉他蒙眬的睡眼,说道。之后,小溪流又慢慢地探出头来,他看见了在青草地上玩耍的孩子们,拿着泡泡枪到处喷泡泡……美丽的石门瀑布作文无论是身处学校还是步入社会,说到作文,大家肯定都不陌生吧,作文是从内部言语向外部言语的过渡,即从经过压缩的简要的、自己能明白的语言,向开展的、具有规范语法结构的、能为他人所理解……关于小学生写考试的作文500字汇编8篇在日常生活或是工作学习中,许多人都写过作文吧,作文是人们把记忆中所存储的有关知识、经验和思想用书面形式表达出来的记叙方式。那么,怎么去写作文呢?以下是小编整理的小学生写考试的作……我的新年愿望二年级作文600字现在,正月十五已经过去。也就是说新年的气氛已经结束。大家都进入新的一年:20xx年。现在可以说20xx年已经离我们而去。在新的一年中,大家都肯定有很多的祝福和愿望。我也不……猪八戒的水果店自从猪八戒成了佛后,只知道吃、喝、玩、乐。不久,就从亿万富翁变成了一贫如洗的穷光蛋。猪八戒气的五官变形,现在只剩下一个西瓜和两张白金卡,怎么办呢?情急之下,他马上驾着保存已久的……父爱无言当叛逆之神降临时,我不再乖巧地讨爸妈欢心。总是觉得自己已经长大,不再需要陈词滥调似的叮呤和唠叨。喜欢上奇装异服,喜欢上顶嘴,家里得气氛有些凝重。回想起来,我似乎要走上一条错路了……
移为通信2021年净利1。56亿同比增长71。94董事长廖荣挖贝网4月13日,移为通信(300590)近日发布2021年度报告,报告期内公司实现营业收入920,739,607。53元,同比增长94。79;归属于上市公司股东的净利润155……看菊花展作文600字我细细地观察着,发现它们的姿态各不相同,有的花花瓣缩起,如同一个个小球。下面是小编整理的作文,欢迎查阅。篇一:参观菊花展阳光明媚,天高云淡,凉爽的秋风微微地吹着,空气中弥……关于父爱750字作文时钟滴滴答答地走着,我知道那是他的生命在流淌。爸爸咳嗽了两声,沙哑着喉咙叫我去读书。你上个学期英语成绩落下了很多,快去读书爸爸断断续续地说。爸爸因为工作劳累,……接口自动化测试工具seldom分享在编写接口用例的过程中,针对一个接口,往往只是参数不同,那么参数化就非常有必要了。seldom中参数化的用法非常灵活,这里仅介绍filedata()的N种玩法。二维列表……国家邮政局要求快递业保通保畅4月初网购的商品至今未收到、卡在发货地半个月后自动取消订单记者注意到,目前全国有不少区域遭遇快递物流不畅通的问题,打开电商平台,几乎各大店铺都标注着受疫情影响,商品送达可能延时……有关信心责任友情的作文品鉴历史,回味生活,我们深切可以感受到,无论是祖辈,还是现在,人们之间拥有许许多多美好的品质与情感,信心、责任、友情就是其中最绚丽光彩,值得赞美,也渴望拥有。时光倒流,来……工信部建立不良APP安全监测处置技术能力中新经纬4月14日电国新办14日就打击治理电信网络诈骗犯罪工作进展情况举行发布会。对于过度收集个人信息的监管问题,工信部网络安全管理局局长隋静明确了四点。有媒体问:个人信……创新高!高新区22项成果荣获河北省科学技术奖4月12日上午,河北省科学技术奖励大会在石家庄召开,会上对2021年度河北省科学技术奖的获奖项目及个人进行了表彰和奖励。高新区企业共22个项目在本次奖励大会上获奖,其中,石药控……中华美德ldquo;中华美德rdquo;,一个人人皆知的词汇。每一个人都在提倡:争做美德少年,争做美德市民,但是在我们的生活中,又有谁能够毫无疑问的做到了?我国的传统美德很多,在……我喜欢大熊猫的作文600字大熊猫,体色为黑白两色,它有着圆圆的脸颊,大大的黑眼圈,胖嘟嘟的身体,标志性的内八字的行走方式,也有解剖刀般锋利的爪子。是世界上最可爱的动物之一。下面我们用自己的角度来描写一下……观日出的作文900字睁开惺忪的睡眼,望着窗外灰蒙蒙的天空,太阳公公似乎尚未起床,冷清的窗外带有几分宁静,大地上的人们彷佛还沉浸在甜美的梦乡,我不禁打了一个冷颤,山上冰冷的空气直逼我的每一吋肌肤,妈……巴学园,我梦中的天堂品学网专稿未经允许不得转载快乐的暑假生活就这样结束了,我马上就要成为一名三年级的小学生了!昨天有幸读了日本着名作家黑柳彻子写的《窗边的小豆豆》一书,感触很深!这本书是作者……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网