做了一点优化,实际测试效果提升不是非常大,约8%左右的提升#463
做了一点优化,实际测试效果提升不是非常大,约8%左右的提升#463sunvim wants to merge 13 commits intolesismal:masterfrom sunvim:master
Conversation
|
感谢发起PR! buffer pool 部分
分级buffer是不太适合http部分的,因为很多append,buffer append后size就改变了,很容易造成从小size的池子里拿出来、放回的时候到了大size的池子里,反倒导致复用率低。
这个的Put如果不是currentsize会重新分配并放回,重新分配完全是多余的,如果觉得size不适合直接就return了,应该是类似进程fork的 copy on write原则——真正用到的时候再分配、也就是说应该在Malloc的地方分配 这个RecordRead都有锁,高并发每次读完都RecordRead都有锁并且maybeResize里都有至少一次time.Since,这个也是比较浪费的。 而且,最重要的,这里传给OnData是读取到的size的部分,但是borrow、payback之间buffer size是不变的,而且我看好像只有engine设置poller读取时这个buffer用到这个、其他地方都没有用到,那其实size是一直不变的,没必要进行RecordRead相关的计算: 另外,我们无法预估任何时段的流量和内存状况,应用层自己做这些动态适配,我觉得不如就交给runtime,自己加的额外计算的方案往往能在定制的压测中有优势,在千变万化不可预测的现实中反倒可能是负优化,fasthttp里用的bytesbufferpool里的动态我个人也是觉得没太大必要的,所以也没有做类似的实现。 另外,整体上对于buffer pool,nbio都是支持可配置的,用户可以自定制、然后设置成自己想要的方案,比如http的部分用不按size对齐的,body部分用size对齐的。nbio默认使用同一个不按size对齐的是考虑更大复用率,如果用户想自己配置nbhttp.Engine.BodyAllocator就可以了。 |
taskpool这个实现竟然使用time sleep,这是非常不合理的:
与buffer pool类似,这些都是可配置项,nbio选择的实现方案是比较均衡的,如果有特殊需要,可以自己设置 nbhttp.Engine.Execute/ClientExecute 就好了 |
嗯,有道理! 但层级内存管理 不是这样的, 各种尺寸的池,比如 1K/2K/4K/8K/16K 各 64个, 正常的请求大概都在1K左右,那么自然使用1K的chunk 就多一些,以此类推,更合理的管理内存, 采用统一分配的确实现简单一些,但在小body请求很多的时候就太浪费内存了, 我认为是值得去优化的,NBIO这个库定位是 高性能,关键设施的,无论是计算资源还是存储资源抑或是IO资源 都值得精细化管理 不过有些地方确实还是需要持续优化的,最好能在无所的情况下实现 层级管理 |
|
另外,如果再发起PR,文件中请不要使用中文 |
|
这个PR整体上不会被合并,所以我先关闭了,如果需要讨论可以继续留言 |
okkk, 那就关了吧 |
只有不需要被append的buffer,可以使用这种分级的,因为get put是对应的相同的池。如果会被append,那就不可控了,每次请求的size不可控,上次put回来和下次get出去的顺序不可控,buffer基本就只朝着一个方向流动、就是从小size到大size的pool。 另外还有ws zero copy的,因为nbio epoll管理的conn,每个ws message解析出来后默认是协程池去异步执行的,这是可能上个message还没处理完,bytesCached被put回pool并且被别的conn拿到用于处理解析从poller的读buffer拷贝数据过来、然后脏内存了 |
分级buffer pool的管理本身不需要锁,就是[]sync.Pool,按照size对齐取index操作sync.Pool就可以了,剩下的都是sync.Pool自己内部的锁、这个避免不掉了 |
优化列表:
4.其他小细节
没有进行系统性测试, repo主有的话,请测试一下,有问题 请反馈!