diff --git a/mps/code/djbench.c b/mps/code/djbench.c index ee200931647..23006445190 100644 --- a/mps/code/djbench.c +++ b/mps/code/djbench.c @@ -5,7 +5,21 @@ #include #include #include +#include #include "getopt.h" +#include "testlib.h" + +#include "mps.c" + + +static mps_arena_t arena; +static mps_pool_t pool; +static mps_ap_t ap; + + +/* The benchmark behaviour is defined as a macro in order to give realistic + opportunities for compiler optimisation and the intended inlining of the + MPS functions. */ static unsigned niter = 100; /* iterations */ static unsigned npass = 1000; /* passes over blocks */ @@ -13,53 +27,79 @@ static unsigned nblocks = 1000; /* number of blocks */ static unsigned sshift = 18; /* log2 max block size in words */ static double prob = 0.2; /* probability per pass of acting */ -#define DJRUN dj_malloc -#define ALLOC(p, s) do { p = malloc(s); } while(0) -#define FREE(p, s) do { free(p); } while(0) -#include "djrun.c" -#undef DJRUN -#undef ALLOC -#undef FREE +#define DJRUN(alloc, free) \ + do { \ + struct {void *p; size_t s;} *blocks = alloca(sizeof(*blocks) * nblocks); \ + unsigned i, j, k; \ + \ + for (k = 0; k < nblocks; ++k) { \ + blocks[k].p = NULL; \ + } \ + \ + for (i = 0; i < niter; ++i) { \ + for (j = 0; j < npass; ++j) { \ + for (k = 0; k < nblocks; ++k) { \ + if (rnd() % 16384 < prob * 16384) { \ + if (blocks[k].p == NULL) { \ + size_t s = rnd() % ((sizeof(void *) << (rnd() % sshift)) - 1); \ + void *p = NULL; \ + if (s > 0) alloc(p, s); \ + blocks[k].p = p; \ + blocks[k].s = s; \ + } else { \ + free(blocks[k].p, blocks[k].s); \ + blocks[k].p = NULL; \ + } \ + } \ + } \ + } \ + \ + for (k = 0; k < nblocks; ++k) { \ + if (blocks[k].p) { \ + free(blocks[k].p, blocks[k].s); \ + blocks[k].p = NULL; \ + } \ + } \ + } \ + } while(0) -#include "mps.c" -static mps_arena_t arena; -static mps_pool_t pool; -static mps_ap_t ap; +/* malloc/free benchmark */ -#define DJRUN dj_alloc -#define ALLOC(p, s) do { mps_alloc(&p, pool, s); } while(0) -#define FREE(p, s) do { mps_free(pool, p, s); } while(0) -#include "djrun.c" -#undef DJRUN -#undef ALLOC -#undef FREE +#define MALLOC_ALLOC(p, s) do { p = malloc(s); } while(0) +#define MALLOC_FREE(p, s) do { free(p); } while(0) + +static void dj_malloc(void) { + DJRUN(MALLOC_ALLOC, MALLOC_FREE); +} + +/* mps_alloc/mps_free benchmark */ + +#define MPS_ALLOC(p, s) do { mps_alloc(&p, pool, s); } while(0) +#define MPS_FREE(p, s) do { mps_free(pool, p, s); } while(0) + +static void dj_alloc(void) { + DJRUN(MPS_ALLOC, MPS_FREE); +} + +/* reserve/free benchmark */ #define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) - -#define DJRUN dj_reserve -#define ALLOC(p, s) \ +#define RESERVE_ALLOC(p, s) \ do { \ size_t _s = ALIGN_UP(s, (size_t)MPS_PF_ALIGN); \ mps_reserve(&p, ap, _s); \ mps_commit(ap, p, _s); \ } while(0) -#define FREE(p, s) do { mps_free(pool, p, s); } while(0) -#include "djrun.c" -#undef DJRUN -#undef ALLOC -#undef FREE +#define RESERVE_FREE(p, s) do { mps_free(pool, p, s); } while(0) -#define MUST(expr) \ - do { \ - mps_res_t res = (expr); \ - if (res != MPS_RES_OK) { \ - fprintf(stderr, #expr " returned %d\n", res); \ - exit(EXIT_FAILURE); \ - } \ - } while(0) +static void dj_reserve(void) { + DJRUN(RESERVE_ALLOC, RESERVE_FREE); +} +/* Wrap a call to dj benchmark that doesn't require MPS setup */ + static void wrap(void (*dj)(void), mps_class_t dummy, const char *name) { clock_t start, finish; @@ -73,6 +113,17 @@ static void wrap(void (*dj)(void), mps_class_t dummy, const char *name) } +/* Wrap a call to a dj benchmark that requires MPS setup */ + +#define MUST(expr) \ + do { \ + mps_res_t res = (expr); \ + if (res != MPS_RES_OK) { \ + fprintf(stderr, #expr " returned %d\n", res); \ + exit(EXIT_FAILURE); \ + } \ + } while(0) + static void arena_wrap(void (*dj)(void), mps_class_t pool_class, const char *name) { MPS_ARGS_BEGIN(args) { @@ -89,6 +140,8 @@ static void arena_wrap(void (*dj)(void), mps_class_t pool_class, const char *nam } +/* Command-line options definitions. See getopt_long(3). */ + static struct option longopts[] = { {"niter", required_argument, NULL, 'i'}, {"npass", required_argument, NULL, 'p'}, @@ -99,12 +152,13 @@ static struct option longopts[] = { }; +/* Test definitions. */ + static mps_class_t dummy_class(void) { return NULL; } - static struct { const char *name; void (*wrap)(void (*)(void), mps_class_t, const char *name); @@ -117,9 +171,10 @@ static struct { {"mvb", arena_wrap, dj_reserve, mps_class_mv}, /* mv with buffers */ {"an", wrap, dj_malloc, dummy_class}, }; - +/* Command-line driver */ + int main(int argc, char *argv[]) { int ch; unsigned i; diff --git a/mps/code/djrun.c b/mps/code/djrun.c deleted file mode 100644 index 93ff24e5761..00000000000 --- a/mps/code/djrun.c +++ /dev/null @@ -1,48 +0,0 @@ -/* djb.c -- "DJ" benchmark template - * $Id$ - * - * This file is intended to be included in other programs that define - * - * DJRUN function to call to run the template - * ALLOC(p, s) allocate block of size s and assign to p - * FREE(p, s) free previously-allocated block at p of size s - */ - -#include -#include "testlib.h" - -static void DJRUN(void) -{ - struct {void *p; size_t s;} *blocks = alloca(sizeof(*blocks) * nblocks); - unsigned i, j, k; - - for (k = 0; k < nblocks; ++k) { - blocks[k].p = NULL; - } - - for (i = 0; i < niter; ++i) { - for (j = 0; j < npass; ++j) { - for (k = 0; k < nblocks; ++k) { - if (rnd() % 16384 < prob * 16384) { - if (blocks[k].p == NULL) { - size_t s = rnd() % ((sizeof(void *) << (rnd() % sshift)) - 1); - void *p = NULL; - if (s > 0) ALLOC(p, s); - blocks[k].p = p; - blocks[k].s = s; - } else { - FREE(blocks[k].p, blocks[k].s); - blocks[k].p = NULL; - } - } - } - } - - for (k = 0; k < nblocks; ++k) { - if (blocks[k].p) { - FREE(blocks[k].p, blocks[k].s); - blocks[k].p = NULL; - } - } - } -} diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index 92a3b6945c9..a644c698605 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -1266,7 +1266,6 @@ 3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = ""; }; 31379493176CC34D00BCFAEC /* djbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djbench; sourceTree = BUILT_PRODUCTS_DIR; }; 3137949D176CC3B100BCFAEC /* djbench.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = djbench.c; sourceTree = ""; }; - 313794A0176CD21F00BCFAEC /* djrun.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = djrun.c; sourceTree = ""; }; 317B3C2A1731830100F9A469 /* arg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arg.c; sourceTree = ""; }; 31A47BA3156C1E130039B1C2 /* mps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mps.c; sourceTree = ""; }; 31A47BA5156C1E5E0039B1C2 /* ssixi3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ssixi3.c; sourceTree = ""; }; @@ -1760,7 +1759,6 @@ 31F45FD8176D19B800BEAAA8 /* getopt.h */, 31F45FD6176D192800BEAAA8 /* getoptl.c */, 3137949D176CC3B100BCFAEC /* djbench.c */, - 313794A0176CD21F00BCFAEC /* djrun.c */, ); name = Benchmarks; sourceTree = ""; diff --git a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme index 2e10ee7e32d..c659271ec47 100644 --- a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme +++ b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme @@ -15,7 +15,7 @@ @@ -33,7 +33,7 @@ @@ -52,7 +52,7 @@ @@ -88,7 +88,7 @@