Python磁盘测速脚本与CrystalDiskMark结果差异及优化问询
磁盘测速脚本与CrystalDiskMark结果差异问题解答
背景
我编写了一个用于检测选定磁盘速度的Python脚本(共103行),核心读写代码如下:
写入核心代码
# Write start_time_w = time.time() with open (location, "w") as f: try: f.write("0" * 1000 * 1000 * size) # We want size in MiB // size is int(64) f.close() finish_time_w = time.time() except Exception as e: # try removing the file if it was created try: f.close(), os.remove(location) except OSError: pass print(f"Something went wrong...\n{e}") input() return time_taken = round(finish_time_w-start_time_w, 1) print(f"Wrote {size}MiB in {time_taken} ({round(size/time_taken, 2)}MiB/s)")
读取核心代码
# Read start_time_r = time.time() with open (location, "r") as f: try: f.read() f.close() finish_time_r = time.time() except Exception as e: # try removing the file try: f.close(), os.remove(location) except OSError: pass print(f"Something went wrong...\n{e}") input() return time_taken = finish_time_r-start_time_r print(f"Read {round(size, 1)}MiB in {time_taken}s ({round(size/time_taken, 2)}MiB/s)")
我用该脚本和CrystalDiskMark(CDM)对Patriot 1633 PHMPH型号USB移动磁盘(盘符X:)做测试,条件均为无后台、读写64MiB数据,但结果差异显著,有以下疑问:
- 为何脚本写入结果与CDM四种测试均不匹配?
- 为何脚本读取速度远高于CDM?
- 如何解决这些差异问题?
注:已知CDM单位为MiB/MB/s,脚本均为MiB,单位差异不足以导致此差距
问题解答
1. 脚本写入结果与CDM不匹配的原因
- 缓存机制差异:Python的
f.write()会先将数据写入操作系统缓存,f.close()虽触发缓存刷新,但系统可能仍延迟真正的磁盘写入;而CDM会主动控制缓存(如用非缓存I/O、同步写入),直接测试磁盘真实写入性能。 - 数据生成开销:脚本在内存中构造超大重复字符串,字符串的构造、拷贝过程会消耗额外时间,这部分被算入写入耗时,导致结果失真。
- 测试逻辑不同:CDM的四种测试对应不同队列深度、线程数、读写模式(连续/随机),而脚本仅为单线程连续写入,逻辑完全不同,结果自然无法匹配。
2. 脚本读取速度远高于CDM的原因
- 缓存命中:脚本写入后立即读取,数据大概率还在操作系统页缓存中,读取直接从内存获取,而非磁盘;CDM会规避缓存影响,确保测试磁盘真实读取性能。
- 读取方式差异:
f.read()一次性读取整个文件到内存,操作系统会做极致优化;而CDM采用更贴近实际场景的分块、多线程或随机读取模式,这类模式的速度本就比单线程读缓存慢。
3. 解决差异的方法
针对写入测试:
- 绕过操作系统缓存:打开文件时使用直接I/O标志(Linux用
os.O_DIRECT,Windows用win32file.FILE_FLAG_NO_BUFFERING),强制数据直接写入磁盘。 - 优化数据写入方式:避免构造超大字符串,改用分块写入(如每次写4KB/64KB字节块),减少内存占用和数据生成开销。
- 模拟CDM测试逻辑:根据CDM的测试模式调整脚本,比如实现多线程写入、随机位置写入、不同队列深度的测试。
- 精准计时:在
f.close()后调用os.fsync()强制刷新缓存到磁盘,再结束计时,确保只统计真实磁盘写入时间。
针对读取测试:
- 清理缓存后再测试:读取前清理操作系统缓存(Linux执行
sync && echo 3 > /proc/sys/vm/drop_caches,Windows可使用第三方工具或重启),确保读取的是磁盘数据。 - 分块读取文件:模仿CDM的分块读取方式,循环读取固定大小的块直到文件结束,而非一次性读取整个文件。
- 使用直接I/O读取:读取时同样启用直接I/O标志,绕过缓存,测试磁盘真实读取性能。
内容的提问来源于stack exchange,提问作者Oskar
相关产品推荐
相关产品推荐

