Ceph H版本性能调优总结




现状

sas 场景

sas盘场景下,由于有raid卡的缓存加成,以及journal的顺序写特性,因此性能比sas裸盘要好很多,单osd单副本场景下数据(未调优):

经过配置项调整后,同样的测试用例和单osd节点,iops从600多提升到1010左右。调整的配置项是:

但此时内存占用会暴涨,原因是后端data落盘跟不上journal落盘速度,大量op保存在内存中排队。

而裸盘的fio数据:

因此sas盘场景没有仔细调优,主要是在ssd场景下进行的各种对比测试。

需要注意的是,throttle放开的参数在sas场景下不能放开,否则会导致内存暴涨(sas盘性能跟不上,不需要设置太高的throttle)。

ssd 场景

9台物理机(近期上线的机器,cpu应该稍好),每台20个ssd盘(Intel S4500),4k随机写fio+rbd模式下,9个卷(每个500G)可以并发跑到72000个IOPS左右。

fio测试过程中性能稳定无波动,osd后端磁盘IO压力均衡,每个osd均在2000~4000iops范围波动。

同样的9台物理机,每台3个ssd盘(Intel S4500),跑4k随机写裸盘fio+libaio,每个节点可以达到15W iops。

而在线下环境的pubt2-ceph0/1/2 3台节点上(E5-2660 v4 2.0GHz,两个节点ssd盘是SAMSUNG MZ7LM960HMJP,PM863a,官方标称随机写24K IOPS;另外一台是INTEL SSDSC2BB016T7,S3520,官方标称随机写17K IOPS),用线上环境试用的1.2-0版本进行对比测试,配置项使用线上的,无绑核,fio跑在独立的节点上。4k随机写总体iops性能为30652,平均单卷3405:

分析过程及优化手段

注意:下面的分析及优化都是针对的ssd盘场景。

整个分析过程主要依赖的手段包括:
1. perf counter,增加自定义counter
2. 日志,添加耗时统计
3. kill -USR1,获取调用栈
4. Linux perf工具,查看cpu资源占用情况
5. 修改代码,增加io落盘开关,做到无io落盘情况下分析osd层性能,排除磁盘对性能数据的影响

其他期望尝试的工具是lttng+blkin,但H版本这个感觉做的不完善,代码里很多地方都没有打点,后续L版本可以尝试。

单osd性能分析

首先要分析的是单osd、单副本场景下的rbd卷4k随机写性能,分析的是有io落盘和无io落盘两种情况下的性能差距,并找出无io落盘情况下osd层的性能瓶颈点。

9个卷,(4k随机写,128iodepth),有IO落盘(未mock FileStore和journal),单卷性能:

9个卷,(4k随机写,128iodepth),无IO落盘(mock FileStore和journal),单卷性能:

可以看出无io落盘场景下,平均时延过高,因此通过dump_historic_ops分析时延较长的位置,

Filestore相关event影响排序,因此修改代码去掉了之后,

前半段在等待journal落盘,后半段是journal落盘之后等待回调。

但需要注意的是,history ops并不能完全表现真实性能瓶颈,只能作为参考,只有耗时最长的20个op才会列出来,是最大值,而非平均值。

官方代码已有的perf平均值数据如下:

可以看出journal_latency平均值很低,才0.26ms,也就是说绝大部分情况下commit_queued_for_journal_write到journaled_completion_queued阶段都是不怎么耗时的,op_process_latency平均延时比较高。因此需要通过增加perf counter来对比验证瓶颈点。

通过增加perf counter,journal commit可以看出回调耗时较长:

