我是靠谱客的博主 热心网友,这篇文章主要介绍用 Go 语言实现一个测试硬盘读写速度和内存读写速度的应用,现在分享给大家,希望可以做个参考。

用 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
}

使用说明

  1. 编译运行:bashgo build speedtest.go ./speedtest

  2. 自定义参数通过命令行参数可以调整测试数据大小、块大小和临时文件路径: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 语言实现一个测试硬盘读写速度和内存读写速度的应用的全部内容,更多相关内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(4)

评论列表共有 0 条评论

立即
投稿
返回
顶部