?? hdperf.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 + -