近期接到ceph用户报案,说是多进程direct写ceph-fuse的单个文件,性能很低,几乎与单进程direct写文件的性能一样。关乎民生,刻不容缓,笔者立即展开侦查工作~

一、复现案情,寻踪追记

笔者通过fio工具展开测试,分别测试了单进程和多进程direct随机写ceph-fuse的单个文件的性能情况。

fio -filename=/mnt/fuse/file_1T -direct=1  -rw=randwrite -ioengine=sync -bs=4K -size=1G  -numjobs=1 -runtime=180 -group_reporting -name=test
fio -filename=/mnt/fuse/file_1T -direct=1 -rw=randwrite -ioengine=sync -bs=4K -size=1G -numjobs=16 -runtime=180 -group_reporting -name=test

结果显示,无论单进程,还是多进程,而且无论多少进程,iops结果差不多都是50左右(磁盘未开write-cache)。那么,多进程写多个文件呢,性能又是怎样的?

这里注意了,将fio的参数filename改成directory后,对于多进程,fio会为每个进程创建一个测试文件。

fio -directory=/mnt/fuse/ -direct=1  -rw=randwrite -ioengine=sync -bs=4K -size=1G -numjobs=16 -runtime=180 -group_reporting -name=test

结果显示,iops大概是800左右,正好是单进程50的16(进程数)倍,怎么这么巧?

二、分析案情,锁定可能的嫌疑人

写同一个文件,单进程和多进程具有相同的iops性能,说明多进程在io路径的某个环节变成了串行,从而导致多进程实际上也变成了单进程。

我们先来看下ceph-fuse的io链条:

用户态程序fio -> vfs -> kernel fuse -> libfuse -> ceph-fuse -> [mds] -> ceph cluster

笔者之前看过链条上一些环节的代码,但由于代码量太大,代码的细节太多,所以认知并不深入,无法直接定位到凶手。

为了帮助分析案情,这里简单描述下这条io链:
用户态程序fio通过多进程进行direct随机写,通过vfs后进入kernel fuse,kernel fuse会将io请求放入到pending队列,然后等待结果。用户态libfuse的多个进程通过/dev/fuse设备读取pending队列中请求,然后调用更底层的ceph-fuse进行处理。ceph-fuse最终将请求发送给mds或者ceph集群进行处理。

必然是上述io链条中某个环节导致了案情的发生。然而我们很难熟知于io链条中的每一环,所以我们需要根据更多已知的线索来缩小io链条的排查范围。

三、搜集线索,缩小排查范围

目前已知的线索有:

① fio多进程和单进程写同一文件性能几乎一致
② fio多进程写进程数个文件的性能 = 单进程性能 * 进程数

由于没有更多的线索,笔者开始对io链条进行排查。先从熟悉的ceph-fuse、mds和ceph cluster开始。

嫌疑人 分析
ceph cluster 对比多进程写单文件和多进程写多文件的性能,说明出现案情时,ceph cluster不是瓶颈
mds 由于fio测试是单客户端的,所以多进程的写也不会竞争fw的caps,另外fio的测试,涉及mds的请求很少,所以mds作案的可能性很小
ceph-fuse 这是笔者怀疑的重点,众所周知,ceph-fuse有把client大锁,通过阅读代码发现,ceph-fuse在发送写请求给osd后就释放了client锁,并没有持锁等待结果,这虽然对写性能有一定的影响,但不至于将多进程io串行

笔者展开更多测试,发现了一条重要的线索:

③ 16进程direct随机写16个文件时,通过kernel fuse的controlfs(/sys/fs/fuse/connections/39/waiting)看到等待的请求数一直是16,而16进程direct随机写单文件时,等待的请求数一直是1

线索③说明,在libfuse之前,多进程已经被串行化,这样可以基本排除libfuse、ceph-fuse、mds、ceph cluster的嫌疑了,笔者可以把精力放在io链条的前面了。

用户态程序fio -> vfs -> kernel fuse

静下心来,思索下...
多进程写单个文件,io被完全串行化,凭经验,要么是有文件锁,要么有inode锁。先朝这方向走一下,我们需要定位下锁在io链条的哪个环节,逐个分析下每个环节。

用户态程序fio:
通过查看fio的man page,笔者发现fio有个lockfile的参数,当lockfile设置成exclusive或者readwrite时,多进程的写会被串行化,然而该参数的默认值是none,所以可以排除用户态程序fio的嫌疑。

vfs:
vfs是内核很薄的一层,而且linux上可以通过flock和fcntl对文件进行加锁,在没有用户态程序调用的情况下,vfs显然不会私自对文件和inode加锁,并且,这个案情在kernel cephfs客户端下不存在,所以可以排除vfs的嫌疑。

排除了其他io环节,最后只剩下 kernel fuse ,是笔者熟悉程度相对比较低的模块,看来需要重点招待了。

四、搜集证据,锁定凶手

笔者重新阅读kernel fuse的io流程代码,最终拿到证据,真相是如此简单....

static ssize_t fuse_direct_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){
...
/* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex);
res = __fuse_direct_write(&io, &iov, 1, ppos);
if (res > 0)
fuse_write_update_size(inode, *ppos);
mutex_unlock(&inode->i_mutex);
...
}

凶手作案手法:
多进程direct写io到kernel fuse的该函数后,拿到inode锁,进行io请求,io请求发送到pending队列后,会持锁等待io请求结束,从而导致多进程的direct写io被串行化。

五、关注笔者

专注笔者公众号,阅读更多干货文章:)

IO侦探:多进程写ceph-fuse单文件性能瓶颈侦查的更多相关文章

  1. io流之写文件

    用Java程序写文件有多种方式,对于不同类型的数据,有不同的写方法.写文件的关键技术点如下: 1.FileOutputStream打开文件输出流,通过write方法以字节为单位写文件,是写文件最通用的 ...

  2. vue 单文件 样式写了scoped 不能覆盖框架原有样式的解决办法

    vue 单文件 样式写了scoped 不能覆盖框架原有样式的解决办法 在vue 里面<style scoped></style> 是为了让样式只影响本身自己组件的样式,不改变全 ...

  3. 开源作品-PHP写的JS和CSS文件压缩利器(单文件绿色版)-SuMinify_PHP_1_5

    前言: 网站项目需要引用外部文件以减小加载流量,而且第一次加载外部资源文件后,其他同域名的页面如果引用相同的地址,可以利用浏览器缓存直接读取本地缓存资源文件,而不需要每个页面都下载相同的外部资源文件. ...

  4. 开源作品-PHP写的Redis管理工具(单文件绿色版)-SuRedisAdmin_PHP_1_0

    前言:项目开发用到了Redis,但是在调试Redis数据的时候,没有一款通用的可视化管理工具.在网络找了一些,但是感觉功能上都不尽人意,于是决定抽出一点时间,开发一个用起来顺手的Redis管理工具.秉 ...

  5. 开源作品-PHP写的在线文件管理工具(单文件绿色版)-SuExplorer_PHP_3_0

    前言:项目开发过程中,网站一般部署到远程服务器,所以文件管理就不能和本机操作一样方便.通常文件管理是用ftp下载到本地,修改后再上传,或者远程登录到服务器进行修改.但是这些操作都依赖于复杂的第三方软件 ...

  6. Ueditor1.4.3实现跨域上传到独立文件服务器,完美解决单文件和多文件上传!

    再写配置方法之前先吐槽一下网上的各种教程,TM没一个有卵用,一群傻屌不会写就别写,写了就要负责. 百度google搜了半天,全是配置什么document.domain,根域名什么的,我只想对你说: 好 ...

  7. SQLite的原子提交--单文件场景

    3. 单文件提交 我们首先概要说明SQLite在单个数据库文件上为了执行事务的原子提交而采取的步骤.在后面的部分将讨论如何设计文件格式以保护其在断电故障中损坏,以及原子提交在多个数据库上的执行. 3. ...

  8. C# 日志记录分级功能使用 按照日期,大小,或是单文件存储

    本文将使用一个Nuget的一个组件库来实现一个简单强大的日志记录功能,包采用线程安全实现,所有的记录在后台完成,即使您在前台调用100万次方法,耗时也不过1000ms(具体时间依照电脑性能决定),支持 ...

  9. Spring MVC - MultipartFile实现文件上传(单文件与多文件上传)

    准备工作: 需要先搭建一个spirngmvc的maven项目 1.加入jar包 <dependency> <groupId>commons-fileupload</gro ...

随机推荐

  1. Qt使用预编译头文件Using Precompiled Headers(提升10倍以上)

    预编译头文件是被很多编译器用来编译稳定的代码以及将编译好的稳定代码存储在二进制文件中用于提升编译性能.在随后的编译中,编译器将加载存储状态继续编译指定的文件.每一个随后的编译将更快,因为稳定的代码不需 ...

  2. Tab选项卡界面(1)

    Tab用一个简单的应用程序接口的标签是集中的界面布局文件的同一页上的接口组件不同的标签.并计划将在主类集中的代码文件.这种方法的优点是,文件在项目数不会被添加,但是,假设Tab接口组件更个性化的标签. ...

  3. Adapter的泛型

    宗旨:GetView方法放在具体的Activity/Fragment里面实现,其他的均可以复用 /// <summary> /// 通用适配器:新建GetViewEvent委托+OnGet ...

  4. VC++互相转码GBK,unicode,utf8

    windows平台下微软的库自带了一些api可用于几种编码格式间的互相转码,其实可以用一个iconv开源跨平台的转码库,那个方法更方便且统一. 使用前要引入头文件和命名空间 #include < ...

  5. 备份一个支持虚拟化的wrappanel

    public class VirtualizingWrapPanel : VirtualizingPanel, IScrollInfo { #region Fields UIElementCollec ...

  6. Win8 Metro(C#)数字图像处理--2.70修正后的阿尔法滤波器

    原文:Win8 Metro(C#)数字图像处理--2.70修正后的阿尔法滤波器 /// <summary> /// Alpha filter. /// </summary> / ...

  7. 零元学Expression Blend 4 - Chapter 12 用实例了解布局容器系列-「Viewbox」

    原文:零元学Expression Blend 4 - Chapter 12 用实例了解布局容器系列-「Viewbox」 本系列将教大家以实做案例认识Blend 4 的布局容器,此章介绍的布局容器是Bl ...

  8. Windows实用小工具-问题步骤记录器

    今晚给大家介绍个实用的好工具,可以做简单的问题记录,再也不用截图加注释这么辛苦了····· 经测试,这东东在win7,2008 及2008R2里适用,也就是说,在win7以上的系统中才有.好了,下面直 ...

  9. extjs grid 复选框选择事件

    开发中需求是统计选择的行数,所以要监控checkbox的选择事件包括表头的全选事件 遇到的问题就不赘述了 方案是监控grid的复选框和行加载时绑定事件 baseView: DBEN.controls. ...

  10. Raknet是一个基于UDP网络传输协议的C++网络库(还有一些其它库,比如nanomsg,fastsocket等等)

    Raknet是一个基于UDP网络传输协议的C++网络库,允许程序员在他们自己的程序中实现高效的网络传输服务.通常情况下用于游戏,但也可以用于其它项目. Raknet有以下好处: 高性能 在同一台计算机 ...