cephfs内核客户端性能追踪

问题描述

测试cephfs内核客户端的吞吐性能,direct写时单个客户端性能有上限,只能接近150 mb/s:

image

查看网卡流量,并没有打满:

image

查看集群负载也很低,osd磁盘很空闲,验证多台机器同时并发测试,总吞吐可以上去,怀疑单个客户端的上限有瓶颈。

源码分析

集群没有打满,网络也不是瓶颈,那么只能从内核客户端cephfs的写IO入手,寻找问题的根源。 cephfs内核客户端写IO的代码在文件fs/ceph/file.c:

image

从代码实现看,主要流程是newrequest, startrequest, wait_request三个步骤。 直觉告诉我这里的wait会被block住,跟踪一下这里的wait实现:

image

先看超时的时间,传入的是0,最终结果是LONG_MAX,差不多就是一直wait:

image

接下来看条件的满足:

image

从kernel的注释看,函数schedule_timeout就是sleep直到timeout:

image

从源码分析看,已经比较明确,一次请求下发后,只有等请求完成了才会进行下一次请求,IO并不是并发的下发给后端的集群。

接下来的问题是,每次请求的size如何决定? 这个和文件的layout属性和当前写的位置相关,如果从文件offset 0开始写的话,以及采用默认属性,最大就是ceph object size的大小,即4MB。 ceph的layout解释可以参考官方文档。

image

实验证明

调取文件属性

为了更明显的观察延时,我们将文件的属性调整一下,即从4m到64m:

image

获取文件inode

image

文件对应的对象

image

查看两个对象对应的osd信息,分别对应osd 121和130:

image

再次执行刚才的dd命令,并在两个primary osd(121, 130)上观察op的情况,并同时用ftrace,观察kernel客户端写的过程。

osd机器OP请求

通过以下命令查看osd的op信息,ID为上面的121和130:

ceph daemon osd.ID dumphistoricops

image

上面是osd 121的信息,操作的对象是10000000388.00000000,op持续了426.153ms,主要耗费时间在网络读数据的延时和副本操作的延时。op开始时间16:04:19.049346,结束时间16:04:19.475499。

image

这是osd 130的信息,操作的对象是10000000388.00000001,op持续了439.539ms。op开始时间16:04:19.491627,结束时间16:04:19.931166。

可以很清楚的看见,先写第一个对象,再写第二个对象,对象之间是没有并发写的,这区别于块存储,块存储的实现,至少librbd的实现,如果一次io对应多个object,多个请求是同时发出的,而不会等第一个对象完成了才下发第二个对象的IO,参见如下代码:

image

写文件的客户端ftrace信息

enable ftrace步骤:

image

观察日志:

image

这里用了差不多500ms才开始下一个请求,而上面从osd端的分析看,第一个IO用了426ms才完成,osd完成IO后通知kernel客户端有网络延时,然后加上kernel调度的延时,差不多能够匹配。

结论

通过源码分析,然后分别从集群osd端和kernel客户端进行验证,direct的情况,cephfs性能确实有限制。但是,用户也不用过于担心性能跟不上,因为通常情况下,不会是direct写,kernel客户端有page cache,写会非常快,

image

更贴近真实的使用场景,用户先写数据,最后调用一次sync操作:

image

更新日期:
本文总阅读量