原文:http://blog.thinksrc.com/?p=189001

感叹归感叹,发泄完了还得继续过。

前几天忙的不可开交,周报上面竟然能列出11项,想想以前在T公司时候的清闲,现在的老板的真幸运了。

好了,言归正传。

我们的系统是使用ext4作为文件系统的,ext4怎么好呢? 主要是我对它感觉比较好,呵呵,开玩笑的。还记得第一次使用一个全新的ext4作为文件系统(不是ext3转过来的)时候感觉性能的feeling,应该用神奇来形容。

在我们android系统上使用ext4呢,主要是觉得它mount比较快,这样开机时间会很快。还记得当年在一点一点的抠启动时间,从40秒终于搞到30秒以内了,结果现在到了gingerbread(2.3)以后,没什么特别优化感觉都已经跑入15秒以内了。

现在遇到的问题是我们在跑一个benchmark的时候,分数比竞争对手低好几倍。总是自我感觉不良好的我们认为这可能就是我们比人家慢吧。这种故事通常的结果就是,到了实在要命的时候,比如一个很大的客户在挑战的时候。就要开始进去查了,好的,这次是我进去了。

调查的手段呢,第一个想到的就是strace,因为是IO嘛,必定和系统调用有关,所以strace肯定能够看出来一个一二三的,再加上strace的时间打印,就可以大概看出来哪些操作比较慢了。果然有发现,通过strace,发现fsync(3)消耗很多时间,中间甚至进程都出现了明显的调度出去,至于write,read这些操作,倒也不知道快慢。就先看这个fsync()为什么这么费时间吧。 其实一开始就怀疑是fsync()搞的鬼,因为有一个问题就是我们之前的kernel版本是2.6.31,这个bechmark跑的就很高,而升级到2.6.35上以后,这个分数就下降到1/3这么多。

还有一个类似的问题就是USB Mass Stroage的性能,在2.6.31上的写性能就很快,而2.6.35上的写性能就奇慢。而USM的f_storage.c里面是调用vfs_write()来进行写Block设备。通过把vfs_write()和mmc的command dump出来发现。原来在2.6.31上,加上了F_SYNC参数的vfs_write()在mmc这层,还是乱序的。而在2.6.35上,发现每一条vfs_write()都对应几条mmc命令,等这几条命令发完以后,才去从USB那里传数据,这样就成了一个很傻很慢的家伙了。而为什么2.6.31上明明加上了F_SYNC参数还是会乱序的写,我想这是一个BUG吧,在2.6.35上修复了而已。

所以这里的ext4文件系统fsync()慢可能也是和这个有关系的。但是作为嵌入式设备,随处会面对掉电的风险。所以掉电保护就很重要,不能说为了性能吧所有sync的写都变成un-sync的写,那些数据丢失会比较严重。

Google了两天,发现很多关于fsync和ext4的讨论,放在这里一些万一别人要看呢, [1]

无头绪,于是继续看ext4在kernel里面的文档,看到了mount参数这节,忽然灵机一动想起换换mount参数跑这个benchmark会不会有所改进呢?

于是就把那些看似和write相关的参数都做了一个表格。

Ext4 with different option nobarrier nodelalloc journal_async_commit  
         
(no combine) 558 1087 524  
nobarrier NA NA 522  
nodelalloc 1052 N\A 1051  
journal_aysnc_commit        
& nobarrier & nodelalloc        

可以看的出来,nodelalloc在这里贡献非常大。几乎是一倍的分数。

为什么这个参数nodelalloc会这样呢,这是它的文档中的解释:

delalloc        (*)     Defer block allocation until just before ext4
                        writes out the block(s) in question.  This
                        allows ext4 to better allocation decisions
                        more efficiently.

nodelalloc              Disable delayed allocation.  Blocks are allocated
                        when the data is copied from userspace to the
                        page cache, either via the write(2) system call
                        or when an mmap'ed page which was previously
                        unallocated is written for the first time.
先看这个delalloc, 这是默认值, 就是说把所有的block分配推后到真正要写数据的时候,当有sync调用的时候,也就是这种时候。

而关掉这个默认feather以后,块号就会在page cache的时候分配。 如果区别只是这里, 就无法解释为什么分配块号会花费这么多的时间了。是的,瓶颈不在这里。

我们接着看fsync()这个系统调用,它在手册里面的解释是:

fsync() transfers ("flushes") all modified in-core data of (i.e., modi‐
       fied  buffer cache pages for) the file referred to by the file descrip‐
       tor fd to the disk device (or other  permanent  storage  device)  where
       that  file  resides.

所以它仅仅要求文件系统把所有*该文件*的修改写到磁盘中。

然后我们去看看ext4对于它的实现。

/*
* akpm: A new design for ext4_sync_file().
*
* This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
* There cannot be a transaction open by this task.
* Another task could have dirtied this inode. Its data can be in any
* state in the journalling system.
*
* What we do is just kick off a commit and wait on it. This will snapshot the
* inode to disk.
*
* i_mutex lock is held when entering and exiting this function
*/ int ext4_sync_file(struct file *file, int datasync)

