应使用 std::random_device 与 std::mt19937 组合生成可复现、高吞吐、低开销的随机字节:用 std::random_device 初始化 mt19937 种子,配合 uint8_t 均匀分布批量填充缓冲区(64KB–1MB),再一次性写入磁盘,并校验错误、预分配空间、调用 fsync() 确保真实 I/O 性能。
用
和
生成高质量随机字节
性能测试需要的是**可复现、高吞吐、低开销**的随机数据,不是密码学安全级别。直接用
不仅分布不均、周期短,还可能因未调用
导致每次运行都生成相同序列——这会让测试结果完全失真。
正确做法是组合
(用于种子)和
(Mersenne Twister,快且均匀):
在多数平台(Linux / Windows MSVC / Clang)会读取系统熵源,比
可靠得多
用
分布而非
,避免高位零填充导致写入时出现大量
字节(影响 I/O 模式判断)
不要在循环里反复构造
或
,它们不是轻量对象
批量生成比逐字节写入快 10 倍以上
对一个 1GB 文件,如果每字节调用一次
再写入磁盘,
系统调用次数达 10⁹ 次,内核上下文切换开销压倒一切。必须用缓冲区批量处理。
分配一块 64KB~1MB 的
缓冲区(太小没收益,太大易触发 NUMA 问题)
用
填充整块缓冲区:
用
或
一次性刷出,避免
流操作(带格式化开销)
Linux 下可加
标志跳过页缓存(需对齐内存和文件偏移),但只在测裸设备或绕过缓存时才启用
生成结构化伪随机内容(如 JSON 行、CSV)要控制字段长度和分隔符
纯二进制随机数据无法验证解析器行为,真实性能测试常需“看起来像数据”的内容。例如生成 100 万行 JSON,每行含
、
、
字段。
C知道
CSDN推出的一款AI技术问答工具
下载
立即学习
“
C++免费学习笔记(深入)
”;
不要用
拼接每行:堆分配 + 复制开销巨大;改用预分配缓冲区 +
或
(C++20)写入固定位置
名字字段可用随机长度(3–12 字节)+ 随机 ASCII 字母填充,避免全空或超长字符串干扰测试焦点
时间戳建议用递增 base + 小范围随机偏移(如
),保证单调性便于后续排序验证
换行符必须显式写入
,Windows 下若用
会多占 1 字节/行,影响总大小精度
注意文件系统和 libc 的实际限制
生成几十 GB 文件时,
默认行为可能让你掉坑里:它不检查磁盘空间,也不处理
错误,写失败后
被设但程序照常退出。
每次
后检查返回值,
大文件建议用
(Linux)或
(Windows)预先分配空间,避免碎片和写时扩展延迟
glibc 的
在缓冲区满时自动 flush,但 musl 或某些嵌入式 libc 不一定;显式调用
更稳妥
生成完成后务必调用
—— 否则你测的其实是 page cache 写入速度,不是磁盘真实吞吐
真正难的从来不是“怎么生成随机数”,而是让生成过程不成为性能瓶颈本身,以及确保生成的数据能准确反映你要测的那个环节的真实压力。
std::random_devicestd::mt19937rand()srand()std::random_devicestd::mt19937std::random_device rd;
std::mt19937 gen(rd()); // 避免用 time(0) 做种子
std::uniform_int_distribution dist(0, 255);
std::random_devicetime(0)uint8_tint0x00gendistdist(gen)write()std::vectorstd::generatestd::generate(buf.begin(), buf.end(), [&]{ return dist(gen); });write()fwrite()<<O_DIRECT"id""name""ts"std::stringsnprintfstd::formatbase_ts + dist_small(gen) % 1000\n\r\nstd::ofstreamENOSPCfailbitwrite()if (written != expected) { perror("write"); exit(1); }posix_fallocate()SetFileInformationByHandle()fwritefflush()fsync()