From 63799a0304f672b44080f01d24ed44687947b584 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 8 Jun 2013 19:50:55 +0100 Subject: [PATCH 01/14] branching mps master sources to branch/2013-06-08/benchmarks. Copied from Perforce Change: 182647 ServerID: perforce.ravenbrook.com From 2dfab5bbb8c8897f5a1803d511f5505b3632ff78 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Fri, 14 Jun 2013 12:19:02 +0100 Subject: [PATCH 02/14] Adding sql tools for analysing event logs Copied from Perforce Change: 182734 ServerID: perforce.ravenbrook.com --- mps/tool/telemetry.sql | 98 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 mps/tool/telemetry.sql diff --git a/mps/tool/telemetry.sql b/mps/tool/telemetry.sql new file mode 100644 index 00000000000..a34eb3269c2 --- /dev/null +++ b/mps/tool/telemetry.sql @@ -0,0 +1,98 @@ +-- telemetry.sql -- SQL tools for analysing telemetry output +-- $Id$ +-- +-- This file can be loaded into a sqlite database that has been generated by +-- the ``mpseventsql`` tool in order to provide useful views for analysing +-- the event log. +-- +-- TODO: Documentation. +-- TODO: Focus on CPU/memory overhead and pause times. +-- TODO: Log clocks_per_sec so that ClockLerp and provide output in seconds. + +-- TODO: Label strings all start with double quotes. Bug in eventsql? +CREATE VIEW Address_Label AS + SELECT address, string + FROM EVENT_Label JOIN EVENT_Intern USING (log_serial, stringId); + + +-- Correlate the processor clock with the process clock by lerp +-- Note that the subselect pattern for finding the next clock is significantly +-- faster than a join in sqlite. + +CREATE INDEX EVENT_EventClockSync_log_serial_time_clock + ON EVENT_EventClockSync (log_serial, time, clock); + +CREATE VIEW ClockInterval AS + SELECT *, + (SELECT time FROM EVENT_EventClockSync AS top + WHERE log_serial = bot.log_serial AND time > bot.time + ORDER BY time) AS next + FROM EVENT_EventClockSync as bot; + +CREATE VIEW ClockLerp AS + SELECT ci.log_serial AS log_serial, + ci.clock, + ci.time AS time, + next.time AS next, + (next.time - ci.time) / (next.clock - ci.clock) AS rate + FROM ClockInterval AS ci, + EVENT_EventClockSync AS next + WHERE ci.log_serial = next.log_serial AND ci.next = next.time; + + +-- Model Segments + +CREATE INDEX EVENT_SegAlloc_log_serial_seg_time ON EVENT_SegAlloc (log_serial, seg, time); +CREATE INDEX EVENT_SegFree_log_serial_seg_time ON EVENT_SegFree (log_serial, seg, time); + +CREATE VIEW Seg AS + SELECT *, + (SELECT time + FROM EVENT_SegFree + WHERE log_serial = alloc.log_serial AND + seg = alloc.seg AND + time >= alloc.time + ORDER BY time) as free_time + FROM EVENT_SegAlloc AS alloc; + + +-- Model Traces + +CREATE INDEX EVENT_TraceCreate_log_serial_trace_time ON EVENT_TraceCreate (log_serial, trace, time); +CREATE INDEX EVENT_TraceDestroy_log_serial_trace_time ON EVENT_TraceDestroy (log_serial, trace, time); + +CREATE VIEW Trace AS + SELECT c.log_serial AS log_serial, + c.trace AS trace, + why, + c.time AS create_time, + (SELECT time + FROM EVENT_TraceDestroy + WHERE log_serial = c.log_serial AND + trace = c.trace AND + time >= c.time + ORDER BY time + LIMIT 1) AS destroy_time + FROM EVENT_TraceCreate AS c; + +CREATE INDEX EVENT_TraceStart_log_serial_trace_time ON EVENT_TraceStart (log_serial, trace, time); + +CREATE VIEW Trace2 AS + SELECT * + FROM EVENT_TraceStart AS start + LEFT JOIN Trace + ON start.log_serial = Trace.log_serial AND + start.trace = Trace.trace AND + start.time BETWEEN create_time AND destroy_time; + +CREATE VIEW Trace3 AS + SELECT * + FROM EVENT_TraceStart AS start + LEFT JOIN EVENT_TraceStatCondemn as condemn + ON condemn.log_serial = Trace.log_serial AND + condemn.trace = Trace.trace AND + condemn.time BETWEEN create_time AND destroy_time + LEFT JOIN Trace + ON start.log_serial = Trace.log_serial AND + start.trace = Trace.trace AND + start.time BETWEEN create_time AND destroy_time; From 7545b41d42b5a91b5e1606f7cce3fb267724f021 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Fri, 14 Jun 2013 15:47:30 +0100 Subject: [PATCH 03/14] Adding more todo notes and references. Copied from Perforce Change: 182753 ServerID: perforce.ravenbrook.com --- mps/tool/telemetry.sql | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mps/tool/telemetry.sql b/mps/tool/telemetry.sql index a34eb3269c2..e7d748cadfe 100644 --- a/mps/tool/telemetry.sql +++ b/mps/tool/telemetry.sql @@ -1,4 +1,5 @@ --- telemetry.sql -- SQL tools for analysing telemetry output +-- telemetry.sql -- SQL tools for analysing MPS telemetry output +-- -- $Id$ -- -- This file can be loaded into a sqlite database that has been generated by @@ -6,8 +7,19 @@ -- the event log. -- -- TODO: Documentation. --- TODO: Focus on CPU/memory overhead and pause times. +-- TODO: Focus on CPU/memory overhead and pause times, BMU [sach04]_ and MMU [chen01]_. -- TODO: Log clocks_per_sec so that ClockLerp and provide output in seconds. +-- TODO: Incorporate https://info.ravenbrook.com/mail/2012/11/09/15-21-27/0/ +-- TODO: Output a EventSync whenever we call mps_clock (because why not?) +-- +-- .. [chen01] Perry Cheng and Guy Blelloch. A parallel, real-time +-- garbage collector. In PLDI 2001 [PLDI01], 2001, pages 125-136. +-- +-- +-- .. [sach04] Narendran Sachindran, J. Eliot B. Moss, and Emery D. +-- Berger. MC²: High-performance garbage collection for memory-constrained +-- environments. In OOPSLA 2004 [OOPSLA04], 2004, pages 81-98. +-- . -- TODO: Label strings all start with double quotes. Bug in eventsql? CREATE VIEW Address_Label AS From b610d57e92d919ebcae2ff15f158218e7d062c4d Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 15 Jun 2013 16:24:38 +0100 Subject: [PATCH 04/14] Sharing the scheme building xcode scheme so that others can get logs and profile easily. Copied from Perforce Change: 182754 ServerID: perforce.ravenbrook.com --- .../xcshareddata/xcschemes/scheme.xcscheme | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 mps/code/mps.xcodeproj/xcshareddata/xcschemes/scheme.xcscheme diff --git a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/scheme.xcscheme b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/scheme.xcscheme new file mode 100644 index 00000000000..4e618a67ab5 --- /dev/null +++ b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/scheme.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 29fb66594dc34887c0d87fecd58090810de31740 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 15 Jun 2013 18:41:58 +0100 Subject: [PATCH 05/14] Adding "dj" benchmark to exercise manual variable pools and compare with malloc. Copied from Perforce Change: 182766 ServerID: perforce.ravenbrook.com --- mps/code/djb.c | 52 +++++++++++ mps/code/djban.c | 93 ++++++++++++++++++++ mps/code/mps.xcodeproj/project.pbxproj | 117 +++++++++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 mps/code/djb.c create mode 100644 mps/code/djban.c diff --git a/mps/code/djb.c b/mps/code/djb.c new file mode 100644 index 00000000000..04030ed2242 --- /dev/null +++ b/mps/code/djb.c @@ -0,0 +1,52 @@ +/* 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(unsigned niter, /* iterations */ + unsigned npass, /* passes over blocks */ + unsigned nblocks, /* number of blocks */ + unsigned sshift, /* log2 max block size in words */ + double prob) /* probability per pass of acting */ +{ + 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/djban.c b/mps/code/djban.c new file mode 100644 index 00000000000..860c4b6bf1f --- /dev/null +++ b/mps/code/djban.c @@ -0,0 +1,93 @@ +/* djban.c -- "DJ" Benchmark on ANSI C library + * $Id$ + */ + +#include +#include +#include + +#define DJRUN dj_malloc +#define ALLOC(p, s) do { p = malloc(s); } while(0) +#define FREE(p, s) do { free(p); } while(0) +#include "djb.c" +#undef DJRUN +#undef ALLOC +#undef FREE + +#include "mps.c" + +static mps_arena_t arena; +static mps_pool_t pool; +static mps_ap_t ap; + +#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 "djb.c" +#undef DJRUN +#undef ALLOC +#undef FREE + +#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) + +#define DJRUN dj_reserve +#define 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 "djb.c" +#undef DJRUN +#undef ALLOC +#undef FREE + +#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) + + +typedef void (*dj_t)(unsigned, unsigned, unsigned, unsigned, double); + +static void wrap(dj_t dj, const char *name) +{ + clock_t start, finish; + + start = clock(); + dj(100, 1000, 1000, 18, 0.2); + finish = clock(); + + printf("%s: %g\n", name, (double)(finish - start) / CLOCKS_PER_SEC); +} + + +static void arena_wrap(dj_t dj, mps_class_t pool_class, const char *name) +{ + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 256ul * 1024 * 1024); /* FIXME: Why is there no default? */ + MPS_ARGS_DONE(args); + MUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args)); + } MPS_ARGS_END(args); + MUST(mps_pool_create_k(&pool, arena, pool_class, mps_args_none)); + MUST(mps_ap_create_k(&ap, pool, mps_args_none)); + wrap(dj, name); + mps_ap_destroy(ap); + mps_pool_destroy(pool); + mps_arena_destroy(arena); +} + + +int main(void) { + arena_wrap(dj_reserve, mps_class_mvt(), "mvt"); + arena_wrap(dj_reserve, mps_class_mvff(), "mvff"); + arena_wrap(dj_alloc, mps_class_mv(), "mv"); + wrap(dj_malloc, "an"); + + return EXIT_SUCCESS; +} diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index d735f470044..250704e7b03 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ buildPhases = ( ); dependencies = ( + 313794A4176CDD7D00BCFAEC /* PBXTargetDependency */, + 313794A2176CDD7900BCFAEC /* PBXTargetDependency */, 3104AFF6156D37BC000A585A /* PBXTargetDependency */, 3114A644156E94FB001E0AA3 /* PBXTargetDependency */, 3104AFF8156D37BE000A585A /* PBXTargetDependency */, @@ -204,6 +206,8 @@ 3124CAFA156BE82000753214 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; 3124CAFB156BE82000753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; 3124CAFC156BE82900753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; + 3137949E176CC3B100BCFAEC /* djban.c in Sources */ = {isa = PBXBuildFile; fileRef = 3137949D176CC3B100BCFAEC /* djban.c */; }; + 3137949F176CD02700BCFAEC /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; 3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; 317B3C2B1731830100F9A469 /* arg.c in Sources */ = {isa = PBXBuildFile; fileRef = 317B3C2A1731830100F9A469 /* arg.c */; }; 31A47BA4156C1E130039B1C2 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; }; @@ -654,6 +658,20 @@ remoteGlobalIDString = 3114A6C5156E9815001E0AA3; remoteInfo = mpseventcnv; }; + 313794A1176CDD7900BCFAEC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 31FCAE0917692403008C034C; + remoteInfo = scheme; + }; + 313794A3176CDD7D00BCFAEC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 31379492176CC34D00BCFAEC; + remoteInfo = djban; + }; 31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; @@ -1039,6 +1057,15 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + 31379491176CC34D00BCFAEC /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 31D6000B156D3CB200337B26 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1236,6 +1263,9 @@ 3124CAE4156BE6D500753214 /* fmthe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmthe.c; sourceTree = ""; }; 3124CAEB156BE7F300753214 /* amcss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcss; sourceTree = BUILT_PRODUCTS_DIR; }; 3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = ""; }; + 31379493176CC34D00BCFAEC /* djban */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djban; sourceTree = BUILT_PRODUCTS_DIR; }; + 3137949D176CC3B100BCFAEC /* djban.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = djban.c; sourceTree = ""; }; + 313794A0176CD21F00BCFAEC /* djb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = djb.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 = ""; }; @@ -1559,6 +1589,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 31379490176CC34D00BCFAEC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 31D6000A156D3CB200337B26 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1714,6 +1751,15 @@ name = Tests; sourceTree = ""; }; + 3137948E176CC0F800BCFAEC /* Benchmarks */ = { + isa = PBXGroup; + children = ( + 3137949D176CC3B100BCFAEC /* djban.c */, + 313794A0176CD21F00BCFAEC /* djb.c */, + ); + name = Benchmarks; + sourceTree = ""; + }; 31A47BA6156C1E620039B1C2 /* I3 */ = { isa = PBXGroup; children = ( @@ -1745,6 +1791,7 @@ 31EEABD8156AAE9E00714D05 = { isa = PBXGroup; children = ( + 3137948E176CC0F800BCFAEC /* Benchmarks */, 2D07B97B163705E400DB751B /* libsqlite3.dylib */, 3114A6D6156E9846001E0AA3 /* Tools */, 31A47BA8156C1E930039B1C2 /* MPS */, @@ -1796,6 +1843,7 @@ 2291A5E3175CB05F001D4920 /* exposet0 */, 224CC799175E1821002FF81B /* fotest */, 31FCAE0A17692403008C034C /* scheme */, + 31379493176CC34D00BCFAEC /* djban */, ); name = Products; sourceTree = ""; @@ -2503,6 +2551,23 @@ productReference = 3124CAEB156BE7F300753214 /* amcss */; productType = "com.apple.product-type.tool"; }; + 31379492176CC34D00BCFAEC /* djban */ = { + isa = PBXNativeTarget; + buildConfigurationList = 31379499176CC34D00BCFAEC /* Build configuration list for PBXNativeTarget "djban" */; + buildPhases = ( + 3137948F176CC34D00BCFAEC /* Sources */, + 31379490176CC34D00BCFAEC /* Frameworks */, + 31379491176CC34D00BCFAEC /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = djban; + productName = djban; + productReference = 31379493176CC34D00BCFAEC /* djban */; + productType = "com.apple.product-type.tool"; + }; 31D6000C156D3CB200337B26 /* awluthe */ = { isa = PBXNativeTarget; buildConfigurationList = 31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */; @@ -2724,6 +2789,7 @@ 2D604B9B16514B1A003AAF46 /* mpseventtxt */, 22CDE8EF16E9E97D00366D0A /* testrun */, 31FCAE0917692403008C034C /* scheme */, + 31379492176CC34D00BCFAEC /* djban */, ); }; /* End PBXProject section */ @@ -3062,6 +3128,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3137948F176CC34D00BCFAEC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3137949E176CC3B100BCFAEC /* djban.c in Sources */, + 3137949F176CD02700BCFAEC /* testlib.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 31D60009156D3CB200337B26 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3450,6 +3525,16 @@ target = 3114A6C5156E9815001E0AA3 /* mpseventcnv */; targetProxy = 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */; }; + 313794A2176CDD7900BCFAEC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 31FCAE0917692403008C034C /* scheme */; + targetProxy = 313794A1176CDD7900BCFAEC /* PBXContainerItemProxy */; + }; + 313794A4176CDD7D00BCFAEC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 31379492176CC34D00BCFAEC /* djban */; + targetProxy = 313794A3176CDD7D00BCFAEC /* PBXContainerItemProxy */; + }; 31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 31EEABFA156AAF9D00714D05 /* mps */; @@ -4166,6 +4251,28 @@ }; name = Release; }; + 3137949A176CC34D00BCFAEC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 3137949B176CC34D00BCFAEC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 3137949C176CC34D00BCFAEC /* WE */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = WE; + }; 318387EB15DC30CC008E4EA0 /* WE */ = { isa = XCBuildConfiguration; buildSettings = { @@ -5110,6 +5217,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 31379499176CC34D00BCFAEC /* Build configuration list for PBXNativeTarget "djban" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3137949A176CC34D00BCFAEC /* Debug */, + 3137949B176CC34D00BCFAEC /* Release */, + 3137949C176CC34D00BCFAEC /* WE */, + ); + defaultConfigurationIsVisible = 0; + }; 31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -5208,6 +5324,7 @@ 31FCAE1217692403008C034C /* WE */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; From c548654603d240adb78f9641bb3c257e08deed03 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 00:21:28 +0100 Subject: [PATCH 06/14] Generalising dj benchmark test to accept options controlling test parameters and arguments saying which pool classes to test. Copied from Perforce Change: 182767 ServerID: perforce.ravenbrook.com --- mps/code/djban.c | 93 ---------- mps/code/djbench.c | 167 ++++++++++++++++++ mps/code/{djb.c => djrun.c} | 6 +- mps/code/mps.xcodeproj/project.pbxproj | 31 ++-- .../xcshareddata/xcschemes/djban.xcscheme | 104 +++++++++++ 5 files changed, 291 insertions(+), 110 deletions(-) delete mode 100644 mps/code/djban.c create mode 100644 mps/code/djbench.c rename mps/code/{djb.c => djrun.c} (78%) create mode 100644 mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme diff --git a/mps/code/djban.c b/mps/code/djban.c deleted file mode 100644 index 860c4b6bf1f..00000000000 --- a/mps/code/djban.c +++ /dev/null @@ -1,93 +0,0 @@ -/* djban.c -- "DJ" Benchmark on ANSI C library - * $Id$ - */ - -#include -#include -#include - -#define DJRUN dj_malloc -#define ALLOC(p, s) do { p = malloc(s); } while(0) -#define FREE(p, s) do { free(p); } while(0) -#include "djb.c" -#undef DJRUN -#undef ALLOC -#undef FREE - -#include "mps.c" - -static mps_arena_t arena; -static mps_pool_t pool; -static mps_ap_t ap; - -#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 "djb.c" -#undef DJRUN -#undef ALLOC -#undef FREE - -#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) - -#define DJRUN dj_reserve -#define 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 "djb.c" -#undef DJRUN -#undef ALLOC -#undef FREE - -#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) - - -typedef void (*dj_t)(unsigned, unsigned, unsigned, unsigned, double); - -static void wrap(dj_t dj, const char *name) -{ - clock_t start, finish; - - start = clock(); - dj(100, 1000, 1000, 18, 0.2); - finish = clock(); - - printf("%s: %g\n", name, (double)(finish - start) / CLOCKS_PER_SEC); -} - - -static void arena_wrap(dj_t dj, mps_class_t pool_class, const char *name) -{ - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 256ul * 1024 * 1024); /* FIXME: Why is there no default? */ - MPS_ARGS_DONE(args); - MUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args)); - } MPS_ARGS_END(args); - MUST(mps_pool_create_k(&pool, arena, pool_class, mps_args_none)); - MUST(mps_ap_create_k(&ap, pool, mps_args_none)); - wrap(dj, name); - mps_ap_destroy(ap); - mps_pool_destroy(pool); - mps_arena_destroy(arena); -} - - -int main(void) { - arena_wrap(dj_reserve, mps_class_mvt(), "mvt"); - arena_wrap(dj_reserve, mps_class_mvff(), "mvff"); - arena_wrap(dj_alloc, mps_class_mv(), "mv"); - wrap(dj_malloc, "an"); - - return EXIT_SUCCESS; -} diff --git a/mps/code/djbench.c b/mps/code/djbench.c new file mode 100644 index 00000000000..b09c31aaa39 --- /dev/null +++ b/mps/code/djbench.c @@ -0,0 +1,167 @@ +/* djban.c -- "DJ" Benchmark on ANSI C library + * $Id$ + */ + +#include +#include +#include +#include "getopt.h" + +static unsigned niter = 100; /* iterations */ +static unsigned npass = 1000; /* passes over blocks */ +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 + +#include "mps.c" + +static mps_arena_t arena; +static mps_pool_t pool; +static mps_ap_t ap; + +#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 ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) + +#define DJRUN dj_reserve +#define 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 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 wrap(void (*dj)(void), mps_class_t dummy, const char *name) +{ + clock_t start, finish; + (void)dummy; + + start = clock(); + dj(); + finish = clock(); + + printf("%s: %g\n", name, (double)(finish - start) / CLOCKS_PER_SEC); +} + + +static void arena_wrap(void (*dj)(void), mps_class_t pool_class, const char *name) +{ + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 256ul * 1024 * 1024); /* FIXME: Why is there no default? */ + MPS_ARGS_DONE(args); + MUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args)); + } MPS_ARGS_END(args); + MUST(mps_pool_create_k(&pool, arena, pool_class, mps_args_none)); + MUST(mps_ap_create_k(&ap, pool, mps_args_none)); + wrap(dj, NULL, name); + mps_ap_destroy(ap); + mps_pool_destroy(pool); + mps_arena_destroy(arena); +} + + +static struct option longopts[] = { + {"niter", required_argument, NULL, 'i'}, + {"npass", required_argument, NULL, 'p'}, + {"nblocks", required_argument, NULL, 'b'}, + {"sshift", required_argument, NULL, 's'}, + {"prob", required_argument, NULL, 'r'}, + {NULL, 0, NULL, 0} +}; + + +static mps_class_t dummy_class(void) +{ + return NULL; +} + + +static struct { + const char *name; + void (*wrap)(void (*)(void), mps_class_t, const char *name); + void (*dj)(void); + mps_class_t (*pool_class)(void); +} pools[] = { + {"mvt", arena_wrap, dj_reserve, mps_class_mvt}, + {"mvff", arena_wrap, dj_reserve, mps_class_mvff}, + {"mv", arena_wrap, dj_alloc, mps_class_mv}, + {"an", wrap, dj_malloc, dummy_class}, +}; + + + +int main(int argc, char *argv[]) { + int ch; + unsigned i; + + while ((ch = getopt_long(argc, argv, "i:p:b:s:r:", longopts, NULL)) != -1) + switch (ch) { + case 'i': + niter = (unsigned)strtoul(optarg, NULL, 10); + break; + case 'p': + npass = (unsigned)strtoul(optarg, NULL, 10); + break; + case 'b': + nblocks = (unsigned)strtoul(optarg, NULL, 10); + break; + case 's': + nblocks = (unsigned)strtoul(optarg, NULL, 10); + break; + case 'r': + sshift = (unsigned)strtoul(optarg, NULL, 10); + break; + default: + fprintf(stderr, + "Usage: %s [option...]\n" + "Options: UTSL!\n", + argv[0]); + return EXIT_FAILURE; + } + argc -= optind; + argv += optind; + + while (argc > 0) { + for (i = 0; i < sizeof(pools) / sizeof(pools[0]); ++i) + if (strcmp(argv[0], pools[i].name) == 0) { + pools[i].wrap(pools[i].dj, pools[i].pool_class(), pools[i].name); + goto found; + } + fprintf(stderr, "unknown pool test \"%s\"\n", argv[0]); + return EXIT_FAILURE; + found: + --argc; + ++argv; + } + + return EXIT_SUCCESS; +} diff --git a/mps/code/djb.c b/mps/code/djrun.c similarity index 78% rename from mps/code/djb.c rename to mps/code/djrun.c index 04030ed2242..93ff24e5761 100644 --- a/mps/code/djb.c +++ b/mps/code/djrun.c @@ -11,11 +11,7 @@ #include #include "testlib.h" -static void DJRUN(unsigned niter, /* iterations */ - unsigned npass, /* passes over blocks */ - unsigned nblocks, /* number of blocks */ - unsigned sshift, /* log2 max block size in words */ - double prob) /* probability per pass of acting */ +static void DJRUN(void) { struct {void *p; size_t s;} *blocks = alloca(sizeof(*blocks) * nblocks); unsigned i, j, k; diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index 250704e7b03..7fcc3cd3d85 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -206,7 +206,7 @@ 3124CAFA156BE82000753214 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; 3124CAFB156BE82000753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; 3124CAFC156BE82900753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3137949E176CC3B100BCFAEC /* djban.c in Sources */ = {isa = PBXBuildFile; fileRef = 3137949D176CC3B100BCFAEC /* djban.c */; }; + 3137949E176CC3B100BCFAEC /* djbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 3137949D176CC3B100BCFAEC /* djbench.c */; }; 3137949F176CD02700BCFAEC /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; 3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; 317B3C2B1731830100F9A469 /* arg.c in Sources */ = {isa = PBXBuildFile; fileRef = 317B3C2A1731830100F9A469 /* arg.c */; }; @@ -247,6 +247,7 @@ 31D600A1156D406400337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; 31EEAC75156AB58E00714D05 /* mpmss.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC74156AB58E00714D05 /* mpmss.c */; }; 31EEAC9F156AB73400714D05 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; + 31F45FD7176D192800BEAAA8 /* getoptl.c in Sources */ = {isa = PBXBuildFile; fileRef = 31F45FD6176D192800BEAAA8 /* getoptl.c */; }; 31FCAE161769244F008C034C /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; }; 31FCAE19176924D4008C034C /* scheme.c in Sources */ = {isa = PBXBuildFile; fileRef = 31FCAE18176924D4008C034C /* scheme.c */; }; /* End PBXBuildFile section */ @@ -1264,8 +1265,8 @@ 3124CAEB156BE7F300753214 /* amcss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcss; sourceTree = BUILT_PRODUCTS_DIR; }; 3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = ""; }; 31379493176CC34D00BCFAEC /* djban */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djban; sourceTree = BUILT_PRODUCTS_DIR; }; - 3137949D176CC3B100BCFAEC /* djban.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = djban.c; sourceTree = ""; }; - 313794A0176CD21F00BCFAEC /* djb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = djb.c; sourceTree = ""; }; + 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 = ""; }; @@ -1339,6 +1340,8 @@ 31EEAC74156AB58E00714D05 /* mpmss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpmss.c; sourceTree = SOURCE_ROOT; }; 31EEAC9E156AB73400714D05 /* testlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testlib.c; sourceTree = ""; }; 31EEACA7156AB79800714D05 /* span.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = span.c; sourceTree = ""; }; + 31F45FD6176D192800BEAAA8 /* getoptl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getoptl.c; sourceTree = ""; }; + 31F45FD8176D19B800BEAAA8 /* getopt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = getopt.h; sourceTree = ""; }; 31F6CCA91739B0CF00C48748 /* mpscamc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mpscamc.h; sourceTree = ""; }; 31F6CCAA1739B0CF00C48748 /* mpscawl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mpscawl.h; sourceTree = ""; }; 31F6CCAB1739B0CF00C48748 /* mpsclo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mpsclo.h; sourceTree = ""; }; @@ -1754,8 +1757,10 @@ 3137948E176CC0F800BCFAEC /* Benchmarks */ = { isa = PBXGroup; children = ( - 3137949D176CC3B100BCFAEC /* djban.c */, - 313794A0176CD21F00BCFAEC /* djb.c */, + 31F45FD8176D19B800BEAAA8 /* getopt.h */, + 31F45FD6176D192800BEAAA8 /* getoptl.c */, + 3137949D176CC3B100BCFAEC /* djbench.c */, + 313794A0176CD21F00BCFAEC /* djrun.c */, ); name = Benchmarks; sourceTree = ""; @@ -2551,9 +2556,9 @@ productReference = 3124CAEB156BE7F300753214 /* amcss */; productType = "com.apple.product-type.tool"; }; - 31379492176CC34D00BCFAEC /* djban */ = { + 31379492176CC34D00BCFAEC /* djbench */ = { isa = PBXNativeTarget; - buildConfigurationList = 31379499176CC34D00BCFAEC /* Build configuration list for PBXNativeTarget "djban" */; + buildConfigurationList = 31379499176CC34D00BCFAEC /* Build configuration list for PBXNativeTarget "djbench" */; buildPhases = ( 3137948F176CC34D00BCFAEC /* Sources */, 31379490176CC34D00BCFAEC /* Frameworks */, @@ -2563,7 +2568,7 @@ ); dependencies = ( ); - name = djban; + name = djbench; productName = djban; productReference = 31379493176CC34D00BCFAEC /* djban */; productType = "com.apple.product-type.tool"; @@ -2789,7 +2794,7 @@ 2D604B9B16514B1A003AAF46 /* mpseventtxt */, 22CDE8EF16E9E97D00366D0A /* testrun */, 31FCAE0917692403008C034C /* scheme */, - 31379492176CC34D00BCFAEC /* djban */, + 31379492176CC34D00BCFAEC /* djbench */, ); }; /* End PBXProject section */ @@ -3132,8 +3137,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3137949E176CC3B100BCFAEC /* djban.c in Sources */, + 3137949E176CC3B100BCFAEC /* djbench.c in Sources */, 3137949F176CD02700BCFAEC /* testlib.c in Sources */, + 31F45FD7176D192800BEAAA8 /* getoptl.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3532,7 +3538,7 @@ }; 313794A4176CDD7D00BCFAEC /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 31379492176CC34D00BCFAEC /* djban */; + target = 31379492176CC34D00BCFAEC /* djbench */; targetProxy = 313794A3176CDD7D00BCFAEC /* PBXContainerItemProxy */; }; 31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = { @@ -5217,7 +5223,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 31379499176CC34D00BCFAEC /* Build configuration list for PBXNativeTarget "djban" */ = { + 31379499176CC34D00BCFAEC /* Build configuration list for PBXNativeTarget "djbench" */ = { isa = XCConfigurationList; buildConfigurations = ( 3137949A176CC34D00BCFAEC /* Debug */, @@ -5225,6 +5231,7 @@ 3137949C176CC34D00BCFAEC /* WE */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */ = { isa = XCConfigurationList; diff --git a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme new file mode 100644 index 00000000000..3841b0cbcd1 --- /dev/null +++ b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From be18333bdb1f66f295fb5ba472348a56441821a4 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 00:38:06 +0100 Subject: [PATCH 07/14] Fixing parsing of -s and -r options. Copied from Perforce Change: 182768 ServerID: perforce.ravenbrook.com --- mps/code/djbench.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mps/code/djbench.c b/mps/code/djbench.c index b09c31aaa39..ce1b4edbc5e 100644 --- a/mps/code/djbench.c +++ b/mps/code/djbench.c @@ -114,6 +114,7 @@ static struct { {"mvt", arena_wrap, dj_reserve, mps_class_mvt}, {"mvff", arena_wrap, dj_reserve, mps_class_mvff}, {"mv", arena_wrap, dj_alloc, mps_class_mv}, + {"mvb", arena_wrap, dj_reserve, mps_class_mv}, {"an", wrap, dj_malloc, dummy_class}, }; @@ -135,10 +136,10 @@ int main(int argc, char *argv[]) { nblocks = (unsigned)strtoul(optarg, NULL, 10); break; case 's': - nblocks = (unsigned)strtoul(optarg, NULL, 10); + sshift = (unsigned)strtoul(optarg, NULL, 10); break; case 'r': - sshift = (unsigned)strtoul(optarg, NULL, 10); + prob = strtod(optarg, NULL); break; default: fprintf(stderr, From 201a76c3b7a847269a76fcb5a1bdfc5c49d359ab Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 00:55:41 +0100 Subject: [PATCH 08/14] Improving usage message. Copied from Perforce Change: 182772 ServerID: perforce.ravenbrook.com --- mps/code/djbench.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/mps/code/djbench.c b/mps/code/djbench.c index ce1b4edbc5e..ee200931647 100644 --- a/mps/code/djbench.c +++ b/mps/code/djbench.c @@ -114,7 +114,7 @@ static struct { {"mvt", arena_wrap, dj_reserve, mps_class_mvt}, {"mvff", arena_wrap, dj_reserve, mps_class_mvff}, {"mv", arena_wrap, dj_alloc, mps_class_mv}, - {"mvb", arena_wrap, dj_reserve, mps_class_mv}, + {"mvb", arena_wrap, dj_reserve, mps_class_mv}, /* mv with buffers */ {"an", wrap, dj_malloc, dummy_class}, }; @@ -143,9 +143,30 @@ int main(int argc, char *argv[]) { break; default: fprintf(stderr, - "Usage: %s [option...]\n" - "Options: UTSL!\n", - argv[0]); + "Usage: %s [option...] [test...]\n" + "Options:\n" + " -i n, --niter=n\n" + " Iterate each test n times (default %u).\n" + " -p n, --npass=n\n" + " Pass over the block array n times (default %u).\n" + " -b n, --nblocks=n\n" + " Length of the block array (default %u).\n" + " -s n, --sshift=n\n" + " Log2 max block size in words (default %u).\n" + " -r p, --prob=p\n" + " Probability of acting on a block (default %g).\n" + "Tests:\n" + " mvt pool class MVT\n" + " mvff pool class MVFF\n" + " mv pool class MV\n" + " mvb pool class MV with buffers\n" + " an malloc\n", + argv[0], + niter, + npass, + nblocks, + sshift, + prob); return EXIT_FAILURE; } argc -= optind; From 57925c8a86ca2b2bd206b960a2e6d1715a75588e Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 07:52:15 +0100 Subject: [PATCH 09/14] Renaming djban test to djbench in xcode project and sharing scheme. Copied from Perforce Change: 182773 ServerID: perforce.ravenbrook.com --- mps/code/mps.xcodeproj/project.pbxproj | 18 +++++++++++++++--- .../{djban.xcscheme => djbench.xcscheme} | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) rename mps/code/mps.xcodeproj/xcshareddata/xcschemes/{djban.xcscheme => djbench.xcscheme} (99%) diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index 7fcc3cd3d85..92a3b6945c9 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -1264,7 +1264,7 @@ 3124CAE4156BE6D500753214 /* fmthe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmthe.c; sourceTree = ""; }; 3124CAEB156BE7F300753214 /* amcss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcss; sourceTree = BUILT_PRODUCTS_DIR; }; 3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = ""; }; - 31379493176CC34D00BCFAEC /* djban */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djban; sourceTree = BUILT_PRODUCTS_DIR; }; + 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 = ""; }; @@ -1848,7 +1848,7 @@ 2291A5E3175CB05F001D4920 /* exposet0 */, 224CC799175E1821002FF81B /* fotest */, 31FCAE0A17692403008C034C /* scheme */, - 31379493176CC34D00BCFAEC /* djban */, + 31379493176CC34D00BCFAEC /* djbench */, ); name = Products; sourceTree = ""; @@ -2570,7 +2570,7 @@ ); name = djbench; productName = djban; - productReference = 31379493176CC34D00BCFAEC /* djban */; + productReference = 31379493176CC34D00BCFAEC /* djbench */; productType = "com.apple.product-type.tool"; }; 31D6000C156D3CB200337B26 /* awluthe */ = { @@ -4260,6 +4260,10 @@ 3137949A176CC34D00BCFAEC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + CONFIG_VAR_COOL, + CONFIG_PROD_EPCORE, + ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -4268,6 +4272,10 @@ 3137949B176CC34D00BCFAEC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + CONFIG_VAR_HOT, + MPS_PROD_EPCORE, + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -4275,6 +4283,10 @@ 3137949C176CC34D00BCFAEC /* WE */ = { isa = XCBuildConfiguration; buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + CONFIG_VAR_WE, + MPS_PROD_EPCORE, + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = WE; diff --git a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme similarity index 99% rename from mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme rename to mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme index 3841b0cbcd1..2e10ee7e32d 100644 --- a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djban.xcscheme +++ b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme @@ -40,8 +40,8 @@ Date: Sun, 16 Jun 2013 15:32:43 +0100 Subject: [PATCH 10/14] Tidying up djbench and merging into a single file rather than relying on #include hacks. Copied from Perforce Change: 182774 ServerID: perforce.ravenbrook.com --- mps/code/djbench.c | 127 +++++++++++++----- mps/code/djrun.c | 48 ------- mps/code/mps.xcodeproj/project.pbxproj | 2 - .../xcshareddata/xcschemes/djbench.xcscheme | 8 +- 4 files changed, 95 insertions(+), 90 deletions(-) delete mode 100644 mps/code/djrun.c 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 @@ From d02bc32f5f61e0cf00859596459550b784483b8d Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 15:36:17 +0100 Subject: [PATCH 11/14] Adding leader comment description, copyright, and license. Copied from Perforce Change: 182775 ServerID: perforce.ravenbrook.com --- mps/code/djbench.c | 53 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/mps/code/djbench.c b/mps/code/djbench.c index 23006445190..d4479266d8f 100644 --- a/mps/code/djbench.c +++ b/mps/code/djbench.c @@ -1,5 +1,14 @@ -/* djban.c -- "DJ" Benchmark on ANSI C library +/* djbench.c -- "DJ" Benchmark on ANSI C library + * * $Id$ + * Copyright 2013 Ravenbrook Limited. See end of file for license. + * + * This is an allocation stress benchmark test for manual variable pools + * and also for stdlib malloc/free (for comparison). + * + * It repeatedly runs over an array of blocks and allocates or frees them + * with some probability, then frees all the remaining blocks at the end. + * This test can be iterated. */ #include @@ -242,3 +251,45 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } + + +/* C. COPYRIGHT AND LICENSE + * + * Copyright (c) 2001-2013 Ravenbrook Limited . + * All rights reserved. This is an open source license. Contact + * Ravenbrook for commercial licensing options. + * + * 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. + * + * 3. Redistributions in any form must be accompanied by information on how + * to obtain complete source code for this software and any accompanying + * software that uses this software. The source code must either be + * included in the distribution or be available for no more than the cost + * of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source + * code means the source code for all modules it contains. It does not + * include source code for modules or files that typically accompany the + * major components of the operating system on which the executable file + * runs. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS AND CONTRIBUTORS 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 + * USE, 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. + */ From 8ef0a0be214481aaf3878f4f9cab1fd84a9a6175 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 18:59:54 +0100 Subject: [PATCH 12/14] Adding recursion factor and repeatable random number seeding to dj benchmark. Copied from Perforce Change: 182776 ServerID: perforce.ravenbrook.com --- mps/code/djbench.c | 137 +++++++++++------- mps/code/mps.xcodeproj/project.pbxproj | 5 +- .../xcshareddata/xcschemes/djbench.xcscheme | 10 +- mps/code/testlib.c | 16 +- mps/code/testlib.h | 1 + 5 files changed, 110 insertions(+), 59 deletions(-) diff --git a/mps/code/djbench.c b/mps/code/djbench.c index d4479266d8f..4971e616406 100644 --- a/mps/code/djbench.c +++ b/mps/code/djbench.c @@ -30,47 +30,60 @@ static mps_ap_t ap; opportunities for compiler optimisation and the intended inlining of the MPS functions. */ -static unsigned niter = 100; /* iterations */ -static unsigned npass = 1000; /* passes over blocks */ -static unsigned nblocks = 1000; /* number of blocks */ +static rnd_state_t seed = 0; /* random number seed */ +static unsigned niter = 50; /* iterations */ +static unsigned npass = 100; /* passes over blocks */ +static unsigned nblocks = 64; /* number of blocks */ static unsigned sshift = 18; /* log2 max block size in words */ -static double prob = 0.2; /* probability per pass of acting */ +static double pact = 0.2; /* probability per pass of acting */ +static unsigned rinter = 75; /* pass interval for recursion */ +static unsigned rmax = 10; /* maximum recursion depth */ -#define DJRUN(alloc, free) \ - do { \ +#define DJRUN(fname, alloc, free) \ + static unsigned fname##_inner(unsigned depth, unsigned r) { \ struct {void *p; size_t s;} *blocks = alloca(sizeof(*blocks) * nblocks); \ - unsigned i, j, k; \ + unsigned 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 (j = 0; j < npass; ++j) { \ + for (k = 0; k < nblocks; ++k) { \ + if (rnd() % 16384 < pact * 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; \ - } \ + if (rinter > 0 && depth > 0 && ++r % rinter == 0) { \ + /* putchar('>'); fflush(stdout); */ \ + r = fname##_inner(depth - 1, r); \ + /* putchar('<'); fflush(stdout); */ \ } \ } \ - } while(0) + \ + for (k = 0; k < nblocks; ++k) { \ + if (blocks[k].p) { \ + free(blocks[k].p, blocks[k].s); \ + blocks[k].p = NULL; \ + } \ + } \ + return r; \ + } \ + \ + static void fname(void) { \ + unsigned i; \ + for (i = 0; i < niter; ++i) \ + (void)fname##_inner(rmax, 0); \ + } /* malloc/free benchmark */ @@ -78,18 +91,16 @@ static double prob = 0.2; /* probability per pass of acting */ #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); -} +DJRUN(dj_malloc, 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); -} +DJRUN(dj_alloc, MPS_ALLOC, MPS_FREE) + /* reserve/free benchmark */ @@ -102,9 +113,7 @@ static void dj_alloc(void) { } while(0) #define RESERVE_FREE(p, s) do { mps_free(pool, p, s); } while(0) -static void dj_reserve(void) { - DJRUN(RESERVE_ALLOC, RESERVE_FREE); -} +DJRUN(dj_reserve, RESERVE_ALLOC, RESERVE_FREE) /* Wrap a call to dj benchmark that doesn't require MPS setup */ @@ -152,11 +161,15 @@ 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[] = { + {"help", no_argument, NULL, 'h'}, {"niter", required_argument, NULL, 'i'}, {"npass", required_argument, NULL, 'p'}, {"nblocks", required_argument, NULL, 'b'}, {"sshift", required_argument, NULL, 's'}, - {"prob", required_argument, NULL, 'r'}, + {"pact", required_argument, NULL, 'a'}, + {"rinter", required_argument, NULL, 'r'}, + {"rmax", required_argument, NULL, 'd'}, + {"seed", required_argument, NULL, 'x'}, {NULL, 0, NULL, 0} }; @@ -187,8 +200,10 @@ static struct { int main(int argc, char *argv[]) { int ch; unsigned i; + + seed = rnd_seed(); - while ((ch = getopt_long(argc, argv, "i:p:b:s:r:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "hi:p:b:s:a:r:d:x:", longopts, NULL)) != -1) switch (ch) { case 'i': niter = (unsigned)strtoul(optarg, NULL, 10); @@ -202,8 +217,17 @@ int main(int argc, char *argv[]) { case 's': sshift = (unsigned)strtoul(optarg, NULL, 10); break; + case 'a': + pact = strtod(optarg, NULL); + break; case 'r': - prob = strtod(optarg, NULL); + rinter = (unsigned)strtoul(optarg, NULL, 10); + break; + case 'd': + rmax = (unsigned)strtoul(optarg, NULL, 10); + break; + case 'x': + seed = strtoul(optarg, NULL, 10); break; default: fprintf(stderr, @@ -217,34 +241,45 @@ int main(int argc, char *argv[]) { " Length of the block array (default %u).\n" " -s n, --sshift=n\n" " Log2 max block size in words (default %u).\n" - " -r p, --prob=p\n" - " Probability of acting on a block (default %g).\n" + " -a p, --pact=p\n" + " Probability of acting on a block (default %g).\n", + argv[0], + niter, + npass, + nblocks, + sshift, + pact); + fprintf(stderr, + " -r n, --rinter=n\n" + " Recurse every n passes if n > 0 (default %u).\n" + " -d n, --rmax=n\n" + " Maximum recursion depth (default %u).\n" + " -x n, --seed=n\n" + " Random number seed (default from entropy).\n" "Tests:\n" " mvt pool class MVT\n" " mvff pool class MVFF\n" " mv pool class MV\n" " mvb pool class MV with buffers\n" " an malloc\n", - argv[0], - niter, - npass, - nblocks, - sshift, - prob); + rinter, + rmax); return EXIT_FAILURE; } argc -= optind; argv += optind; + printf("seed: %lu\n", seed); + while (argc > 0) { for (i = 0; i < sizeof(pools) / sizeof(pools[0]); ++i) - if (strcmp(argv[0], pools[i].name) == 0) { - pools[i].wrap(pools[i].dj, pools[i].pool_class(), pools[i].name); + if (strcmp(argv[0], pools[i].name) == 0) goto found; - } fprintf(stderr, "unknown pool test \"%s\"\n", argv[0]); return EXIT_FAILURE; found: + rnd_state_set(seed); + pools[i].wrap(pools[i].dj, pools[i].pool_class(), pools[i].name); --argc; ++argv; } diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index a644c698605..e63825869bc 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -4282,9 +4282,10 @@ isa = XCBuildConfiguration; buildSettings = { GCC_PREPROCESSOR_DEFINITIONS = ( - CONFIG_VAR_WE, + CONFIG_VAR_RASH, MPS_PROD_EPCORE, ); + GCC_TREAT_WARNINGS_AS_ERRORS = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = WE; @@ -4299,7 +4300,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = ansi; GCC_OPTIMIZATION_LEVEL = 2; - GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_WE; + GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_RASH; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; diff --git a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme index c659271ec47..edab6272d9e 100644 --- a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme +++ b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme @@ -59,7 +59,7 @@ + + + + diff --git a/mps/code/testlib.c b/mps/code/testlib.c index fe81040ae85..9de6e7e232f 100644 --- a/mps/code/testlib.c +++ b/mps/code/testlib.c @@ -236,6 +236,16 @@ double rnd_double(void) } +rnd_state_t rnd_seed(void) +{ + /* Initialize seed based on seconds since epoch and on processor + * cycle count. */ + EventClock t2; + EVENT_CLOCK(t2); + return 1 + ((unsigned long)time(NULL) + (unsigned long)t2) % (R_m - 1); +} + + /* randomize -- randomize the generator, or initialize to replay * * There have been 3 versions of the rnd-states reported by this @@ -270,11 +280,7 @@ void randomize(int argc, char *argv[]) argv[0], seed0); rnd_state_set(seed0); } else { - /* Initialize seed based on seconds since epoch and on processor - * cycle count. */ - EventClock t2; - EVENT_CLOCK(t2); - seed0 = 1 + ((unsigned long)time(NULL) + (unsigned long)t2) % (R_m - 1); + seed0 = rnd_seed(); printf("%s: randomize(): choosing initial state (v3): %lu.\n", argv[0], seed0); rnd_state_set(seed0); diff --git a/mps/code/testlib.h b/mps/code/testlib.h index 9df253d797e..37fa12cbcaa 100644 --- a/mps/code/testlib.h +++ b/mps/code/testlib.h @@ -200,6 +200,7 @@ typedef unsigned long rnd_state_t; extern rnd_state_t rnd_state(void); extern void rnd_state_set(rnd_state_t state_v3); extern void rnd_state_set_v2(rnd_state_t seed0_v2); /* legacy */ +extern rnd_state_t rnd_seed(void); /* rnd_verify() -- checks behaviour of rnd() */ From b0e4e8528fe81ed9c2bc7bf8a7331466d7f7919e Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sun, 16 Jun 2013 21:20:29 +0100 Subject: [PATCH 13/14] Adding multi-threading to djbench in order to test performance with thread contention. Copied from Perforce Change: 182778 ServerID: perforce.ravenbrook.com --- mps/code/djbench.c | 97 ++++++++++++++----- .../xcshareddata/xcschemes/djbench.xcscheme | 18 +++- 2 files changed, 85 insertions(+), 30 deletions(-) diff --git a/mps/code/djbench.c b/mps/code/djbench.c index 4971e616406..4e23a3a6bc1 100644 --- a/mps/code/djbench.c +++ b/mps/code/djbench.c @@ -15,15 +15,24 @@ #include #include #include +#include #include "getopt.h" #include "testlib.h" #include "mps.c" +#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 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 @@ -31,6 +40,7 @@ static mps_ap_t ap; MPS functions. */ static rnd_state_t seed = 0; /* random number seed */ +static unsigned nthreads = 1; /* threads */ static unsigned niter = 50; /* iterations */ static unsigned npass = 100; /* passes over blocks */ static unsigned nblocks = 64; /* number of blocks */ @@ -40,8 +50,8 @@ static unsigned rinter = 75; /* pass interval for recursion */ static unsigned rmax = 10; /* maximum recursion depth */ #define DJRUN(fname, alloc, free) \ - static unsigned fname##_inner(unsigned depth, unsigned r) { \ - struct {void *p; size_t s;} *blocks = alloca(sizeof(*blocks) * nblocks); \ + static unsigned fname##_inner(mps_ap_t ap, unsigned depth, unsigned r) { \ + struct {void *p; size_t s;} *blocks = alloca(sizeof(blocks[0]) * nblocks); \ unsigned j, k; \ \ for (k = 0; k < nblocks; ++k) { \ @@ -65,7 +75,7 @@ static unsigned rmax = 10; /* maximum recursion depth */ } \ if (rinter > 0 && depth > 0 && ++r % rinter == 0) { \ /* putchar('>'); fflush(stdout); */ \ - r = fname##_inner(depth - 1, r); \ + r = fname##_inner(ap, depth - 1, r); \ /* putchar('<'); fflush(stdout); */ \ } \ } \ @@ -79,10 +89,16 @@ static unsigned rmax = 10; /* maximum recursion depth */ return r; \ } \ \ - static void fname(void) { \ + static void *fname(void *p) { \ unsigned i; \ + mps_ap_t ap = NULL; \ + if (pool != NULL) \ + MUST(mps_ap_create_k(&ap, pool, mps_args_none)); \ for (i = 0; i < niter; ++i) \ - (void)fname##_inner(rmax, 0); \ + (void)fname##_inner(ap, rmax, 0); \ + if (ap != NULL) \ + mps_ap_destroy(ap); \ + return p; \ } @@ -115,34 +131,59 @@ DJRUN(dj_alloc, MPS_ALLOC, MPS_FREE) DJRUN(dj_reserve, RESERVE_ALLOC, RESERVE_FREE) +typedef void *(*dj_t)(void *); -/* Wrap a call to dj benchmark that doesn't require MPS setup */ +static void weave(dj_t dj) +{ + pthread_t *threads = alloca(sizeof(threads[0]) * nthreads); + unsigned t; + + for (t = 0; t < nthreads; ++t) { + int err = pthread_create(&threads[t], NULL, dj, NULL); + if (err != 0) { + fprintf(stderr, "Unable to create thread: %d\n", err); + exit(EXIT_FAILURE); + } + } + + for (t = 0; t < nthreads; ++t) { + int err = pthread_join(threads[t], NULL); + if (err != 0) { + fprintf(stderr, "Unable to join thread: %d\n", err); + exit(EXIT_FAILURE); + } + } +} -static void wrap(void (*dj)(void), mps_class_t dummy, const char *name) + +static void watch(dj_t dj, const char *name) { clock_t start, finish; - (void)dummy; start = clock(); - dj(); + if (nthreads == 1) + dj(NULL); + else + weave(dj); finish = clock(); printf("%s: %g\n", name, (double)(finish - start) / CLOCKS_PER_SEC); } +/* Wrap a call to dj benchmark that doesn't require MPS setup */ + +static void wrap(dj_t dj, mps_class_t dummy, const char *name) +{ + (void)dummy; + pool = NULL; + watch(dj, 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) +static void arena_wrap(dj_t dj, mps_class_t pool_class, const char *name) { MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 256ul * 1024 * 1024); /* FIXME: Why is there no default? */ @@ -150,9 +191,7 @@ static void arena_wrap(void (*dj)(void), mps_class_t pool_class, const char *nam MUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args)); } MPS_ARGS_END(args); MUST(mps_pool_create_k(&pool, arena, pool_class, mps_args_none)); - MUST(mps_ap_create_k(&ap, pool, mps_args_none)); - wrap(dj, NULL, name); - mps_ap_destroy(ap); + watch(dj, name); mps_pool_destroy(pool); mps_arena_destroy(arena); } @@ -162,6 +201,7 @@ static void arena_wrap(void (*dj)(void), mps_class_t pool_class, const char *nam static struct option longopts[] = { {"help", no_argument, NULL, 'h'}, + {"nthreads",required_argument, NULL, 't'}, {"niter", required_argument, NULL, 'i'}, {"npass", required_argument, NULL, 'p'}, {"nblocks", required_argument, NULL, 'b'}, @@ -183,8 +223,8 @@ static mps_class_t dummy_class(void) static struct { const char *name; - void (*wrap)(void (*)(void), mps_class_t, const char *name); - void (*dj)(void); + void (*wrap)(dj_t, mps_class_t, const char *name); + dj_t dj; mps_class_t (*pool_class)(void); } pools[] = { {"mvt", arena_wrap, dj_reserve, mps_class_mvt}, @@ -203,8 +243,11 @@ int main(int argc, char *argv[]) { seed = rnd_seed(); - while ((ch = getopt_long(argc, argv, "hi:p:b:s:a:r:d:x:", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "ht:i:p:b:s:a:r:d:x:", longopts, NULL)) != -1) switch (ch) { + case 't': + nthreads = (unsigned)strtoul(optarg, NULL, 10); + break; case 'i': niter = (unsigned)strtoul(optarg, NULL, 10); break; @@ -233,6 +276,8 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Usage: %s [option...] [test...]\n" "Options:\n" + " -t n, --nthreads=n\n" + " Launch n threads each running the test\n" " -i n, --niter=n\n" " Iterate each test n times (default %u).\n" " -p n, --npass=n\n" diff --git a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme index edab6272d9e..a68469add5c 100644 --- a/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme +++ b/mps/code/mps.xcodeproj/xcshareddata/xcschemes/djbench.xcscheme @@ -59,7 +59,7 @@ + + + + + + From fa4962877081504caf724068ba56975dee2f6ad4 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Fri, 24 Jan 2014 15:07:33 +0000 Subject: [PATCH 14/14] Adding const qualifier to various strings as required by xcode. Copied from Perforce Change: 184105 ServerID: perforce.ravenbrook.com --- mps/example/scheme/scheme.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/mps/example/scheme/scheme.c b/mps/example/scheme/scheme.c index e7fe547e490..f790a9d1e03 100644 --- a/mps/example/scheme/scheme.c +++ b/mps/example/scheme/scheme.c @@ -133,12 +133,12 @@ typedef struct integer_s { typedef struct special_s { type_t type; /* TYPE_SPECIAL */ - char *name; /* printed representation, NUL terminated */ + const char *name; /* printed representation, NUL terminated */ } special_s; typedef struct operator_s { type_t type; /* TYPE_OPERATOR */ - char *name; /* printed name, NUL terminated */ + const char *name; /* printed name, NUL terminated */ entry_t entry; /* entry point -- see eval() */ obj_t arguments, body; /* function arguments and code */ obj_t env, op_env; /* closure environments */ @@ -389,7 +389,7 @@ static mps_ap_t obj_ap; /* allocation point used to allocate objects */ * message. */ -static void error(char *format, ...) +static void error(const char *format, ...) { va_list args; @@ -484,7 +484,7 @@ static obj_t make_integer(long integer) return obj; } -static obj_t make_symbol(size_t length, char string[]) +static obj_t make_symbol(size_t length, const char string[]) { obj_t obj; mps_addr_t addr; @@ -519,7 +519,7 @@ static obj_t make_string(size_t length, char string[]) return obj; } -static obj_t make_special(char *string) +static obj_t make_special(const char *string) { obj_t obj; mps_addr_t addr; @@ -535,7 +535,7 @@ static obj_t make_special(char *string) return obj; } -static obj_t make_operator(char *name, +static obj_t make_operator(const char *name, entry_t entry, obj_t arguments, obj_t body, obj_t env, obj_t op_env) { @@ -732,7 +732,7 @@ static unsigned long hash(const char *s, size_t length) { * is full. */ -static obj_t *find(char *string) { +static obj_t *find(const char *string) { unsigned long i, h, probe; h = hash(string, strlen(string)); @@ -791,7 +791,7 @@ static void rehash(void) { } /* union-find string in symbol table, rehashing if necessary */ -static obj_t intern(char *string) { +static obj_t intern(const char *string) { obj_t *where; where = find(string); @@ -1549,7 +1549,7 @@ static obj_t load(obj_t env, obj_t op_env, obj_t filename) { * using the message given. */ -static obj_t eval_list(obj_t env, obj_t op_env, obj_t list, char *message) +static obj_t eval_list(obj_t env, obj_t op_env, obj_t list, const char *message) { obj_t result, end, pair; result = obj_empty; @@ -1574,7 +1574,7 @@ static obj_t eval_list(obj_t env, obj_t op_env, obj_t list, char *message) * See eval_args and eval_args_rest for usage. */ -static obj_t eval_args1(char *name, obj_t env, obj_t op_env, +static obj_t eval_args1(const char *name, obj_t env, obj_t op_env, obj_t operands, unsigned n, va_list args) { unsigned i; @@ -1599,7 +1599,7 @@ static obj_t eval_args1(char *name, obj_t env, obj_t op_env, * eval_args("foo", env, op_env, operands, 2, &arg1, &arg2); */ -static void eval_args(char *name, obj_t env, obj_t op_env, +static void eval_args(const char *name, obj_t env, obj_t op_env, obj_t operands, unsigned n, ...) { va_list args; @@ -1623,7 +1623,7 @@ static void eval_args(char *name, obj_t env, obj_t op_env, * eval_args_rest("foo", env, op_env, operands, &rest, 2, &arg1, &arg2); */ -static void eval_args_rest(char *name, obj_t env, obj_t op_env, +static void eval_args_rest(const char *name, obj_t env, obj_t op_env, obj_t operands, obj_t *restp, unsigned n, ...) { va_list args; @@ -3731,7 +3731,7 @@ static obj_t entry_gc(obj_t env, obj_t op_env, obj_t operator, obj_t operands) /* special table */ -static struct {char *name; obj_t *varp;} sptab[] = { +static struct {const char *name; obj_t *varp;} sptab[] = { {"()", &obj_empty}, {"#[eof]", &obj_eof}, {"#[error]", &obj_error}, @@ -3745,7 +3745,7 @@ static struct {char *name; obj_t *varp;} sptab[] = { /* initial symbol table */ -static struct {char *name; obj_t *varp;} isymtab[] = { +static struct {const char *name; obj_t *varp;} isymtab[] = { {"quote", &obj_quote}, {"lambda", &obj_lambda}, {"begin", &obj_begin}, @@ -3758,7 +3758,7 @@ static struct {char *name; obj_t *varp;} isymtab[] = { /* operator table */ -static struct {char *name; entry_t entry;} optab[] = { +static struct {const char *name; entry_t entry;} optab[] = { {"quote", entry_quote}, {"define", entry_define}, {"set!", entry_set}, @@ -3779,7 +3779,7 @@ static struct {char *name; entry_t entry;} optab[] = { /* function table */ -static struct {char *name; entry_t entry;} funtab[] = { +static struct {const char *name; entry_t entry;} funtab[] = { {"not", entry_not}, {"boolean?", entry_booleanp}, {"eqv?", entry_eqvp},