概述
本文分析Ceph OpTracker相关实现,提供osd_enable_op_tracker
的配置分析,并做相关测试对比性能;
代码分析
op_tracker定义
osd_enable_op_tracker
对应的配置是osd中的op_tracker
,每个osd会初始化一个op_tracker
,代码如下:
1 | ## op_tracker的定义 |
OpTracker
的定义如下,里面维护了一个sharded list,会把op映射到对应的list上,每个shard有一个mutex锁,保证这里的track操作不会成为性能瓶颈;
每个list的单位是TrackedOp
1 | class OpTracker { |
TrackedOp定义
TrackedOp
是一个tracked的operation,它会指向所属的OpTracker
,定义如下:
1 | class TrackedOp { |
ceph osd中的每个op都是TrackedOp
的子类;
1 | struct OpRequest : public TrackedOp { |
OpRequest
会在osd dispatch的时候初始化,会根据是否enable op tracker初始化对应值:
1 | osd/OSD.cc <<ms_fast_dispatch>> |
OpTracker记录op
在创建一个op request的时候,就会把op分到OpTracker
的不同shard list上
1 | bool OpTracker::register_inflight_op(xlist<TrackedOp*>::item *i) |
之后可以通过ceph daemon <osd.id> dump_ops_in_flight/dump_historic_ops
查看该osd上的op情况;
TrackedOp mark event
当开启了op tracker,TrackedOp
就会根据配置的debug等级把一些event打印到osd的log文件里,这个操作会影响系统性能;但也可以帮我们分析出一个op哪个阶段比较费时,找出系统瓶颈;
1 | void TrackedOp::mark_event(const string &event) |
性能测试
基于之前搭建的RGW cosbench,对比测试了osd_enable_op_tracker
为false/true的情况下的性能,结果如下:
测试参数:两个cosbench driver,写一个bucket 5,000,000个objects,workers=100,runtime=2000;
debug_optracker = 0/0
& osd_enable_op_tracker = false
先写两个bucket的结果如下:
Op-Type | OOp-Count | OByte-Count | OAvg-ResTime | OAvg-ProcTime | OThroughput | OBandwidth | OSucc-Ratio | |
---|---|---|---|---|---|---|---|---|
1 | write | 2.57 mops | 82.15 GB | 77.79 ms | 77.64 ms | 1284.26 op/s | 41.1 MB/S | 100% |
2 | write | 1.32 mops | 42.28 GB | 151.05 ms | 150.8 ms | 661.69 op/s | 21.17 MB/S | 100% |
【第二次写入的性能较差,感觉应该是测试误差导致的,或者是当时有别的io影响,没再重复测试】
删除之前写的bucket的结果如下:
Op-Type | OOp-Count | OByte-Count | OAvg-ResTime | OAvg-ProcTime | OThroughput | OBandwidth | OSucc-Ratio | |
---|---|---|---|---|---|---|---|---|
1 | cleanup-delete | 5 mops | 0 B | 8.03 ms | 8.03 ms | 12468.13 op/s | 0 B/S | 100% |
2 | cleanup-delete | 5 mops | 0 B | 4.79 ms | 4.79 ms | 20898.72 op/s | 0 B/S | 100% |
debug_optracker = 0/0
& osd_enable_op_tracker = true
先写两个bucket的结果如下:
Op-Type | OOp-Count | OByte-Count | OAvg-ResTime | OAvg-ProcTime | OThroughput | OBandwidth | OSucc-Ratio | |
---|---|---|---|---|---|---|---|---|
1 | write | 2.67 mops | 85.47 GB | 74.79 ms | 74.59 ms | 1335.65 op/s | 42.74 MB/S | 100% |
2 | write | 2.47 mops | 79.02 GB | 80.91 ms | 80.76 ms | 1234.71 op/s | 39.51 MB/S | 100% |
删除之前写的bucket的结果如下:
Op-Type | OOp-Count | OByte-Count | OAvg-ResTime | OAvg-ProcTime | OThroughput | OBandwidth | OSucc-Ratio | |
---|---|---|---|---|---|---|---|---|
1 | cleanup-delete | 5 mops | 0 B | 10.3 ms | 10.3 ms | 9709.31 op/s | 0 B/S | 100% |
2 | cleanup-delete | 5 mops | 0 B | 8.63 ms | 8.63 ms | 11581.92 op/s | 0 B/S | 100% |
【删除的相应时间比之前还是慢的比较多,不清晰是测试误差,还是别的原因】
结论
从上述两项的对比可以看出,false/true的测试结果在误差范围内,印证了osd_enable_op_tracker
设置为true对Ceph系统性能没什么影响;
打开debug_optracker
为了追踪op在osd中各个阶段的时间开销,我们可以打开debug_optracker
,然后在osd的log中查到对应的event log;
打开关闭debug_optracker的方法:
1 | ceph daemon <osd-id> config set debug_optracker 5\/5 // 打开debug log |
之后可以在对应osd的log文件中看到如下log,以其中一个write op为例:
1 | 2017-05-09 11:15:58.925362 7f556af0f700 5 -- op tracker -- seq: 682036, time: 2017-05-09 11:15:58.925362, event: queued_for_pg, op: osd_op(client.1027809.0:366525835 31.36c4e4e0 (undecoded) ondisk+write+known_if_redirected e2611) |
打开debug_optracker会有大量的osd log写入,严重影响osd的性能,所以这里只是建议在调试osd性能的时候偶尔打开收集下信息,然后分析osd的性能瓶颈;
dump_historic_ops
在不打开debug_optracker
的情况下,也可以获取部分OpRequest
的event信息,这就是通过dump_historic_ops
获取;然后就可以分析op的各个时间段开销了;
1 | # ceph daemon osd.11 dump_historic_ops |