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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高性能框架都会复用对象,它做到了开箱即用相关的知识,希望对你有一定的参考价值。

参考技术A 之前的文章httprouter路由框架为什么高性能提到过一点高性能的原因就是它减少了内存分配。因为分配内存是在堆上分配的,调用mallocgc函数,是有性能消耗的。

而httprouter中使用sync.pool来减少内存分配,减少GC消耗。

那么sync.Pool为什么能做到这一点?做出来哪些减少性能消耗的工作?

sync.Pool是一组可以单独保存和检索的临时对象。存储在Pool中的任意对象可能会自动删除,这个删除过程是不会通知到用户的。

Pool的目的是缓存已分配但没有使用的对象以供之后复用,减轻垃圾回收的压力。而Pool是并发安全的,也就是说,它可以轻松构建高效、线程安全的存储池。

一个例子就是在fmt包中,Pool维护了一个动态大小的临时输出缓冲区存储,存储在负载的时候扩展(多goroutine打印),在静止时缩小。

然后当使用时申请对象,Get方法会返回Pool已经存在的对象,如果没有,就走New方法来初始化一个对象。

当使用完成后,调用Put方法把对象放回Pool中。

Pool就3个接口,针对所有的对象类型都可以使用。

那么我们来思考一个问题,使用sync.Pool有什么好处?

下面我们来看一个例子

最终打印结果

多次运行可能会出现不同的结果,但是次数count都不大。如果不是使用Pool来申请,而是直接使用buffer := make([]byte, 1024)来申请内存,那么就会申请 1024 * 1024 个对象,造成极大的浪费。而Pool就是对这类对象的复用。

既然已经知道了复用对象的好处,那么sync.Pool到底是如何实现这一功能的呢?

首先我们来看看Pool的结构

poolLocal管理Pool池里的cache元素的关键结构

这个pin函数hold住了当前goroutine在P上,不允许调度,并且返回P的本地pool和P的id。

这个indexLocal其实就是个索引到本地pool的指针

通常只有第一次执行的时候,p.localSize为0,才会执行p.pinSlow,其他都直接走if返回本地pool了。

pinSlow就是把Pool注册进allPools数组中

首先先解锁,然后加全局互斥锁

allPools就是全局的pool,oldPool就是victim使用的pool。

然后再重新hold住goroutine在P上,二次判断是否直接返回本地pool。

而使用runtime.GOMAXPROCS(0)来获取cpu的数量,也就是P的数量。

这里深入扩展一下,runtime_procPin其实是runtime包下的procPin的一层封装。

procPin的目的就是为了当前G被抢占了执行权限,也就是说G在M上不走了,而实际核心是mp.locks++,在newstack函数里,有这么段代码

这里mp.locks>0,所以就只能让G一直执行

而runtime_procUnpin函数可以猜想的到,就是让mp.lock--。

从private中取出对象,如果取出的对象为nil,那么就尝试从share队列中获取,如果还是nil,就从其他P的队列中取,或者从victim中取。

如果上面几个地方都不存在该对象,那么就调用New函数初始化一个对象返回

看到这里,可能就有点疑惑了,Pool就这两个方法,也没有用到victim。

这个奥秘就在于它注册了init函数,在每次GC的时候调用poolCleanup函数,也就是说每一轮GC都会对所有的Pool做清理工作。

而poolCleanup函数就是做pool的迁移

1、sync.Pool是并发安全的,读取数据时会hold住当前的goroutine不被打断

2、sync.Pool不允许复制后使用,因为nocopy

3、sync.Pool不适用于socket长连接或连接池等,因为无法知道连接池的个数,连接池的元素随时可能会被释放。

4、从sync.Pool取出的对象使用完需要放回池中。

快速高性能的开箱即用系统:Clear Linux

英特尔推出Clear Linux项目的目标是让用户可以充分利用虚拟机的隔离技术以及容器的部署优势,Clear Linux不管是在启动速度还是内存消耗方面都不逊于容器,据知情人透露,Clear Linux目前还处于试验阶段,接下来会支持AppC以及Docker。然而经过这么长时间的等待,我们得到了一些消息:通过Ubuntu、OpenSUSE、Debian、Clear Linux、Fedora、Antergos和CentOS最新稳定版本和滚动更新版本系统的基准测试显示,英特尔的发行版Clear Linux为用户提供了最快的开箱即用性能。
技术图片
Clear Linux是一个滚动更新发行版,最新版本号是5700,它主要专注于容器和云端。相比于其它发行版,它采用了最具进取性的优化策略以提供最快的性能,它默认启用了许多编译器优化,如支持Function Multiversioning,运行时根据CPU类型自动选择最正确的架构特定代码版本,其它发行版也可以进行调整以提供更高的性能,但Clear Linux提供了最快的开箱即用性能。

 

本文转自:https://www.linuxprobe.com/high-performance-out-of-the-box-system-clear-linux.html

以上是关于高性能框架都会复用对象,它做到了开箱即用的主要内容,如果未能解决你的问题,请参考以下文章

快速高性能的开箱即用系统:Clear Linux

迷你avalonjs框架

聊聊Netty那些事儿之从内核角度看IO模型

聊聊Netty那些事儿之从内核角度看IO模型

Apache SkyWalking 为.NET Core带来开箱即用的分布式追踪和应用性能监控

腾讯 JDK 11 正式开源,高性能太牛逼啦!