【是否原创】是
【首发渠道】TiDB 社区
【首发渠道链接】其他平台首发请附上对应链接
【目录】
【正文】
在之前一篇TiDB 性能优化实践中提到,TiDB的性能可以通过绑定NUMA的方式提升性能。同时,通过分析,发现Go运行时中的runtime.heapBitsSetType函数可能是影响TiDB在多Socket服务器环境提升性能的主要原因。在这一篇,我们将使用Perf c2c工具进行进一步的分析。
按照我们过去的经验,CPU Cache line上的读写访问冲突,特别是Cache line假共享问题,是许多应用程序在多核尤其是多Socket服务器上性能扩展不佳的一个典型原因。针对这类问题,perf c2c工具可以帮助进行分析。
使用perf c2c工具,我们首先获得一个出现HITM的地址从多到少的列表,是下面这样子滴:
然后,我们具体分析列表中的第一行数据,即地址0x57ae900所在cache line上的读写访问冲突,如下图所示。可以看出大约90%的Remote HITM都和函数runtime.heapBitsSetType有关。而导致它出现HITM原因,是由于函数runtime.(*mspan).sweep、runtime.sweepone和函数runtime.(*mheap).reclaim对该cache line的写操作造成的。而从CL off上看,读、写操作访问的偏移地址并不一样,说明这很有可能是一个cache line的假共享访问问题。那么通过改变相关的数据定义,使热点的读、写数据分别放在两个cache line上,是有可能解决这个问题的。
遗憾的是,perf工具对go程序的支持还不完善,不能像对c语言程序那样得到访问该cache line的具体代码位置。我们对go语言的只是也很有限。不知道这个问题是Go程序的一个已知共有问题,还是和TiDB的某种具体实现有关。如果社区里的同学知道如何通过代码地址关联到go源代码的位置,欢迎在评论区留言,一起来分析和解决这个问题!