暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TiDB 多Socket 服务器性能扩展问题分析-续

2021-10-21
194

作者:Hacker_URrvEGHH

原文来源:https://tidb.net/blog/fcbee15e

【是否原创】是\ 【首发渠道】TiDB 社区\ 【首发渠道链接】\ 【正文】

在上一篇TiDB 多Socket 服务器性能扩展问题分析中提到,我们通过Perf C2C工具分析,认为这个问题很可能是由于CPU Cache line的false share造成的。 并定位到对同一cache line上不同数据的读写冲突的函数分别是:\ runtime.heapBitsSetType\ runtime.(*mspan).sweep\ runtime.sweepone\ runtime.(*mheap).reclaim\ 但由于Perf C2C工具并不支持关联到Go代码的位置,因此我们还无法定位到发生冲突的对应的结构、变量定义。

最近,在工作中我们发现英特尔的性能分析神器vtune是可以支持go应用的。我们就使用vtune工具来进一步分析这个问题。我们首先使用vtune的hotspot分析功能来对TiDB进行的profiling。和之前Perf的结果略有区别,vTune给出最热点的函数是runtime.heapBitsForAddr,占比23.4%。不过由于这个函数是被runtime.heapBitsSetType调用的,所以算在runtime.heapBitsSetType中也没问题。热点函数如下面这张图所示:

hotspot

点击runtime.heapBitsForAddr,就可以关联到该函数对应的go源代码。特别强大的是,我们还能关联到这个函数对应的汇编代码。就像这张图:

source_code

由于在上一篇的分析中,我们借助perf c2c工具已经可以找到发生HITM时的代码地址。比如对runtime.heapBitsSetType函数来说,代码地址是0x10d786a。利用vtune的汇编代码视图,我们根据这个代码地址,就可以找到对应的汇编代码位置。比如,对于0x10d786a地址来说,就对应这样一条汇编指令。

image

在我们找到这条汇编指令后,vtune能够帮助我们找到这条汇编指令对应的go源代码,就是下面这行代码。

image

通过这个方法,我们可以分别找到:\ runtime.(*mspan).sweep函数中的代码是:\ “atomic.Xadd64(\&mheap_.pagesSwept, int64(s.npages))”,

runtime.sweepone函数对应的代码是\ “atomic.Xadduintptr(\&mheap_.reclaimCredit, npages)”,runtime.

(*mheap).relcaim函数对应的代码是\ “if atomic.Casuintptr(\&h.reclaimCredit, credit, credit-take) {”。

用这个办法,我们可以很容易地确定cache line假共享和mheap结构中的pagesSwept、reclaimCredit以及arenas变量有关。如果,假设pagesSwept在cache line中的offset是0x00的话,则reclaimCredit位于0x30,arenas位于0x38。这刚好和上一篇中,Perf c2c工具输出发生HITM的cache line上的偏移对应。

mheap

到这里,我们比较确定地找到了TiDB在2路服务器上性能下降的根源在于Go中mheap结构的定义方式。一般解决cache line假共享问题的方法是在出现假共享的变量间增加一些padding,或改变变量的定义顺序,使发生冲突的变量分配到不同的Cache line上。

由于这个问题的根源是出现在go runtime中,我们向go社区提交了一个issuehttps://github.com/golang/go/issues/47831。让我们拭目以待这个问题的最终解决,以及TiDB最终能在2路的环境上获得多少的性能提升。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论