⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hdperf.c

📁 在EMBEDDED LINUX中测试HDD效能的程序
💻 C
字号:
/* hdbench.c  * * $Id: hdperf.c,v 1.5 2005/02/23 23:24:35 nil Exp $ * * Copyright (C) 1999-2004 Nathan Laredo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#define _LARGEFILE64_SOURCE#include <errno.h>#include <fcntl.h>#include <signal.h>#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/time.h>#include <sys/types.h>#include <sys/mount.h>#include <sys/ioctl.h>#define MAX_BUF		1048576#define N_ZONES		64static float zone_perf[N_ZONES];	/* surface performance bins */static uint8_t buf[MAX_BUF];		/* transfer buffer */static int impatient = 0;	/* max number of seconds to run each test */static void do_random_test(int fd, int xfer_size, int max_lba, int count){	off64_t off64;	int i, lba, cdiv;	struct timeval tv_start, tv_end;	uint64_t len;	if (xfer_size > MAX_BUF) {		fprintf(stderr, "Illegal transfer size requested\n");		exit(1);	}	cdiv = count / 32;	/* show 32 status updates */	gettimeofday(&tv_start, NULL);	for (i = 0; i < count; i++) {		lba = rand() % max_lba;		off64 = (uint64_t)lba << 9;		if (lseek64(fd, off64, SEEK_SET) < 0) {			perror("seek");		}		if ((i % cdiv) == 0 || i == count - 1) {			if (xfer_size == 1) {				printf("\r%3d%% of %d random seek test"					" @ LBA %9d...", (100 * i) /					(count - 1), count, lba);			} else {				printf("\r%3d%% of %d random %d byte read"					" @ LBA %9d...", (100 * i) /					(count - 1), count, xfer_size, lba);			}			fflush(stdout);		}		if (read(fd, buf, xfer_size) < xfer_size) {			perror("read");		}		if (i > 1 && impatient) {			gettimeofday(&tv_end, NULL);			timersub(&tv_end, &tv_start, &tv_end);			if (tv_end.tv_sec >= impatient)				break;		}	}	count = i;	gettimeofday(&tv_end, NULL);	timersub(&tv_end, &tv_start, &tv_end);	len = (uint64_t)count * (uint64_t)xfer_size;	if (xfer_size == 1) {		printf("\r%d random seeks in %d.%03d sec, %.1fms "			"average seek time\n", count, (int)tv_end.tv_sec,			(int)(tv_end.tv_usec / 1000), 1000.0 *			((float)tv_end.tv_sec + (float)tv_end.tv_usec /			1000000.0) / (float)(count));		return;	}	printf("\r%d random %d byte block reads done in %d.%03d sec,"		" %.3f KB/sec\n", count, xfer_size, (int)tv_end.tv_sec,		(int)(tv_end.tv_usec / 1000), (float)(len >> 10) /		((float)tv_end.tv_sec + (float)tv_end.tv_usec / 1000000.0));}static void do_seq_test(int fd, int xfer_size, int start_lba, int count){	off64_t off64;	int i, cdiv;	struct timeval tv_start, tv_end;	uint64_t len;	if (xfer_size > MAX_BUF) {		fprintf(stderr, "Illegal transfer size requested\n");		exit(1);	}	cdiv = count / 32;	/* show 32 status updates */	off64 = (uint64_t)start_lba << 9;	if (lseek64(fd, off64, SEEK_SET) < 0) {		perror("seek");	}	/* make sure the seek has taken effect */	if (read(fd, buf, 512) < 512) {		perror("read");	}	gettimeofday(&tv_start, NULL);	for (i = 0; i < count; i++) {		if ((i % cdiv) == 0 || i == count - 1) {			printf("\r%3d%% of %d sequential %d byte read "				"@ LBA %9d...", (100 * i) / (count - 1),				count, xfer_size, start_lba + i);			fflush(stdout);		}		if (read(fd, buf, xfer_size) < xfer_size) {			perror("read");		}		if (i > 1 && impatient) {			gettimeofday(&tv_end, NULL);			timersub(&tv_end, &tv_start, &tv_end);			if (tv_end.tv_sec >= impatient)				break;		}	}	count = i;	gettimeofday(&tv_end, NULL);	timersub(&tv_end, &tv_start, &tv_end);	len = (uint64_t)count * (uint64_t)xfer_size;	printf("\r%d sequential %d byte block reads done in %d.%03d sec,"		" %.3f KB/sec\n", count, xfer_size, (int)tv_end.tv_sec,		(int)(tv_end.tv_usec / 1000), (float)(len >> 10) /		((float)tv_end.tv_sec + (float)tv_end.tv_usec / 1000000.0));}static void do_zone_test(int fd, int start_lba, int zone, int count){	off64_t off64;	struct timeval tv_start, tv_end;	uint64_t len;	int i, cdiv;	off64 = (uint64_t)start_lba << 9;	if (lseek64(fd, off64, SEEK_SET) < 0) {		perror("seek");	}	/* make sure the seek has taken effect */	if (read(fd, buf, 512) < 512) {		perror("read");	}	cdiv = count / 32;	/* show 32 status updates */	gettimeofday(&tv_start, NULL);	for (i = 0; i < count; i++) {		if (read(fd, buf, MAX_BUF) < MAX_BUF) {			perror("read");		}		gettimeofday(&tv_end, NULL);		timersub(&tv_end, &tv_start, &tv_end);		len = (uint64_t)(i + 1) * (uint64_t)MAX_BUF;		if ((i % cdiv) == 0 || i == count - 1) {			printf("\r%3d%% of %d zone %d read @ "				"LBA %9d, %10.3f KB/sec...",				(100 * i) / (count - 1), count, zone,				start_lba + i, (float)(len >> 10) /				((float)tv_end.tv_sec +				(float)tv_end.tv_usec / 1000000.0));			fflush(stdout);		}		if (impatient) {			if (tv_end.tv_sec >= impatient)				break;		}	}	zone_perf[zone] = (float)(len >> 10) /		((float)tv_end.tv_sec + (float)tv_end.tv_usec / 1000000.0);}static void draw_zone_chart(int lba_delta){	int i, line;	float min = 1.0e+30F, max = -1.0e+30F, delta, cur;	for (i = 0; i < N_ZONES; i++) {		if (zone_perf[i] < min)			min = zone_perf[i];		if (zone_perf[i] > max)			max = zone_perf[i];	}	delta = (max - min) / 20.0F;	printf("\rMin transfer rate = %.3f, max transfer rate = %.3f\n",		min, max);	for (line = 0; line < 21; line++) {		cur = min + delta * (20 - line);		printf("%10.3f", cur);		for (i = 0; i < N_ZONES; i++) {			if (zone_perf[i] < cur)				putchar(' ');			else				putchar('|');		}		putchar('\n');	}	printf("KB/sec^^^ ");	for (i = 0; i < N_ZONES; i++) {		putchar('0' + i / 10);	}	printf("\nZone>>>   ");	for (i = 0; i < N_ZONES; i++) {		putchar('0' + i % 10);	}	putchar('\n');}static void flush_buffers(int fd){	if (ioctl(fd, BLKFLSBUF, 0) < 0) {		perror("ioctl(fd, BLKFLSBUF, 0)");	}}int main(int argc, char **argv){	int f, i, max_lba, zone_size;	off64_t off64;	printf("$Id: hdperf.c,v 1.5 2005/02/23 23:24:35 nil Exp $\n");	if (argc < 2) {		fprintf(stderr, "usage: %s [device] [secs]\n", argv[0]);		exit(1);	}	if (argc > 2) {		impatient = strtoul(argv[2], NULL, 0);		if (impatient <= 0) {			impatient = 0;			printf("impatient timeout disabled\n");		} else {			printf("impatient = %d second timeout\n", impatient);		}	}	if ((f = open64(argv[1], O_RDONLY)) < 0) {		perror(argv[1]);		exit(1);	}	off64 = 0;	if ((off64 = lseek64(f, off64, SEEK_END)) < 0) {		perror("seek");		exit(1);	}	max_lba = (int)(off64 >> 9);	zone_size = max_lba / (N_ZONES + 1);	printf("%s: %d blocks (%dGiB)\n", argv[1], max_lba, max_lba >> 21);	max_lba -= (MAX_BUF >> 9);	/* fluff at end to make math easy */	for (i = 9; i < 21; i++) {		flush_buffers(f);		do_seq_test(f, 1 << (29 - i), max_lba >> 1, 1 << (i - 2));	}	flush_buffers(f);	do_random_test(f, 1, max_lba, 512);	for (i = 9; i < 21; i++) {		flush_buffers(f);		do_random_test(f, 1 << i, max_lba, 128);	}	for (i = 0; i < N_ZONES; i++) {		/* note: this assumes MAX_BUF == 1MB */		do_zone_test(f, i * zone_size, i, zone_size >> 11);	}	draw_zone_chart(zone_size);	exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -