GlusterFS关键代码优化

jszhaogy 贡献于2016-01-27

作者 load  创建于2014-05-01 03:29:00   修改者load  修改于2014-05-04 10:04:00字数3209

文档摘要:本次优化点主要基于qemu+GlusterFS测试和性能调优。针对qemu+GlusterfS和qemu+localfilesystem两种场景做了性能测试和对比。最终形成了GlusterFS的优化包括两点带标记位的fsync操作优化write申请写缓冲区内存管理优化qemu+GlusterIntegrationIOStack带标记位的fsync操作优化当guestOS的APP执行fsync操作时,GlusterFS后端存储性能比与本地文件系统backend差很多,而普通的asyncwrite和directwrite相比,二者相差并没那么大。例如,VM中采用dd工具测试,dd设置dsync标记后,执行写操作测试数据如下。提交的数据块尺寸较小时,GUSTER虚机与本地虚机性能差别较大,在差3倍多,随着提交数据块尺寸增大,差距逐步缩小大一倍左右。
关键词:

GlusterFS关键代码优化 本次优化点主要基于qemu+GlusterFS测试和性能调优。针对qemu+GlusterfS和qemu+local filesystem两种场景做了性能测试和对比。最终形成了GlusterFS的优化包括两点 1. 带标记位的fsync操作优化 2. write申请写缓冲区内存管理优化 qemu+Gluster Integration IOStack (一) 带标记位的fsync操作优化 当guestOS的APP执行fsync操作时,GlusterFS后端存储性能比与本地文件系统backend差很多,而普通的async write和direct write相比,二者相差并没那么大。 例如,VM中采用dd工具测试,dd设置dsync标记后,执行写操作测试数据如下。提 交的数据块尺寸较小时,GUSTER虚机与本地虚机性能差别较大,在差3倍多,随着提交数据块尺寸增大,差距逐步缩小大一倍左右。 测试命令 local filesystem back end gluster fs backend time dd if=/dev/zero of=/test.dbf bs=4k count=500000 oflag= dsync 4.2M/S 1.2M/S time dd if=/dev/zero of=/test.dbf bs=8k count=500000 oflag= dsync 8.6M/S 2.4 M/S time dd if=/dev/zero of=/test.dbf bs=64k count=500000 oflag= dsync 28.7M/S 8.9M/S time dd if=/dev/zero of=/test.dbf bs=256k count=500000 oflag= dsync 128M/S 54.8M/S time dd if=/dev/zero of=/test.dbf bs=1024k count=500000 oflag= dsync 213M/S 119M/S Sync操作分析: VM的filesystem fsync一个4K数据块,QEMU会调用GLUSTER 3次写操作,6次fsync操作。从日志上看,多余的2个write是虚机写入的其他数据。每1到2个写操作,会连续执行3次gluster的fsync。 Gluster的fsync操作与write操作各耗时比例大概为3:1。 GLUSTER被调用的行为如下所示: [2014-04-22 02:00:29.046597] T [glfs-fops.c:923:glfs_pwritev_async] 0-glfs-fops: ENTER glfs_pwritev_async offset=18346790912, data=0x7f0e9c3ea000 0.6MS [2014-04-22 02:00:29.055341] T [glfs-fops.c:923:glfs_pwritev_async] 0-glfs-fops: ENTER glfs_pwritev_async offset=354156544, data=0x7f0e000140c0 0.6MS [2014-04-22 02:00:29.056373] T [glfs-fops.c:1089:glfs_fsync_async] 0-glfs-fops: ENTER [glfs-fops.c][glfs_fsync_async][1089] 1.2MS server: 0.6 [2014-04-22 02:00:29.057717] T [glfs-fops.c:1089:glfs_fsync_async] 0-glfs-fops: ENTER [glfs-fops.c][glfs_fsync_async][1089] 0.7MS server: 0.35 [2014-04-22 02:00:29.058590] T [glfs-fops.c:1089:glfs_fsync_async] 0-glfs-fops: ENTER [glfs-fops.c][glfs_fsync_async][1089] 0.8MS server: 0.35 [2014-04-22 02:00:29.059770] T [glfs-fops.c:923:glfs_pwritev_async] 0-glfs-fops: ENTER glfs_pwritev_async offset=354177024, data=0x7f0e9c3e9d00 0.57MS [2014-04-22 02:00:29.060632] T [glfs-fops.c:1089:glfs_fsync_async] 0-glfs-fops: ENTER [glfs-fops.c][glfs_fsync_async][1089] 1.34MS server: 0.73 [2014-04-22 02:00:29.057717] T [glfs-fops.c:1089:glfs_fsync_async] 0-glfs-fops: ENTER [glfs-fops.c][glfs_fsync_async][1089] 0.78MS server: 0.37 [2014-04-22 02:00:29.062967] T [glfs-fops.c:1089:glfs_fsync_async] 0-glfs-fops: ENTER [glfs-fops.c][glfs_fsync_async][1089] 0.8MS server: 0.39 优化思路: 从上面的日志中可以看到,调用过Gluster的write后,执行第一次fsync是有意义的,会触发Gluster server将缓存数据flush到磁盘,而第二次和第三次fsync并没做实际意义的工作,大部分时间消耗在:GlusterClient到Gluster server的rpc交互、Gluster server调用本地磁盘文件的fsync系统调用。 为了减少第二次和第三次的fsync操作,在glusterFS client的File handle中增加一个标记位,记录FD对应的file是否执行过fsync操作: client每调用一次write/ftruncate操作,就将此标记位置为脏; client每调用一次fsync操作,就将脏位清空; client调用fsync时,首先检查此标记位是否为脏: 如果file为脏,则执行原来的fysnc流程,通知gluster server段flushcache数据。 如果不脏,则fsync直接返回,不再需要跟server交互。 代码修改点: 1) write 、ftruncate 把no_dirty置为0 2) fsync 、fsync_async 成功 把no_dirty 置为1 3) fsync 、fsync_async 、fdatasync 、fdatasync_async 判断no_dirty 非0 接口直接返回 (二) write申请写缓冲区内存管理优化 gluster普通异步write的性能比本地文件系统差很多。分析后发现主要的性能瓶颈在gluster client会有大块内存申请,这块内存申请直接调用libc的calloc函数,动态申请一块大内存,并在使用前将这块内存初始时为0。对于经常使用大块内存buffe,calloc的效率是比较低的。 synctask_new { …… newtask->stack = CALLOC (1, env->stacksize); if (!newtask->stack) { gf_log ("syncop", GF_LOG_ERROR, "out of memory for stack"); goto err; } ……. } 优化思路: 使用静态buffer循环队列的方式对这块内存进行管理。每次申请的时候直接从循环队列中取出一块空闲内存作为buffer,不再进行初始化操作。 优化后的结果对比: 下图是内存分配改进前后的性能对比图。左侧是未修改内存分配测试数据,右侧是改进后的测试数据,可以看到改进后性能提升明显。

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档