当前finisher线程是1个,不能修改,之前正好看到社区代码有修改这部分,增加finisher回调线程数量,于是尝试合入进行对比(https://github.com/ceph/ceph/pull/6486/commits )。

增加finisher线程前(默认都是1个线程):

增加finisher线程后:

增加finisher线程数量后,队列中等待的op数量已经没有堆积,fio性能偶尔可以从原来的每个卷1200左右增加到1800左右,但更多时候是下降的,到800多,需要进一步分析原因。
说明还有其他地方有性能瓶颈。

统计perf counter耗时,发现提交journal之后到op_commit耗时仍然比较长(上面有之前的数据),当时没想到具体的瓶颈点,翻了社区提交的性能优化代码找到一个相关的改动,合入之后发现提升挺明显(https://github.com/ceph/ceph/commit/eb020b6a6a75c69f71dc29fd607a4626bed28366 ),单osd单副本9个卷无IO落盘,每个卷性能从1490提高到2200:

有IO落盘(从960提升到1490):

根据晨会上宏松的建议,看了下所有的pr,涉及到osd层、pg层、journal层、FileStore层的performance优化都过滤下,看看有么有可以拿过来的。找到一个https://github.com/ceph/ceph/commit/a75a9a8178f42ba7363de4929af5da140b64c668 ,合入后无IO落盘场景(其他条件同上),每个卷性能从2206提升到2320:

有IO落盘场景,从1490提升到1527:

其他的可以合入的patch也都合入测试了,发现并没有提升。

分析无IO落盘场景下的fio结果,发现时延还是比较高,平均55ms,于是通过kill -USR1看了下top里cpu占用最高的线程的调用栈(多kill几次),发现每次调用栈都是在打印日志,于是尝试把日志级别都改成0(主要是内存级别,因此文件级别已经是0了),

使用上面的脚本,关掉所有模块日志(包括内存日志)之后,性能有很大提升。

无IO落盘提升非常大(延时敏感,每个卷从2320提升到5718,翻1倍还要多):

有IO落盘,从1527提升到1770:

上述单osd场景下,也对比过64个pg和256个pg的性能,256 pg性能比64个要好一些,因此上述优化都是在256 pg场景下测试的。

单节点3 osd 3副本性能分析

使用上面修改过代码及配置项的版本部署3副本场景(共3个osd位于同一个节点上,排除网络影响),进行性能测试。

3副本(3个osd,在同一节点上),256 pg,无io落盘场景下,版本为未合入CLDNBS-1383相关pr的版本,也即CLDNBS-1358相关commit合入的版本,配置项与线上环境相同,9个客户端卷,每个卷的iops情况(单osd cpu利用率1000%左右):

有io落盘iops情况(单osd cpu利用率400%~800%之间波动):

3副本(3个osd,在同一节点上),256 pg,无io落盘场景下,版本为未合入CLDNBS-1383相关pr的版本,也即CLDNBS-1358相关commit合入的版本,配置项与CLDNBS-1358测试时相同,9个客户端卷,每个卷的iops情况(单osd cpu利用率1000%左右):

有io落盘iops情况(单osd cpu利用率1300%左右):

主pg数量不均衡,导致一个osd处理的osd_op数量比其他两个少40W(180W~220W),经过手工调整后(
hzwangpan@pubt2-ceph2 ceph $ ceph osd primary-affinity 35 0.95
set osd.35 primary-affinity to 0.95 (8622592)
hzwangpan@pubt2-ceph2 ceph $ ceph pg ls-by-primary 35| wc ),iops有一些提升(无io落盘场景,其他同上):

问题:无io落盘3个osd场景下,为啥性能仍然较差?

首先通过增加perf counter分析到osd之间的repop发送和接收过程较慢导致的,并进一步通过debug_ms=10日志确认。 之后再Pipe::reader()里面增加耗时和队列长度统计,并分析日志,9个卷无IO落盘场景下,可以看出sent队列长度为1100+,repop相关dispatch耗时在0.1ms左右,与客户端时延接近(120+ms),而单卷无IO落盘场景下,sent队列长度为100+,dispatch耗时不变,客户端时延14ms左右,也即与9个卷场景相差9倍左右(但单卷和9个卷的总体iops相差不大),由此可见,是服务端来不及处理高并发的IO,在服务端排队导致的时延较高。另外还在Pipe::writer()里增加代码进行测试,发现out_q队列长度均非常小,基本都在1或者0,没有排队。

查看cpu利用率最高的线程,均为Pipe::reader()线程,达到90%以上,kill -USR1看到是在mark_event,尝试关掉optracker功能之后(osd_enable_op_tracker = false),9个卷128iodepth无IO落盘,iops从1050左右提升到1680+,时延从122ms降低到75ms。每个osd的cpu利用率也从1200%降低到750%左右。

另外尝试把Pipe:reader线程绑定到独立的cpu上,把osd的其他线程绑定到其他cpu上,iops有一点提升,从1680+提升到1700+。
把日志都改成0级别(包括内存),iops提升到1950+。以上均为无io落盘,9个卷128iodepth。

3节点57 osd 3副本性能分析

9个卷,57个osd(3节点,每节点19个osd),有io落盘(关闭optracker、关闭日志),4k随机写,128iodepth,平均每个卷的性能:

用老的版本,老的配置项,同样的测试用例,同样的环境,iops性能为:

两种场景下,前4个核都已经跑满,经过对比发现前4个核跑满是因为被osd和fio线程占用了。

绑核之后(fio、osd线程绑定到4-55,fio分散到3个节点执行,每个节点跑3个卷),老的版本加老的配置,同样的测试场景下,性能提升到:

同样的绑核策略,新版本+新配置项,性能提升:

此时发现cpu是瓶颈,于是尝试采用async messager替换simple messager来对比测试(需要backport高版本的async功能),async比simple的线程数要少很多,cpu占用应该也会少一些。发现async比simple有提升,可以跑到5270左右了(simple是4960左右)。

之后才做了其他对比测试,以下数据均为async messager:
1. 尝试不绑定osd线程到4-55 cpu,iops下降到5260左右(fio线程是否绑定4-55 cpu对性能几乎无影响)。
2. 绑核,减少线程数,可以跑到5500左右:
filestore_op_threads = 16
osd_op_num_threads_per_shard = 1
osd_op_num_shards = 16
filestore_ondisk_finisher_threads = 8
filestore_apply_finisher_threads = 8
osd_enable_op_tracker = true
其他配置不变

3. 关闭osd_enable_op_tracker,可以跑到5570左右,其他配置不变
4. 尝试把fio跑在其他节点(与osd节点分开),其他不变,可以跑到5819;把async改为simple messager,同样的场景,可以跑到5106

线上环境使用的1.2-0版本进行对比测试,配置项使用线上的,无绑核,fio跑在独立的节点上。4k随机写总体iops性能为30652,平均单卷3405,

绑核后性能提升到33145,平均单卷3682:

尝试绑核并且修改配置文件,1.2-0版本可以跑到总iops 47750,平均单卷5305:

尝试每个节点只用6个osd,性能也比19个osd高,单卷iops平均6415(总57735),时延在19~20ms。单osd cpu利用率在700~800%左右,内存最大到12G左右,原因是数据落盘比journal延迟10几秒,此时ssd盘才达到瓶颈。

总结:

  1. cpu是瓶颈(测试过程中除了前4个cpu只跑软中断有20~30%的idle之后,其他cpuidle基本都接近0),ssd盘性能仍有较大余量
  2. async messager性能最好,线程数量少很多,cpu利用率比较低一些,性能可以提升一些,总iops可以跑到52374
  3. 优化代码合入对多osd场景的最终性能影响有限,原因是cpu利用率是瓶颈,ssd性能发挥不出来,对单osd性能提升比较明显
  4. 绑定cpu对性能有提升
  5. 内存日志级别也要调整到0,对性能有提升
  6. 打开op tracker在无io落盘场景下对性能影响较大,但在有io落盘场景下不明显,可以接受
  7. 通过perf top分析可以看出,cpu利用率占用较多的是内存分配释放操作,其次是bufferlist、字符串等操作

配置项改动:

其他改进手段

  1. 优化osd的cpu利用率,进一步发挥ssd盘的性能
  2. 可以考虑混合部署sas和ssd,降低ssd盘的密度,更好的发挥ssd盘的性能