用 Go 语言编写的测试硬盘读写速度和内存读写速度的程序。它通过顺序读写大块数据并测量耗时来计算吞吐量(MB/s)。硬盘测试使用常规文件操作并调用 Sync() 确保数据落盘,内存测试分配大切片并通过循环读写防止编译器优化。
package main
import (
"flag"
"fmt"
"io"
"os"
"time"
)
const (
defaultSize = 1 * 1024 * 1024 * 1024 // 1GB
defaultBlock = 1 * 1024 * 1024 // 1MB
)
var (
size = flag.Int64("size", defaultSize, "测试数据总大小(字节)")
block = flag.Int("block", defaultBlock, "每次读写的块大小(字节)")
file = flag.String("file", "speedtest.tmp", "硬盘测试使用的临时文件路径")
)
func main() {
flag.Parse()
fmt.Println("内存读写速度测试...")
memoryWriteSpeed, memoryReadSpeed := memorySpeed(*size, *block)
fmt.Printf("内存写入速度: %.2f MB/s\n", memoryWriteSpeed)
fmt.Printf("内存读取速度: %.2f MB/s\n", memoryReadSpeed)
fmt.Println("\n硬盘读写速度测试...")
diskWriteSpeed, diskReadSpeed, err := diskSpeed(*size, *block, *file)
if err != nil {
fmt.Printf("硬盘测试失败: %v\n", err)
return
}
fmt.Printf("硬盘写入速度: %.2f MB/s\n", diskWriteSpeed)
fmt.Printf("硬盘读取速度: %.2f MB/s\n", diskReadSpeed)
}
// memorySpeed 测试内存读写速度,返回写入速度(MB/s)和读取速度(MB/s)
func memorySpeed(totalSize int64, blockSize int) (writeSpeed, readSpeed float64) {
// 分配内存
data := make([]byte, totalSize)
// 写入测试:逐块填充数据
start := time.Now()
for i := int64(0); i < totalSize; i += int64(blockSize) {
end := i + int64(blockSize)
if end > totalSize {
end = totalSize
}
// 写入块:简单赋值,避免编译器优化
for j := i; j < end; j++ {
data[j] = byte(j)
}
}
elapsed := time.Since(start).Seconds()
writeSpeed = float64(totalSize) / elapsed / 1024 / 1024
// 读取测试:遍历并累加,确保数据被使用
var sum int64
start = time.Now()
for i := int64(0); i < totalSize; i += int64(blockSize) {
end := i + int64(blockSize)
if end > totalSize {
end = totalSize
}
for j := i; j < end; j++ {
sum += int64(data[j])
}
}
elapsed = time.Since(start).Seconds()
readSpeed = float64(totalSize) / elapsed / 1024 / 1024
// 防止 sum 被优化掉
if sum == 0 {
fmt.Println("sum is zero")
}
return
}
// diskSpeed 测试硬盘读写速度,返回写入速度(MB/s)和读取速度(MB/s)
func diskSpeed(totalSize int64, blockSize int, path string) (writeSpeed, readSpeed float64, err error) {
// 创建临时文件
f, err := os.Create(path)
if err != nil {
return
}
defer func() {
f.Close()
os.Remove(path)
}()
// 准备缓冲区
buf := make([]byte, blockSize)
for i := range buf {
buf[i] = byte(i)
}
// 写入测试
start := time.Now()
var written int64
for written < totalSize {
toWrite := int64(blockSize)
if remaining := totalSize - written; remaining < toWrite {
toWrite = remaining
}
n, err := f.Write(buf[:toWrite])
if err != nil {
return 0, 0, fmt.Errorf("写入失败: %v", err)
}
written += int64(n)
}
// 强制写入磁盘
err = f.Sync()
if err != nil {
return 0, 0, fmt.Errorf("同步失败: %v", err)
}
elapsed := time.Since(start).Seconds()
writeSpeed = float64(totalSize) / elapsed / 1024 / 1024
// 读取测试:重新定位到文件开头
_, err = f.Seek(0, io.SeekStart)
if err != nil {
return 0, 0, fmt.Errorf("定位失败: %v", err)
}
// 读取测试
start = time.Now()
var read int64
for read < totalSize {
toRead := int64(blockSize)
if remaining := totalSize - read; remaining < toRead {
toRead = remaining
}
n, err := f.Read(buf[:toRead])
if err != nil && err != io.EOF {
return 0, 0, fmt.Errorf("读取失败: %v", err)
}
read += int64(n)
}
elapsed = time.Since(start).Seconds()
readSpeed = float64(totalSize) / elapsed / 1024 / 1024
return
}使用说明
编译运行:bashgo build speedtest.go ./speedtest
自定义参数通过命令行参数可以调整测试数据大小、块大小和临时文件路径:bash./speedtest -size=2GB -block=4MB -file=/mnt/tmp/test.dat支持的单位:B、KB、MB、GB(如 1GB、512MB),解析由 flag 包自动处理。
注意事项
硬盘测试写测试使用 Write + Sync(),确保数据真正写入磁盘,但 Sync() 的开销会影响速度结果。读测试紧跟在写测试之后,此时数据可能仍在操作系统缓存中,因此测得的读取速度可能远高于实际磁盘读取速度。若想测试纯磁盘读取速度,可在运行程序前手动清空缓存(Linux 下需要 root 权限):bashsync && echo 3 > /proc/sys/vm/drop_caches临时文件默认生成在当前目录,测试后自动删除。
内存测试分配的总大小受可用物理内存限制,过大可能导致系统交换,影响结果准确性。通过累加和防止编译器优化,确保读写操作实际执行。
性能影响测试期间会占用大量 CPU 和 I/O 资源,建议在空闲系统上运行。块大小(-block)影响测试效率,通常设为 1MB 左右即可。
最后
以上就是热心网友最近收集整理的关于用 Go 语言实现一个测试硬盘读写速度和内存读写速度的应用的全部内容,更多相关用内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复