{

struct inode *inode = file->f_mapping->host;

struct ext4_inode_info *ei = EXT4_I(inode);

journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;

int ret;

tid_t commit_tid;
    J_ASSERT(ext4_journal_current_handle() == NULL);

    trace_ext4_sync_file(file, datasync);

    if (inode->i_sb->s_flags & MS_RDONLY)
return 0; ret = flush_completed_IO(inode);
if (ret < 0)
return ret;
if (!journal) {
ret = generic_file_fsync(file, datasync);
if (!ret && !list_empty(&inode->i_dentry))
ext4_sync_parent(inode);
return ret;
} /*
* data=writeback,ordered:
* The caller's filemap_fdatawrite()/wait will sync the data.
* Metadata is in the journal, we wait for proper transaction to
* commit here.
*
* data=journal:
* filemap_fdatawrite won't do anything (the buffers are clean).
* ext4_force_commit will write the file data into the journal and
* will wait on that.
* filemap_fdatawait() will encounter a ton of newly-dirtied pages
* (they were dirtied by commit). But that's OK - the blocks are
* safe in-journal, which is all fsync() needs to ensure.
*/
if (ext4_should_journal_data(inode))
return ext4_force_commit(inode->i_sb); commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
if (jbd2_log_start_commit(journal, commit_tid)) {
/*
* When the journal is on a different device than the
* fs data disk, we need to issue the barrier in
* writeback mode. (In ordered mode, the jbd2 layer
* will take care of issuing the barrier. In
* data=journal, all of the data blocks are written to
* the journal device.)
*/
if (ext4_should_writeback_data(inode) &&
(journal->j_fs_dev != journal->j_dev) &&
(journal->j_flags & JBD2_BARRIER))
blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL,
NULL, BLKDEV_IFL_WAIT);
ret = jbd2_log_wait_commit(journal, commit_tid);
} else if (journal->j_flags & JBD2_BARRIER)
blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL,
BLKDEV_IFL_WAIT);
return ret;

}

我们的文件系统是以ordered的方式mount的,所以要调到的函数基本是:

flush_completed_IO()
jdb2_log_start_commit()
jdb2_log_wait_commit()

所以我们可以看到,对于一条fsync(), ext4会把所有的日志都commit掉,所以这才是真正慢的地方。 所以在需要经常做fsync()的应用下,比如sqltie就是一点典型例子。但是我觉得这个功能对于磁盘设备得大于失,但是对于闪存类型的设备,就没什么优势了。

后来又做一个一个在O_SYNC参数下面的write性能对于关不关delalloc的对比:  这里是的Y轴是差值,高于0就是delalloc的性能好,低于就是差。 X轴代表一次write操作的单元, 不同颜色的线代表不同的文件大小。 单位都是KB 

从图上可以看出,对于很大的文件,16M的文件,几乎所有的情况都是delolloc的性能要好。 但是对于64K-512K的文件, 性能就要差很多。

对于文件unit的大小,可以看得出来256K是一个分水岭。 在接近256K的时候,延迟分配性能就要好很多,这个原因是因为我们的L2缓存是256K, 所以当写的数据接近256K的时候,由于延迟分配技术不用去分配Block 块,所以大部分的memory write都可以用来作为文件写page cache,如果有了分配block这些数据,就会导致cache不对其,所以性能就会比延迟分配差很多。

还有一个地方是L1缓存(我们的是32K),这里前面小于L1的写都是延迟分配要快很多。原因和前面类似,但是不同的是接近L1的时候,反而都是不延迟分配要快一些,这点不知道怎么解释。可能的原因是在L1从L2中取数据的时延比较小.

这里还有一个有趣的地方是,对于512K大小的unit,delalloc的性能就要明显达到一个最高点。这是为啥呢?

【注】想起一个事情, 为什么512K是一个特殊的点呢? 因为512K是mmc设备的defualt block size. 但是对于为什么去掉延迟写入的性能会高那么多呢?很有意思。

[1] right thing, but really affect performance  http://postgresql.1045698.n5.nabble.com/ext4-finally-doing-the-right-thing-td2076089.html

[2] This patch fix it.http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5f3481e9a80c240f169b36ea886e2325b9aeb745

</article>

