应避免用 std::rand + write 生成大文件,因其随机性差、系统调用多、多线程不安全;推荐用 std::random_device + std::mt19937_64 + std::uniform_int_distribution 批量填充缓冲区后 write,或直接读 /dev/urandom(Linux/macOS),超大文件需先 fallocate 预分配。

用 std::rand 配合 write 生成大文件,速度不快反而容易翻车
直接用 std::rand + write 循环填充,看似简单,实际在 Linux/macOS 下常卡在系统调用开销上,Windows 下还可能因 rand 实现低效拖慢整条流水线。更关键的是:std::rand 默认周期短、低位重复性强,生成的“随机”字节在统计意义上并不均匀——尤其当你要测存储、压缩或加密模块时,这种偏差会掩盖真实问题。
- 别用
srand(time(nullptr))初始化一次就完事:多线程下未加锁会崩,单线程下也只影响低位,rand() % 256生成的字节分布明显偏斜 - 避免每字节调用一次
rand():1GB 文件调用 10⁹ 次函数,光栈帧进出就吃掉可观时间 -
write不带缓冲地小块写入(比如每次 1 字节)会触发大量系统调用,实测比批量写慢 2–3 个数量级
改用 std::random_device + std::uniform_int_distribution 批量预生成
真正快且靠谱的做法是:先用高质量熵源初始化生成器,再批量产出固定大小的缓冲区(如 64KB),最后用 write 一次性刷出。这样既避开 rand 的缺陷,又压低系统调用频次。
-
std::random_device在多数现代系统上对接硬件 RNG 或内核熵池,比time()种子强得多 - 用
std::uniform_int_distribution直接生成字节数组,避免%运算引入偏差 - 缓冲区大小设为 4KB–64KB:太小起不到批处理作用,太大可能触发 malloc 延迟或内存碎片
#include <random>
#include <unistd.h>
#include <fcntl.h><p>int fd = open("test.bin", O_WRONLY | O_CREAT, 0644);
std::random_device rd;
std::mt19937_64 gen(rd());
std::uniform_int_distribution<uint8_t> dist;</uint8_t></p>
<p>const size_t buf_size = 65536;
std::vector<uint8_t> buf(buf_size);
for (size_t written = 0; written </uint8_t></p></fcntl.h></unistd.h></random>
绕过 C++ 标准库,用 /dev/urandom 直读(Linux/macOS)
如果只要“够用的随机性”,且目标平台确定支持 /dev/urandom,这是最简最快路径——内核已做好缓冲与批处理,用户态几乎零计算开销。
- 打开
/dev/urandom后反复read,比自己生成快 3–5 倍(实测 1GB 耗时从 1.8s 降到 0.4s) - 注意
read可能返回少于请求长度,必须循环直到填满缓冲区 - Windows 上不可用,得 fallback 到
CryptGenRandom或BCryptGenRandom,接口差异大,别硬套
int urand_fd = open("/dev/urandom", O_RDONLY);
ssize_t total = 0;
while (total <h3>生成超大文件(>10GB)时,<code>fallocate</code> 预分配再覆写更稳</h3><p>直接 <code>write</code> 写 20GB,遇到机械盘或某些文件系统(如 ext3)可能因元数据更新阻塞,甚至中途 <code>ENOSPC</code>。先 <code>fallocate</code> 划出空间,再随机覆写,既能保大小精确,又能规避碎片和延迟突刺。</p>
-
fallocate(fd, 0, 0, size)在支持的文件系统上是纯元数据操作,毫秒级完成 - 之后仍要用上面任一方式往里填内容,
fallocate不等于“已写入”,只是预留了磁盘块 - macOS 用
ftruncate+posix_fallocate替代,后者在 HFS+ 上可能失败,得降级处理
生成大文件这事,核心不是“怎么填随机数”,而是“别让随机性拖慢 I/O,也别让 I/O 掩盖随机性缺陷”。越往后做性能压测或模糊测试,越要盯住这两头的细节——比如 std::mt19937_64 的状态大小、/dev/urandom 的读取边界、甚至 write 返回值是否真等于请求长度。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











