实例介绍
模拟 dd 命令测试磁盘 IO 性能 (IOPS 和 吞吐量)。
使用 O_DIRECT 绕过系统缓存,以测试物理磁盘性能。
【实例截图】
root@ubuntu:/tmp/iotest# ./io_test
检查目录: /tmp
剩余空间: 9.48 GB
错误: 空间不足!需要至少 10 GB。
root@ubuntu:/tmp/iotest# ./io_test /data
检查目录: /data
剩余空间: 208.31 GB
------------------------------------------------
正在执行: 写入测试 (Write)...
参数模拟: bs=1M count=10000 (Total 10GB)
耗时 : 183.99 秒
IOPS : 54.35
吞吐量 : 54.35 MB/s
------------------------------------------------
------------------------------------------------
正在执行: 读取测试 (Read)...
参数模拟: bs=1M count=10000 (Total 10GB)
耗时 : 37.93 秒
IOPS : 263.63
吞吐量 : 263.63 MB/s
------------------------------------------------
正在清理测试文件...
测试完成。
root@ubuntu:/tmp/iotest#
参数:
TARGET_DIR (可选) 测试文件的存放目录。默认为 /tmp。
流程:
1. 检查剩余空间 (需 > 10GB)。
2. 写入测试: 模拟 dd if=/dev/zero of=... bs=1M count=10000
3. 读取测试: 模拟 dd if=... of=/dev/zero bs=1M
4. 清理测试文件。
【核心代码】
// 执行 IO 测试核心逻辑
// is_write: true 为写测试,false 为读测试
void perform_test(const std::string& filepath, bool is_write) {
int fd;
void* buffer;
// 1. 分配对齐的内存 (O_DIRECT 要求)
if (posix_memalign(&buffer, ALIGNMENT, BLOCK_SIZE) != 0) {
std::cerr << "错误: 内存分配失败" << std::endl;
exit(1);
}
// 初始化缓冲区数据 (模拟 /dev/zero)
memset(buffer, 0, BLOCK_SIZE);
// 2. 打开文件
int flags = O_DIRECT;
if (is_write) {
flags |= O_WRONLY | O_CREAT | O_TRUNC;
// 使用 sync 确保数据落盘,更接近物理 IO 语义
flags |= O_SYNC;
fd = open(filepath.c_str(), flags, 0644);
} else {
flags |= O_RDONLY;
fd = open(filepath.c_str(), flags);
}
if (fd < 0) {
std::cerr << "错误: 无法打开文件 " << filepath << " (模式: " << (is_write ? "Write" : "Read") << ")" << std::endl;
std::cerr << "原因: " << strerror(errno) << std::endl;
if (errno == EINVAL) {
std::cerr << "提示: 目标文件系统可能不支持 O_DIRECT (例如 tmpfs),请尝试指定物理磁盘挂载点。" << std::endl;
}
free(buffer);
exit(1);
}
std::cout << "------------------------------------------------" << std::endl;
std::cout << "正在执行: " << (is_write ? "写入测试 (Write)" : "读取测试 (Read)") << "..." << std::endl;
std::cout << "参数模拟: bs=1M count=" << BLOCK_COUNT << " (Total 10GB)" << std::endl;
// 3. 计时开始
auto start_time = std::chrono::high_resolution_clock::now();
// 4. 执行循环 IO
ssize_t ret;
for (size_t i = 0; i < BLOCK_COUNT; i) {
if (is_write) {
ret = write(fd, buffer, BLOCK_SIZE);
} else {
ret = read(fd, buffer, BLOCK_SIZE);
}
if (ret != (ssize_t)BLOCK_SIZE) {
std::cerr << "错误: IO 操作失败,在块 " << i << std::endl;
std::cerr << "原因: " << strerror(errno) << std::endl;
close(fd);
free(buffer);
exit(1);
}
}
// 5. 计时结束
// 如果是写操作,再次 sync 确保所有元数据也完成
if (is_write) fsync(fd);
auto end_time = std::chrono::high_resolution_clock::now();
close(fd);
free(buffer);
// 6. 计算结果
std::chrono::duration<double> elapsed = end_time - start_time;
double seconds = elapsed.count();
double total_mb = (double)(BLOCK_COUNT * BLOCK_SIZE) / (1024 * 1024);
double iops = BLOCK_COUNT / seconds;
double throughput_mb = total_mb / seconds;
// 7. 输出结果
std::cout << "耗时 : " << seconds << " 秒" << std::endl;
std::cout << "IOPS : " << std::fixed << std::setprecision(2) << iops << std::endl;
std::cout << "吞吐量 : " << throughput_mb << " MB/s" << std::endl;
std::cout << "------------------------------------------------" << std::endl;
}
标签: IO_TEST
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论