[转帖]ext4的fsync性能和nodelalloc参数的分析的更多相关文章

  1. paip.提升性能---mysql 性能 测试以及 参数调整.txt

    paip.提升性能---mysql 性能 测试以及 参数调整.txt 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://b ...

  2. Dubbo性能调优参数及原理

    本文是针对 Dubbo 协议调用的调优指导,详细说明常用调优参数的作用域及源码. Dubbo调用模型 常用性能调优参数 参数名 作用范围 默认值 说明 备注 threads provider 200 ...

  3. sql中varchar(n),nvarchar(n) 长度性能及所占空间分析

    sql中varchar(n),nvarchar(n) 长度性能及所占空间分析 1.varchar(n),nvarchar(n) 中的n怎么解释: nvarchar(n)最多能存n个字符,不区分中英文. ...

  4. fsync性能问题

    最近在测试种发现程序里调用fsync刷文件到磁盘时,开销只有几百微秒,于是对fsync相关机制进行了一番调查. 磁盘(或RAID卡)自身通常会有硬件缓存机制,对于写操作,有write back和wri ...

  5. sql中NVARCHAR(MAX) 性能和占空间分析 varchar(n),nvarchar(n) 长度性能及所占空间分析

    varchar(n),nvarchar(n) 中的n怎么解释: nvarchar(n)最多能存n个字符,不区分中英文. varchar(n)最多能存n个字节,一个中文是两个字节. 所占空间: nvar ...

  6. 数据库相关文章转载(1) MySQL性能优化之参数配置

    1.目的: 通过根据服务器目前状况,修改Mysql的系统参数,达到合理利用服务器现有资源,最大合理的提高MySQL性能. 2.服务器参数: 32G内存.4个CPU,每个CPU 8核. 3.MySQL目 ...

  7. MySQL 性能优化神器 Explain 使用分析

    简介 MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化. EXPLAIN 命令用法十分简单, 在 ...

  8. MySQL性能优化之参数配置

    1.目的: 通过根据服务器目前状况,修改Mysql的系统参数,达到合理利用服务器现有资源,最大合理的提高MySQL性能. 2.服务器参数: 32G内存.4个CPU,每个CPU 8核. 3.MySQL目 ...

  9. Java技术学习之影响MySQL性能的配置参数

    本文将介绍MySQL参数的五大类设置,平时我们一般都很少碰它们,在进行MySQL性能调优和故障诊断时这些参数还是非常有用的. (一)连接连接通常来自Web服务器,下面列出了一些与连接有关的参数,以及该 ...

  10. [性能调优]PeopleSoft Trace 分析工具 - TraceMagic

    PeopleSoft Trace 文件包含大量的信息,在前面文章讲解过如何查看trace日志文件,这边文章介绍一个工具可以很好的分析trace日志文件. TraceMagic 是由oracle开发的一 ...

随机推荐

  1. 在Global Mapper中导入点的文本格式

    目录 有时候想在Global Mapper快速显示一个点的具体位置,来不及去创建一个具体的矢量文件.一个最快速的方式就是将这个点写在文本文件中导入: 13149831.629692005 281725 ...

  2. C++篇:第十四章_编程_知识点大全

    C++篇为本人学C++时所做笔记(特别是疑难杂点),全是硬货,虽然看着枯燥但会让你收益颇丰,可用作学习C++的一大利器 十四.编程 (一)概念 系统函数及其库是 C++语言所必须的,预处理命令不是 C ...

  3. 云图说|什么是可信智能计算服务TICS

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 本文分享自华为云社区&l ...

  4. 【华为云技术分享】玩转物联网IoTDA服务系列三-自动售货机销售分析场景示例

    摘要:物联网解决方案中,作为数据主体的"物"可能数量会非常大,产生的数据已经无法通过传统的数据处理服务进行处理.如何分析与利用这庞大的物联网设备数据对物联网企业来说又是一个新的挑战 ...

  5. 13个VSCode使用技巧,开启高效的开发模式

    摘要:VsCode是一款开源的编辑器,拥有强大的功能,.由于拥有各种各样的插件,这就使得VsCode可以做到的事情更多了.在使用的过程中,也是有很多技巧的,掌握一些技巧对于后期写代码也会轻松很多. 本 ...

  6. centos8 测地卸载php5.6 与卸载php7

    centos8 yum php 默认安装 php7.1.2 我想卸载php7 ,安装php5.6 yum remove php 无法彻底卸载干净.必须强制删除,使用下面命令查看全部php软件包 rpm ...

  7. 零售品牌如何挑选达人 KOL?火山引擎 VeDI 有妙招!

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 国内消费市场正在发生一些新变化. 近日,由中国人民大学国家发展与战略研究院.经济学院等联合主办的第 57 期宏观经 ...

  8. DNS--智能地址解析(view视图)

    域名:xinenhui.com DNS服务器:192.168.198.128 DNS1:192.168.198.129 DNS2:192.168.198.146 1 简介 使客户端就近访问DNS服务器 ...

  9. dmesg 时间误差现象

    案例现象 这天收到监控平台发来的告警,说有台机器程序崩溃了 因为以前也有过相关的错误,根据经验,用 dmesg命令看下内核信息 发现有点不对劲,报错信息的时间跟告警时间不一致,正常来讲报错时间应该跟告 ...

  10. DOCKER本地仓库

    概述 随着docker的应用越来越多,安装部署越来越方便,批量自动化的镜像生成和发布都需要docker仓库的本地化应用. 试用了docker的本地仓库功能,简单易上手,记录下来以备后用. 环境 cen ...