// memory speed benchmark. // started: december 2003 // // written by Ivaylo Kroumov. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <unistd.h> #include <time.h> #include <sys/times.h> #include <sys/types.h>
#define DIFF_SMALL_MSG "*** no time diff"
#define KB (1024LL) #define MB (KB * KB)
void fatal (const char *format, ...) { va_list args;
fflush (stdout); va_start (args, format); vfprintf (stderr, format, args); fprintf (stderr, "\n"); va_end (args); exit (-1); }
char *cvtsze (u_long s) { double ds = s; int i = 0; static char b [64];
if (ds >= KB) { ds /= KB; i++; if (ds >= KB) { ds /= KB; i++; } } sprintf (b, "%5.2f ", ds);
switch (i) { case 1: strcat (b, "K"); break; case 2: strcat (b, "M"); } return b; }
u_long test_beg = 300 * MB; // start from u_long test_end = 400 * MB; // test to u_long test_step = 10 * MB; // test step u_long test_lups = 2; // test loops
int main (int argc, char *argv []) { u_long size, i, j; register u_long d; volatile u_long *mem; struct tms tms; time_t start, stop, diff; long long rdiff, wdiff, total; int oc;
// parses the command line. while ((oc = getopt (argc, argv, "f:t:s:l:?")) != -1) switch (oc) { case 'f': test_beg = atol (optarg) * MB; break;
case 't': test_end = atol (optarg) * MB; break;
case 's': test_step = atol (optarg) * MB; break;
case 'l': test_lups = atol (optarg); break;
case '?': default: fatal ("usage: %s " "[-f <from mb>] " "[-t <to mb>] " "[-s <step mb>]" "[-l <loops>]", argv [0]); } argc -= optind; argv += optind;
if (test_beg < 1) fatal ("invalid starting size."); if (test_end < test_beg) fatal ("invalid ending size."); if ((test_step < 1) || (test_step > (test_end - test_beg))) fatal ("invalid step size."); if (test_lups < 1) fatal ("invalid number of loops.");
printf ("%10s: %15sB\n", "start from", cvtsze (test_beg)); printf ("%10s: %15sB\n", "test to", cvtsze (test_end)); printf ("%10s: %15sB\n", "step", cvtsze (test_step)); printf ("%10s: %14s\n", "loops", cvtsze (test_lups));
mem = malloc (test_end); if (! mem) fatal ("malloc() failed to alloc %sB", cvtsze (test_end));
printf ("\n" "mapping memory... "); fflush (stdout); memset ((void *) mem, 0, test_end); printf ("done.\n");
printf ("\n" "%21s " "%23s" "%23s" "\n", "size", "write speed", "read speed");
total = rdiff = wdiff = 0; for (size = test_beg; size <= test_end; size += test_step) {
printf ("%20sB ", cvtsze (size)); fflush (stdout);
times (& tms); start = tms. tms_utime; for (i = 0; i < test_lups; i++) { for (j = 0; j < size / sizeof (u_long); j += 64) { mem [j + 0x0] = 0; mem [j + 0x1] = 0; mem [j + 0x2] = 0; mem [j + 0x3] = 0; mem [j + 0x4] = 0; mem [j + 0x5] = 0; mem [j + 0x6] = 0; mem [j + 0x7] = 0; mem [j + 0x8] = 0; mem [j + 0x9] = 0; mem [j + 0xa] = 0; mem [j + 0xb] = 0; mem [j + 0xc] = 0; mem [j + 0xd] = 0; mem [j + 0xe] = 0; mem [j + 0xf] = 0;
mem [j + 0x10] = 0; mem [j + 0x11] = 0; mem [j + 0x12] = 0; mem [j + 0x13] = 0; mem [j + 0x14] = 0; mem [j + 0x15] = 0; mem [j + 0x16] = 0; mem [j + 0x17] = 0; mem [j + 0x18] = 0; mem [j + 0x19] = 0; mem [j + 0x1a] = 0; mem [j + 0x1b] = 0; mem [j + 0x1c] = 0; mem [j + 0x1d] = 0; mem [j + 0x1e] = 0; mem [j + 0x1f] = 0;
mem [j + 0x20] = 0; mem [j + 0x21] = 0; mem [j + 0x22] = 0; mem [j + 0x23] = 0; mem [j + 0x24] = 0; mem [j + 0x25] = 0; mem [j + 0x26] = 0; mem [j + 0x27] = 0; mem [j + 0x28] = 0; mem [j + 0x29] = 0; mem [j + 0x2a] = 0; mem [j + 0x2b] = 0; mem [j + 0x2c] = 0; mem [j + 0x2d] = 0; mem [j + 0x2e] = 0; mem [j + 0x2f] = 0;
mem [j + 0x30] = 0; mem [j + 0x31] = 0; mem [j + 0x32] = 0; mem [j + 0x33] = 0; mem [j + 0x34] = 0; mem [j + 0x35] = 0; mem [j + 0x36] = 0; mem [j + 0x37] = 0; mem [j + 0x38] = 0; mem [j + 0x39] = 0; mem [j + 0x3a] = 0; mem [j + 0x3b] = 0; mem [j + 0x3c] = 0; mem [j + 0x3d] = 0; mem [j + 0x3e] = 0; mem [j + 0x3f] = 0;
} }
times (& tms); stop = tms. tms_utime; diff = stop - start; wdiff += diff;
if (diff) printf ("%20sB/s", cvtsze (size / diff * CLK_TCK * test_lups)); else printf ("%23s", DIFF_SMALL_MSG); fflush (stdout);
times (& tms); start = tms. tms_utime; for (i = 0; i < test_lups; i++) { for (j = 0; j < size / sizeof (u_long); j += 64) { d = mem [j + 0x0]; d = mem [j + 0x1]; d = mem [j + 0x2]; d = mem [j + 0x3]; d = mem [j + 0x4]; d = mem [j + 0x5]; d = mem [j + 0x6]; d = mem [j + 0x7]; d = mem [j + 0x8]; d = mem [j + 0x9]; d = mem [j + 0xa]; d = mem [j + 0xb]; d = mem [j + 0xc]; d = mem [j + 0xd]; d = mem [j + 0xe]; d = mem [j + 0xf];
d = mem [j + 0x10]; d = mem [j + 0x11]; d = mem [j + 0x12]; d = mem [j + 0x13]; d = mem [j + 0x14]; d = mem [j + 0x15]; d = mem [j + 0x16]; d = mem [j + 0x17]; d = mem [j + 0x18]; d = mem [j + 0x19]; d = mem [j + 0x1a]; d = mem [j + 0x1b]; d = mem [j + 0x1c]; d = mem [j + 0x1d]; d = mem [j + 0x1e]; d = mem [j + 0x1f];
d = mem [j + 0x20]; d = mem [j + 0x21]; d = mem [j + 0x22]; d = mem [j + 0x23]; d = mem [j + 0x24]; d = mem [j + 0x25]; d = mem [j + 0x26]; d = mem [j + 0x27]; d = mem [j + 0x28]; d = mem [j + 0x29]; d = mem [j + 0x2a]; d = mem [j + 0x2b]; d = mem [j + 0x2c]; d = mem [j + 0x2d]; d = mem [j + 0x2e]; d = mem [j + 0x2f];
d = mem [j + 0x30]; d = mem [j + 0x31]; d = mem [j + 0x32]; d = mem [j + 0x33]; d = mem [j + 0x34]; d = mem [j + 0x35]; d = mem [j + 0x36]; d = mem [j + 0x37]; d = mem [j + 0x38]; d = mem [j + 0x39]; d = mem [j + 0x3a]; d = mem [j + 0x3b]; d = mem [j + 0x3c]; d = mem [j + 0x3d]; d = mem [j + 0x3e]; d = mem [j + 0x3f];
} }
times (& tms); stop = tms. tms_utime; diff = stop - start; rdiff += diff;
if (diff) printf ("%20sB/s", cvtsze (size / diff * CLK_TCK * test_lups)); else printf ("%23s", DIFF_SMALL_MSG);
printf ("\n"); total += size; }
printf ("\n" "%21s ", "average");
if (wdiff) printf ("%20sB/s", cvtsze (total / wdiff * CLK_TCK * test_lups)); else printf ("%23s", DIFF_SMALL_MSG);
if (rdiff) printf ("%20sB/s", cvtsze (total / rdiff * CLK_TCK * test_lups)); else printf ("%23s", DIFF_SMALL_MSG);
printf ("\n");
return 0; }
|