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

📄 bonnie.c

📁 磁盘的基准测试程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * This is a file system benchmark which attempts to study bottlenecks - * it is named 'Bonnie' after Bonnie Raitt, who knows how to use one. * * Commentary on Bonnie's operations may be found at  * http://www.textuality.com/bonnie/intro.html * * COPYRIGHT NOTICE:  * Copyright (c) Tim Bray, 1990-1996. * * Everybody is hereby granted rights to use, copy, and modify this program,  *  provided only that this copyright notice and the disclaimer below *  are preserved without change. * DISCLAIMER: * This program is provided AS IS with no warranty of any kind, and * The author makes no representation with respect to the adequacy of this *  program for any particular purpose or with respect to its adequacy to  *  produce any particular result, and * The author shall not be liable for loss or damage arising out of *  the use of this program regardless of how sustained, and * In no event shall the author be liable for special, direct, indirect *  or consequential damage, loss, costs or fees or expenses of any *  nature or kind. */#include <unistd.h>#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/time.h>#if defined(SysV)#include <limits.h>#include <sys/times.h>#else#include <sys/resource.h>#endif#define IntSize (sizeof(int))/* * N.B. in seeker_reports, CPU appears and Start/End time, but not Elapsed, *  so position 1 is re-used; icky data coupling. */#define CPU (0)#define Elapsed (1)#define StartTime (1)#define EndTime (2)#define Seeks (4000)#define UpdateSeek (10)#define SeekProcCount (3)#define Chunk (16384)/* labels for the tests, used as an array index */typedef enum{  Putc, ReWrite, FastWrite, Getc, FastRead, Lseek, TestCount} tests_t;static double cpu_so_far();static void   doseek(off_t where, int fd, int update);static void   get_delta_t(tests_t test);static void   io_error(char * message);static void   newfile(char * name, int * fd, FILE * * stream, int create);#if defined(SysV)/* System V wrappers for randomizers */static long   random();static void   srandom(int seed);#endifstatic void   report(char * machine, off_t size);static void   write_html(char * machine, off_t size);static double time_so_far();static void   timestamp();static void   usage();/*  * Housekeeping variables to build up timestamps for the tests; *  global to make it easy to keep track of the progress of time. * all of this could have been done with non-global variables, *  but the code is easier to read this way and I don't anticipate *  much software engineering down the road  */static int    basetime;                  /* when we started */static double delta[(int) TestCount][2]; /* array of DeltaT values */static double last_cpustamp = 0.0;       /* for computing delta-t */static double last_timestamp = 0.0;      /* for computing delta-t */main(  int    argc,  char * argv[]){  int    buf[Chunk / IntSize];  int    bufindex;  int    chars[256];  int    child;  char * dir;  int    html = 0;  int    fd;  double first_start;  double last_stop;  int    lseek_count = 0;  char * machine;  char   name[Chunk];  int    next;  int    seek_control[2];  int    seek_feedback[2];  char   seek_tickets[Seeks + SeekProcCount];  double seeker_report[3];  off_t  size;  FILE * stream;  off_t  words;  fd = -1;  basetime = (int) time((time_t *) NULL);  size = 100;  dir = ".";  machine = "";  /* pick apart args */  for (next = 1; next < argc; next++)    if (strcmp(argv[next], "-d") == 0)      dir = argv[++next];    else if (strcmp(argv[next], "-s") == 0)      size = atol(argv[++next]);    else if (strcmp(argv[next], "-m") == 0)      machine = argv[++next];    else if (strcmp(argv[next], "-html") == 0)      html = 1;    else      usage();  if (size < 1)    usage();  /* sanity check - 32-bit machines can't handle more than 2047 Mb */  if (sizeof(off_t) <= 4 && size > 2047)  {    fprintf(stderr, "File too large for 32-bit machine, sorry\n");    exit(1);  }  sprintf(name, "%s/Bonnie.%d", dir, getpid());  /* size is in meg, rounded down to multiple of Chunk */  size *= (1024 * 1024);  size = Chunk * (size / Chunk);  fprintf(stderr, "File '%s', size: %ld\n", name, size);  /* Fill up a file, writing it a char at a time with the stdio putc() call */  fprintf(stderr, "Writing with putc()...");  newfile(name, &fd, &stream, 1);  timestamp();  for (words = 0; words < size; words++)    if (putc(words & 0x7f, stream) == EOF)      io_error("putc");    /*   * note that we always close the file before measuring time, in an   *  effort to force as much of the I/O out as we can   */  if (fclose(stream) == -1)    io_error("fclose after putc");  get_delta_t(Putc);  fprintf(stderr, "done\n");  /* Now read & rewrite it using block I/O.  Dirty one word in each block */  newfile(name, &fd, &stream, 0);  if (lseek(fd, (off_t) 0, 0) == (off_t) -1)    io_error("lseek(2) before rewrite");  fprintf(stderr, "Rewriting...");  timestamp();  bufindex = 0;  if ((words = read(fd, (char *) buf, Chunk)) == -1)    io_error("rewrite read");  while (words == Chunk)  { /* while we can read a block */    if (bufindex == Chunk / IntSize)      bufindex = 0;    buf[bufindex++]++;    if (lseek(fd, (off_t) -words, 1) == -1)      io_error("relative lseek(2)");    if (write(fd, (char *) buf, words) == -1)      io_error("re write(2)");    if ((words = read(fd, (char *) buf, Chunk)) == -1)      io_error("rwrite read");  } /* while we can read a block */  if (close(fd) == -1)    io_error("close after rewrite");  get_delta_t(ReWrite);  fprintf(stderr, "done\n");  /* Write the whole file from scratch, again, with block I/O */  newfile(name, &fd, &stream, 1);  fprintf(stderr, "Writing intelligently...");  for (words = 0; words < Chunk / IntSize; words++)    buf[words] = 0;  timestamp();  for (words = bufindex = 0; words < (size / Chunk); words++)  { /* for each word */    if (bufindex == (Chunk / IntSize))      bufindex = 0;    buf[bufindex++]++;    if (write(fd, (char *) buf, Chunk) == -1)      io_error("write(2)");  } /* for each word */  if (close(fd) == -1)    io_error("close after fast write");  get_delta_t(FastWrite);  fprintf(stderr, "done\n");  /* read them all back with getc() */  newfile(name, &fd, &stream, 0);  for (words = 0; words < 256; words++)    chars[words] = 0;  fprintf(stderr, "Reading with getc()...");  timestamp();  for (words = 0; words < size; words++)  { /* for each byte */    if ((next = getc(stream)) == EOF)      io_error("getc(3)");    /* just to fool optimizers */    chars[next]++;  } /* for each byte */  if (fclose(stream) == -1)    io_error("fclose after getc");  get_delta_t(Getc);  fprintf(stderr, "done\n");  /* use the frequency count */  for (words = 0; words < 256; words++)    sprintf((char *) buf, "%d", chars[words]);  /* Now suck it in, Chunk at a time, as fast as we can */  newfile(name, &fd, &stream, 0);  if (lseek(fd, (off_t) 0, 0) == -1)    io_error("lseek before read");  fprintf(stderr, "Reading intelligently...");  timestamp();  do  { /* per block */    if ((words = read(fd, (char *) buf, Chunk)) == -1)      io_error("read(2)");    chars[buf[abs(buf[0]) % (Chunk / IntSize)] & 0x7f]++;  } /* per block */  while (words);  if (close(fd) == -1)    io_error("close after read");  get_delta_t(FastRead);  fprintf(stderr, "done\n");  /* use the frequency count */  for (words = 0; words < 256; words++)    sprintf((char *) buf, "%d", chars[words]);  /*   * Now test random seeks; first, set up for communicating with children.   * The object of the game is to do "Seeks" lseek() calls as quickly   *  as possible.  So we'll farm them out among SeekProcCount processes.   *  We'll control them by writing 1-byte tickets down a pipe which   *  the children all read.  We write "Seeks" bytes with val 1, whichever   *  child happens to get them does it and the right number of seeks get   *  done.   * The idea is that since the write() of the tickets is probably   *  atomic, the parent process likely won't get scheduled while the   *  children are seeking away.  If you draw a picture of the likely   *  timelines for three children, it seems likely that the seeks will   *  overlap very nicely with the process scheduling with the effect   *  that there will *always* be a seek() outstanding on the file.   * Question: should the file be opened *before* the fork, so that   *  all the children are lseeking on the same underlying file object?   */  if (pipe(seek_feedback) == -1 || pipe(seek_control) == -1)    io_error("pipe");  for (next = 0; next < Seeks; next++)    seek_tickets[next] = 1;  for ( ; next < (Seeks + SeekProcCount); next++)    seek_tickets[next] = 0;  /* launch some parallel seek processes */  for (next = 0; next < SeekProcCount; next++)  { /* for each seek proc */    if ((child = fork()) == -1)      io_error("fork");    else if (child == 0)    { /* child process */      /* set up and wait for the go-ahead */      close(seek_feedback[0]);      close(seek_control[1]);      newfile(name, &fd, &stream, 0);      srandom(getpid());      fprintf(stderr, "Seeker %d...", next + 1);      /* wait for the go-ahead */

⌨️ 快捷键说明

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