写入子文件夹比写入其父文件夹快

roc*_*ker 6 performance io

我使用 dd 来测量写入性能并观察到一些奇怪的现象:写入 /data/emzed2 比写入 /data 快。这是我衡量性能的方式:

$ dd if=/dev/zero of=/data/emzed2/testfile bs=32

^C4921834+0 条记录

4921834+0 记录输出 157498688 字节 (157 MB) 复制,2,87329 秒,54,8 MB/秒

$ dd if=/dev/zero of=/data/testfile bs=32

^C2487991+0 条记录

2487991+0 条记录已复制 79615712 字节 (80 MB),2,6501 秒,30,0 MB/秒

两个文件夹都在 SSD 驱动器上的同一分区上。我使用 Ubuntu 14.04 并多次重复实验,结果相似。

知道发生了什么吗?

小智 4

看来您受到了 ext4 优化的影响。其中一些在Ext4 磁盘布局文档中进行了描述。

\n\n

每次增长文件时(例如使用 dd),都会为新数据分配一些位置。最终,文件可能会被碎片化,即数据可能会分散在磁盘上的多个块中。碎片是众所周知的速度缓慢的根源(读取和写入时),因此文件系统实现通常会尝试避免它。与 SSD 相比,旋转磁盘(磁头需要移动到连续的块)的碎片化成本更高,但大多数文件系统实现都使用 SSD 的旋转磁盘优化策略。

\n\n

上面提到的文档中描述的第三、第四和第五个“技巧”的组合可能可以解释为什么在您的情况下写入子目录更快。

\n\n
\n

第五个技巧是将磁盘卷分割成 128MB 的块组。[\xe2\x80\xa6] 当在根目录中创建目录时,inode 分配器会扫描块组并将该目录放入它可以找到的负载最轻的块组中。

\n
\n\n

结果,emzed2可能是在 128MB 的空块中创建的。

\n\n
\n

第四个技巧是,如果可行,目录中的所有 inode 都放置在与目录相同的块组中。

\n
\n\n

因此,/data/testfile是在(可能负载较重的)根块组中创建的,而/data/emzed2/testfile是在(可能是空的)emzed2块组中创建的。

\n\n
\n

第三个技巧 [\xe2\x80\xa6] 是它尝试将文件的数据块与其 inode 保持在同一块组中。

\n
\n\n

对于/data/emzed2/testfile,文件系统会首先分配emzed2块组中的所有数据块。如果这个块最初是空的,对于前 128MB,这意味着根本没有碎片。对于/data/testfile,文件系统如果还没有填充的话,会先填充根块组,然后再寻找其他地方来存储数据。

\n\n

此外,您一次将文件增长 32 个字节。幸运的是,诸如 ext4 之类的文件系统会分配比您请求的更多的数据(在 ext4 的情况下为 8kb 块),并尝试延迟分配。您可能会看到类似的模式bs=8196,但速度差异可能会随着块大小的增大而减小。

\n