查看原文
其他

1s 创建 100G 文件,最快的方法是?

CPP开发者 2022-07-01

The following article is from Linux开发那些事儿 Author LinuxThings

在我们日常工作中,为了验证开发的功能,比如:文件上传功能或者算法的处理效率等,经常需要一些大文件进行测试,有时在四处找了一顿之后,发现竟然没有一个合适的,虽然 Linux 中也有一些命令比如:vim、touch 等可以创建文件,但是如果需要一个 100G 或者 1T 的大文件,这些命令就显得力不从心,此时就需要能快速创建大文件命令,接下来将介绍这些命令的常见用法、命令之间的差异、以及使用时如何选择

dd

dd 命令的语法如下

dd if=[source] of=[destination] bs=[block-size] count=[counter]

source 读取并拷贝内容到 destinationsourcedestination 都是文件,前者是读取的文件,后者是写入的文件

bs表示块的大小,单位是字节,后缀中带了字母B的换算单位都是1000, 比如:1KB = 1000 Bytes1MB = 1000 * 1000 Bytes1GB = 1000 * 1000 * 1000 Bytes

后缀省略了字母 B的换算单位是 1024, 比如:1K = 1024 Bytes1M = 1024 * 1024 Bytes1G = 1024 * 1024 * 1024 Bytes

count 表示块的数量,表示 dd 命令需要执行多少次读取并写入的操作

bs 乘以 count 其实就表示目标文件的大小,也即需要创建的文件的大小,比如:下面的命令可以创建一个 10G 大小的文件

[root@localhost dd_cmd]# dd if=/dev/zero of=testfile bs=1G count=10
记录了10+0 的读入
记录了10+0 的写出
10737418240字节(11 GB)已复制,8.61643 秒,1.2 GB/秒
[root@localhost dd_cmd]# du -h testfile  
10G     testfile
[root@localhost dd_cmd]#

上面的命令表示从 /dev/zero文件每次读取 1G大小的数据并写入当前目录中的 testfile 文件, bs=1G count=10 表示块大小是1G,总共有10个块, 所以目标文件最终的大小是: 1G * 10 = 10G

/dev/zero 是一个特殊的字符设备文件,当读取它的时候,它会返回空数据,这里表示从 /dev/zero读取空的数据写入 testfile

命令 du -h testfile 的结果也说明了 testfile 大小是 10G

从结果可以得知,用 dd 命令创建一个 10G 大小的文件花费了约 8.6 秒

yes

前面的 dd 命令创建的是空字符的文件,如果想文件中包含自定义的字符,可以使用 yes 命令,它的作用是循环输出一行指定的字符串,直到进程结束,为了控制文件的大小并打破循环,我们借助 head 命令来实现,使用 yes 命令创建包含指定内容文件的语法如下

yes [string] | head -c [size of file] > [name of file]

string 是写入文件每一行的字符串

head -c [size of file] 是接收指定大小的字符串,单位是字节,后面也可以接 KKBMMBGGB等单位

下面的实例是往 yesfile 文件写入,每行的内容是: this is a test content , 一直到文件大小达到 10G

[root@localhost dd_cmd]# time yes "this is a test content" | head -c 10G > yesfile

real    0m11.266s
user    0m8.898s
sys     0m13.217s
[root@localhost dd_cmd]# du -h yesfile  
10G     yesfile

从结果可以看出,yes 命令创建一个 10G 的文件花费了 13.2 秒,比 dd 命令慢

fallocate

fallocate 命令使用下面的语法 创建大文件

fallocate -l [size of file] [name of file]

-l 选项表示文件大小,单位是字节,后面可以接 KKBMMBGGB等单位

下面的命令是创建一个 10G 大小的文件

[root@localhost dd_cmd]# time fallocate -l 10G allocatefile

real    0m0.002s
user    0m0.000s
sys     0m0.003s
[root@localhost dd_cmd]# du -h allocatefile  
10G     allocatefile

上述的 time 命令只是为了统计创建文件的时间,从结果可以看出:fallocate命令创建一个 10G 大小的文件竟然只花费了 0.003 秒

命令 du -h allocatefile 是查看创建的文件大小,从结果可知,allocatefile 文件大小确实是 10G

truncate

truncate 命令是缩小或者扩展文件至指定大小,它的语法如下:

truncate -s [file-size] [name of the file]

-s 选项表示文件大小,单位是字节,跟 fallocate 命令一样,后面可以接 KKBMMBGGB等单位

下面是使用 truncate 命令创建一个 10G的文件的示例

[root@localhost dd_cmd]# time truncate -s 10G truncatefile

real    0m0.002s
user    0m0.000s
sys     0m0.002s
[root@localhost dd_cmd]# du -h truncatefile 
0       truncatefile

从结果可以得到,truncate 命令 创建一个 10G的文件也只花费了 0.002 秒,和 fallocate 差不多

但是, du -h truncatefile 命令的结果表明 truncatefile 大小为 0

原因是 truncate 命令 创建的是一个稀疏文件而不是实际的文件 ,稀疏文件不会占用磁盘空间

注意:fallocate 命令只支持 btrfs、ext4、 ocfs2、xfs 这几种文件系统,而 truncate 命令支持所有的现代文件系统

创建速度的差异

从上面的几个实例可以看出,同样是创建一个 10G的文件, fallocatetruncate 命令只需要不到 0.1 秒的时间,但是 dd 命令需要 8.6 秒的时间,yes命令需要 13.2 秒,这中间相差了几百倍,为什么会有这么大的差别呢?

fallocate 将空间分配给文件,但是不会往文件中写入任何数据

truncate 创建的是稀疏文件,和 fallocate 一样,它也不会往文件中写入任何数据

ddyes 都有写文件操作,而这需要大量的 IO 时间,所以同样创建 10G 的文件,它们比 fallocatetruncate 要慢很多

如何选择

ddyesfallocatetruncate 这几个命令都可以创建大文件, 在日常的使用中,我们该如何选择呢 ?

对速度没有很高的要求的情况下,一般首选 dd ,如果希望创建的文件中写入自定义的内容的话,使用 yes

如果想快速的创建大文件,比如 1 秒内创建一个 100G 的文件,选择 fallocatetruncate ,如果还需要确保文件是实际占用磁盘空间的话,就只剩下 fallocate 可选了

大部分情况下,fallocate 都能满足要求,所以不想仔细分析的话,使用 fallocate 就行了

小结

本文介绍了Linux下创建大文件的几种方法,并对所提供的方法进行了比较,最后提供了如何选择使用哪种方法的一些建议,文中只对 ddyesfallocatetruncate 命令做了简要的说明,更多的介绍请参考 man 文档


- EOF -

推荐阅读  点击标题可跳转

1、一文看懂 GDB 调试上层实现

2、计算机网络的 89 个核心概念

3、关于 std::set/std::map 的几个为什么


关注『CPP开发者』

看精选C++技术文章 . 加C++开发者专属圈子

点赞和在看就是最大的支持❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存