diff --git a/.classpath b/.classpath index e67f75959..e0fdb6c1b 100644 --- a/.classpath +++ b/.classpath @@ -23,6 +23,6 @@ - + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index adc24059d..1c73d4f6e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -63,13 +63,13 @@ benchmark_job: - ant compile - rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns -benchmark_csp_and_interp_job: +benchmark_job_others: stage: benchmark tags: [benchmarks, infinity] allow_failure: true script: - ant compile - - rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns-SavinaCSP + - rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns-concurrency-models - rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns-interp benchmark_nightly_job: diff --git a/build.xml b/build.xml index a1f6bce0a..a5e826d01 100644 --- a/build.xml +++ b/build.xml @@ -238,6 +238,9 @@ + diff --git a/codespeed.conf b/codespeed.conf index 248b365f6..e347898fa 100644 --- a/codespeed.conf +++ b/codespeed.conf @@ -56,21 +56,10 @@ benchmark_suites: - PageRank: extra_args: "1 0 100" codespeed_name: "1st.PageRank" - - Lee: - extra_args: "1 0 4" - codespeed_name: "1st.Lee" - - LeeSTM: - extra_args: "1 0 4" - codespeed_name: "1st.LeeSTM" - - Vacation: - extra_args: "1 0 8" - codespeed_name: "1st.Vacation" - - VacationSTM: - extra_args: "1 0 8" - codespeed_name: "1st.VacationSTM" - Splay: extra_args: "1 0 1" codespeed_name: "1st.Splay" + macro-steady: gauge_adapter: RebenchLog command: *MACRO_CMD @@ -117,18 +106,6 @@ benchmark_suites: extra_args: "120 0 1000" codespeed_name: "peak.PageRank" warmup: 20 - - Lee: - extra_args: "150 0 2" - codespeed_name: "peak.Lee" - - LeeSTM: - extra_args: "150 0 4" - codespeed_name: "peak.LeeSTM" - - Vacation: - extra_args: "150 0 12" - codespeed_name: "peak.Vacation" - - VacationSTM: - extra_args: "150 0 10" - codespeed_name: "peak.VacationSTM" - Splay: extra_args: "150 0 1" codespeed_name: "peak.Splay" @@ -475,7 +452,7 @@ benchmark_suites: extra_args: "130 0 1000" codespeed_name: "i.Messages" - fj-steady: + fj-seq-steady: description: Sequential version of Fork/Join benchmarks for normal performance tracking gauge_adapter: RebenchLog command: &FJ_CMD " core-lib/Benchmarks/Harness.ns core-lib/Benchmarks/ForkJoin/%(benchmark)s%(input)s.ns " @@ -499,7 +476,7 @@ benchmark_suites: extra_args: "130 0 256" codespeed_name: "peak.LUDecomposition" - fj-startup: + fj-seq-startup: description: Sequential version of Fork/Join benchmarks for normal performance tracking gauge_adapter: RebenchLog command: *FJ_CMD @@ -554,10 +531,11 @@ benchmark_suites: # - UTS: # extra_args: 1 - savina-csp: + csp-steady: description: CSP port of the savina benchmarks gauge_adapter: RebenchLog - command: &CSP_CMD " core-lib/Benchmarks/Harness.ns SavinaCSP.%(benchmark)s 125 0" + command: &HARNESS_W_ITER " core-lib/Benchmarks/Harness.ns %(benchmark)s %(iterations)s 0" + iterations: 125 max_invocation_time: 500 warmup: 30 benchmarks: @@ -574,25 +552,90 @@ benchmark_suites: extra_args: "200 4" codespeed_name: "CSP.Philosophers" - savina-csp-interp: + csp-startup: description: CSP port of the savina benchmarks gauge_adapter: RebenchLog - command: &CSP_INTERP_CMD " core-lib/Benchmarks/Harness.ns SavinaCSP.%(benchmark)s 50 0" + command: *HARNESS_W_ITER + iterations: 1 + invocations: 3 max_invocation_time: 500 warmup: 30 benchmarks: - PingPong: #numMessages numThreads, numThreads is unused extra_args: "8000 2" - codespeed_name: "CSP.PingPong" - ForkJoinThroughput: #numMessages numThreads extra_args: "8000 4" - codespeed_name: "CSP.ForkJoinThroughput" - Philosophers: #numrounds numThreads, uses numThreads - 1 Philosophers extra_args: "700 4" - codespeed_name: "CSP.Philosophers" + + mutex-startup: + description: various mutex based benchmarks + gauge_adapter: RebenchLog + command: *HARNESS_W_ITER + max_invocation_time: 500 + iterations: 1 + invocations: 3 + warmup: 30 + benchmarks: + - MutexSuite.ProducerConsumer: + #buffersize numThreads, split threads equally into producers and consumers + extra_args: "4000 4" + - MutexSuite.Philosophers: + #numrounds numThreads, uses numThreads - 1 Philosophers + extra_args: "50000 4" + - Lee: + extra_args: 4 + - Vacation: + extra_args: 8 + + mutex-steady: + description: various mutex based benchmarks + gauge_adapter: RebenchLog + command: *HARNESS_W_ITER + max_invocation_time: 500 + iterations: 150 + warmup: 30 + benchmarks: + - MutexSuite.ProducerConsumer: + #buffersize numThreads, split threads equally into producers and consumers + extra_args: "4000 4" + - MutexSuite.Philosophers: + #numrounds numThreads, uses numThreads - 1 Philosophers + extra_args: "50000 4" + - Lee: + extra_args: 2 + - Vacation: + extra_args: 12 + + stm-startup: + description: various mutex based benchmarks + gauge_adapter: RebenchLog + command: *HARNESS_W_ITER + max_invocation_time: 500 + iterations: 1 + invocations: 3 + warmup: 30 + benchmarks: + - LeeSTM: + extra_args: 1 + - VacationSTM: + extra_args: 1 + + stm-steady: + description: various mutex based benchmarks + gauge_adapter: RebenchLog + command: *HARNESS_W_ITER + max_invocation_time: 500 + iterations: 150 + warmup: 30 + benchmarks: + - LeeSTM: + extra_args: 4 + - VacationSTM: + extra_args: 10 # VMs have a name and are specified by a path and the binary to be executed executors: @@ -679,8 +722,8 @@ experiments: - sort-steady - som-startup - som-steady - - fj-startup - - fj-steady + - fj-seq-startup + - fj-seq-steady executions: - SOMns-graal SOMns-Savina: @@ -693,15 +736,13 @@ experiments: suites: - savina-jit - SOMns-SavinaCSP: - description: Run the Savina Actor benchmarks + SOMns-concurrency-models: + suites: + - mutex-steady + - stm-steady + - csp-steady executions: - - SOMns-interp-tn: - suites: - - savina-csp-interp - - SOMns-graal-tn: - suites: - - savina-csp + - SOMns-graal-tn SOMns-interp: description: All benchmarks on SOMns without Graal diff --git a/core-lib/Benchmarks/MutexSuite.ns b/core-lib/Benchmarks/MutexSuite.ns new file mode 100644 index 000000000..3025e5092 --- /dev/null +++ b/core-lib/Benchmarks/MutexSuite.ns @@ -0,0 +1,261 @@ +class MutexSuite usingPlatform: platform andHarness: harness = Value ( +| private Benchmark = harness Benchmark. + private processes = platform processes. + private Channel = processes Channel. + private Process = processes Process. + private Array = platform kernel Array. + private Condition = platform threading Condition. + private Delay = platform threading Delay. + private Mutex = platform threading Mutex. + private Thread = platform threading Thread. +|)( + (* A simple PRNG, to be as portable as possible. *) + public class Random new: seed = ( + | private seed ::= seed. + private gotNextGaussian ::= false. + private nextNextGaussian ::= 0.0. | + ) ( + public next = ( + seed:: ((seed * 1309) + 13849) & 65535. + ^ seed + ) + + (* Returns an integer within the range of [0, bound) *) + public next: bound = ( + ^ next % bound + ) + + (* Returns a double uniformly distributed in the range of [0.0, 1.0) *) + public nextDouble = ( + ^ next // 65536 + ) + + public nextBoolean = ( + ^ next < 32768 + ) + + (* Returns a double normally distributed with mean 0.0 + and standard deviation of 1.0 *) + public nextGaussian = ( + | v1 v2 s multiplier | + gotNextGaussian ifTrue: [ + gotNextGaussian:: false. + ^ nextNextGaussian ]. + + v1:: (2.0 * nextDouble) - 1.0. + v2:: (2.0 * nextDouble) - 1.0. + s:: (v1 * v1) + (v2 * v2). + + [s >= 1.0 or: [s = 0.0]] whileTrue: [ + v1:: (2.0 * nextDouble) - 1.0. + v2:: (2.0 * nextDouble) - 1.0. + s:: (v1 * v1) + (v2 * v2). + ]. + + multiplier:: (-2.0 * s log // s) sqrt. + nextNextGaussian:: v2 * multiplier. + gotNextGaussian:: true. + ^ v1 * multiplier + ) + ) : ( + public new = ( + ^ new: 74755 + ) + ) + + (* === Savina Microbenchmarks === *) + + public class Philosophers new = Benchmark <: Value ()( + + private class Arbitrator new: numPhil numRounds: numRounds = ( + | private numPhil = numPhil. + private numRounds = numRounds. + private forks = Array new: numPhil withAll: false. + private numExitedPhilosophers ::= 0. + private m = Mutex new. + private m2 = Mutex new. + |)( + private hungry: leftForkId = ( + | rightForkId | + rightForkId:: 1 + ((leftForkId + 1) % numPhil). + + ((forks at: leftForkId) or: [forks at: rightForkId]) + ifTrue: [ + ^ false. + ] + ifFalse: [ + forks at: leftForkId put: true. + forks at: rightForkId put: true. + ^ true ] + ) + + private done: leftForkId = ( + | rightForkId | + rightForkId:: 1 + ((leftForkId + 1) % numPhil). + + forks at: leftForkId put: false. + forks at: rightForkId put: false. + ) + + private exit = ( + numExitedPhilosophers:: numExitedPhilosophers + 1. + + numPhil = numExitedPhilosophers ifTrue: [ + | forksTaken | + forksTaken:: 0. + forks do: [:f | f ifTrue: [ forksTaken:: forksTaken + 1 ] ]. + forksTaken = 0 ifFalse: [ + self error: 'invalid benchmark result'. + ]. + ] + ) + + public benchmark = ( + |philosophers| + philosophers:: Array new: numPhil. + philosophers doIndexes: [:i | + philosophers at: i put: (Thread spawn: [:id | + | roundsSoFar isEating | + roundsSoFar:: 0. + [roundsSoFar < numRounds] whileTrue: [ + m critical: [ + isEating:: (hungry: id). + ]. + + isEating ifTrue: [ + roundsSoFar:: roundsSoFar + 1. + m critical: [done: id]. + ]. + ]. + + m2 critical: [ + exit. + ]. + ] with: { i }) + ]. + + philosophers do: [:ph | ph join ]. + ^ true. + ) + ) + + public innerBenchmarkLoop: numRounds numThreads: threads = ( + | arbitrator | + arbitrator:: Arbitrator new: (threads - 1) numRounds: numRounds. + ^ arbitrator benchmark + ) + ) : ( + public newInstance = ( ^ self new ) + public setupVerifiedRun: run = ( run problemSize ) + ) + + + public class ProducerConsumer new = Benchmark <: Value ()( + private class SynchronizedRingBuffer new: capacity = ( + | buffer = Array new: capacity. + capacity = capacity. + head ::= 1. (* points to next write location *) + tail ::= 1. (* points to next read location *) + size ::= 0. + mutex = Mutex new. + waitingProducers = mutex newCondition. + waitingConsumers = mutex newCondition. + | + )( + private add: val = ( + buffer at: tail put: val. + tail:: (tail % capacity) + 1. + size:: size + 1. + ) + + private remove = ( + |result| + result:: buffer at: head. + head:: (head % capacity) + 1. + size:: size - 1. + ^ result. + ) + + public offer: val = ( + mutex critical: [ + (size = capacity) ifTrue: [ + (*'producer wait' println.*) + waitingProducers await. + (*'producer woke up' println.*) + ]. + + add: val. + size > 0 ifTrue: [ + waitingConsumers signalOne. + ] + ] + ) + + public poll = ( + mutex critical: [ + |res| + size > 0 ifFalse: [ + (*'consumer wait' println.*) + waitingConsumers await. + (*'consumer woke up' println.*) + ]. + res:: remove. + size < capacity ifTrue:[ + waitingProducers signalOne. + ]. + ^ res + ] + ) + ) + + private busyWait: limit = ( + | test | + test:: 0. + limit timesRepeat: [ + test:: test + 1 ]. + ^ test + ) + + public innerBenchmarkLoop: bufferSize numThreads: threads = ( + |consumers producers buffer numCycles| + consumers:: Array new: (threads / 2 ). + producers:: Array new: (threads / 2 ). + buffer:: SynchronizedRingBuffer new: bufferSize. + numCycles:: bufferSize * 10. + + consumers doIndexes: [:i | + consumers at: i put: (Thread spawn: [:id | + | rand | + rand:: Random new: id * 97 . + numCycles timesRepeat: [ + | rn | + rn:: rand next: 1000. + busyWait: rn. + buffer poll. + ]. + ] with: { i }) + ]. + + producers doIndexes: [:i | + producers at: i put: (Thread spawn: [:id | + | rand | + rand:: Random new: id * 53. + numCycles timesRepeat: [ + | rn | + rn:: rand next: 1000. + busyWait: rn. + buffer offer: rn. + ]. + ] with: { i }) + ]. + + consumers do: [:ph | ph join ]. + producers do: [:ph | ph join ]. + + ^ true. + ) + ) : ( + public newInstance = ( ^ self new ) + public setupVerifiedRun: run = ( run problemSize ) + ) +) diff --git a/core-lib/Benchmarks/STMSuite.ns b/core-lib/Benchmarks/STMSuite.ns new file mode 100644 index 000000000..8ac80bf52 --- /dev/null +++ b/core-lib/Benchmarks/STMSuite.ns @@ -0,0 +1,149 @@ +class STMSuite usingPlatform: platform andHarness: harness = Value ( +| private Benchmark = harness Benchmark. + private processes = platform processes. + private Channel = processes Channel. + private Process = processes Process. + private Array = platform kernel Array. + private Condition = platform threading Condition. + private Delay = platform threading Delay. + private Transaction = platform transactions Transaction. + private Thread = platform threading Thread. +|)( + (* A simple PRNG, to be as portable as possible. *) + public class Random new: seed = ( + | private seed ::= seed. + private gotNextGaussian ::= false. + private nextNextGaussian ::= 0.0. | + ) ( + public next = ( + seed:: ((seed * 1309) + 13849) & 65535. + ^ seed + ) + + (* Returns an integer within the range of [0, bound) *) + public next: bound = ( + ^ next % bound + ) + + (* Returns a double uniformly distributed in the range of [0.0, 1.0) *) + public nextDouble = ( + ^ next // 65536 + ) + + public nextBoolean = ( + ^ next < 32768 + ) + + (* Returns a double normally distributed with mean 0.0 + and standard deviation of 1.0 *) + public nextGaussian = ( + | v1 v2 s multiplier | + gotNextGaussian ifTrue: [ + gotNextGaussian:: false. + ^ nextNextGaussian ]. + + v1:: (2.0 * nextDouble) - 1.0. + v2:: (2.0 * nextDouble) - 1.0. + s:: (v1 * v1) + (v2 * v2). + + [s >= 1.0 or: [s = 0.0]] whileTrue: [ + v1:: (2.0 * nextDouble) - 1.0. + v2:: (2.0 * nextDouble) - 1.0. + s:: (v1 * v1) + (v2 * v2). + ]. + + multiplier:: (-2.0 * s log // s) sqrt. + nextNextGaussian:: v2 * multiplier. + gotNextGaussian:: true. + ^ v1 * multiplier + ) + ) : ( + public new = ( + ^ new: 74755 + ) + ) + + (* === Savina Microbenchmarks === *) + + public class Philosophers new = Benchmark <: Value ()( + + private class Arbitrator new: numPhil numRounds: numRounds = ( + | private numPhil = numPhil. + private numRounds = numRounds. + private forks = Array new: numPhil withAll: false. + private numExitedPhilosophers ::= 0. + |)( + private hungry: leftForkId = ( + | rightForkId | + rightForkId:: 1 + ((leftForkId + 1) % numPhil). + + ((forks at: leftForkId) or: [forks at: rightForkId]) + ifTrue: [ + ^ false. + ] + ifFalse: [ + forks at: leftForkId put: true. + forks at: rightForkId put: true. + ^ true ] + ) + + private done: leftForkId = ( + | rightForkId | + rightForkId:: 1 + ((leftForkId + 1) % numPhil). + + forks at: leftForkId put: false. + forks at: rightForkId put: false. + ) + + private exit = ( + numExitedPhilosophers:: numExitedPhilosophers + 1. + + numPhil = numExitedPhilosophers ifTrue: [ + | forksTaken | + forksTaken:: 0. + forks do: [:f | f ifTrue: [ forksTaken:: forksTaken + 1 ] ]. + forksTaken = 0 ifFalse: [ + self error: 'invalid benchmark result'. + ]. + ] + ) + + public benchmark = ( + |philosophers| + philosophers:: Array new: numPhil. + philosophers doIndexes: [:i | + philosophers at: i put: (Thread spawn: [:id | + | roundsSoFar isEating | + roundsSoFar:: 0. + [roundsSoFar < numRounds] whileTrue: [ + Transaction atomic: [ + isEating:: (hungry: id). + ]. + + isEating ifTrue: [ + roundsSoFar:: roundsSoFar + 1. + Transaction atomic: [done: id]. + ]. + ]. + + Transaction atomic: [ + exit. + ]. + ] with: { i }) + ]. + + philosophers do: [:ph | ph join ]. + ^ true. + ) + ) + + public innerBenchmarkLoop: numRounds numThreads: threads = ( + | arbitrator | + arbitrator:: Arbitrator new: (threads - 1) numRounds: numRounds. + ^ arbitrator benchmark + ) + ) : ( + public newInstance = ( ^ self new ) + public setupVerifiedRun: run = ( run problemSize ) + ) +) diff --git a/som b/som index bf4d67439..5afaea67e 100755 --- a/som +++ b/som @@ -261,9 +261,9 @@ SOM_ARGS = ['-Dbd.settings=som.vm.VmSettings', 'som.Launcher', '--platform', args.som_platform, '--kernel', args.som_kernel] # == Compiler Settings -TWEAK_INLINING = ['-Dgraal.TruffleCompilationThreshold=191', - '-Dgraal.TruffleInliningMaxCallerSize=10000', - '-Dgraal.TruffleSplittingMaxCalleeSize=100000'] +TWEAK_INLINING = ['-Dpolyglot.engine.CompilationThreshold=191', + '-Dpolyglot.engine.InliningMaxCallerSize=10000', + '-Dpolyglot.engine.SplittingMaxCalleeSize=100000'] JAVA_ARGS = ['-server', '-XX:+UseThreadPriorities'] @@ -290,7 +290,7 @@ else: if args.embedded_graal: flags += GRAAL_EMBEDDED_FLAGS if args.early_compilation: - flags += ['-Dgraal.TruffleCompilationThreshold=25', '-Dgraal.TruffleOSRCompilationThreshold=1000'] + flags += ['-Dpolyglot.engine.CompilationThreshold=25', '-Dpolyglot.engine.OSRCompilationThreshold=1000'] if args.som_dnu: flags += ['-Dsom.printStackTraceOnDNU=true'] @@ -334,9 +334,9 @@ if not args.interpreter and (args.graal_profile or args.graal_profile_allocation flags += ['-Dgraal.BenchmarkDynamicCounters=out,completed,total'] if not args.interpreter and args.graal_branch_profile: - flags += ['-Dgraal.TruffleInstrumentBranches=true', - '-Dgraal.TruffleInstrumentBranchesFilter=*', - '-Dgraal.TruffleInstrumentBranchesPerInlineSite=true'] + flags += ['-Dpolyglot.engine.InstrumentBranches=true', + '-Dpolyglot.engine.InstrumentBranchesFilter=*', + '-Dpolyglot.engine.InstrumentBranchesPerInlineSite=true'] if args.truffle_profile: flags += ['-Dtruffle.profiling.enabled=true'] @@ -402,17 +402,17 @@ if args.assisted_debugging_breakpoints: flags += ['-Dsom.assistedDebuggingBp=%s' % args.assisted_debugging_breakpoints ] if not args.interpreter and args.perf_warnings: - flags += ['-Dgraal.TruffleCompilationExceptionsAreFatal=true', - '-Dgraal.TraceTrufflePerformanceWarnings=true', - '-Dgraal.TraceTruffleCompilation=true', - '-Dgraal.TraceTruffleCompilationDetails=true'] + flags += ['-Dpolyglot.engine.CompilationExceptionsAreFatal=true', + '-Dpolyglot.engine.TracePerformanceWarnings=all', + '-Dpolyglot.engine.TraceCompilation=true', + '-Dpolyglot.engine.TraceCompilationDetails=true'] if not args.fail_missing_opts: flags += ['-DfailOnMissingOptimization=true'] if not args.interpreter and args.trace_invalidation: - flags += ['-Dgraal.TraceTruffleTransferToInterpreter=true', - '-Dgraal.TraceTruffleAssumptions=true'] + flags += ['-Dpolyglot.engine.TraceTransferToInterpreter=true', + '-Dpolyglot.engine.TraceAssumptions=true'] if not args.interpreter and args.only_compile: - flags.append("-Dgraal.TruffleCompileOnly=%s" % args.only_compile) + flags.append("-Dpolyglot.engine.CompileOnly=%s" % args.only_compile) if args.visual_vm: flags += ['-agentpath:/Users/smarr/Downloads/visualvm_143/profiler/lib/deployed/jdk16/mac/libprofilerinterface.jnilib=/Users/smarr/Downloads/visualvm_143/profiler/lib,5140'] if args.assert_: @@ -420,11 +420,11 @@ if args.assert_: else: flags += ['-dsa', '-da'] if not args.interpreter and not args.background_compilation: - flags += ['-Dgraal.TruffleBackgroundCompilation=false'] + flags += ['-Dpolyglot.engine.BackgroundCompilation=false'] if not args.interpreter and args.no_compilation: - flags.append('-Dgraal.TruffleCompileOnly=__FAKE_METHOD_NON_EXISTING__') + flags.append('-Dpolyglot.engine.CompileOnly=__FAKE_METHOD_NON_EXISTING__') if not args.interpreter and args.no_trace and not args.perf_warnings: - flags += ['-Dgraal.TraceTruffleInlining=false', '-Dgraal.TraceTruffleCompilation=false'] + flags += ['-Dpolyglot.engine.TraceInlining=false', '-Dpolyglot.engine.TraceCompilation=false'] if not args.interpreter and not args.graph_pe: flags += ['-Dgraal.GraphPE=false'] if args.threads: @@ -442,7 +442,9 @@ if args.java_args: flags += ['-Dsom.tools=' + BASE_DIR + '/tools'] flags += ['-Dsom.baseDir=' + BASE_DIR] -flags += ['-Dgraal.TruffleLanguageAgnosticInlining=false'] + +if not args.interpreter: + flags += ['-Dpolyglot.engine.LanguageAgnosticInlining=false'] if args.use_pinning: ## check whether there are any known restrictions to core usage diff --git a/src/som/vm/VmSettings.java b/src/som/vm/VmSettings.java index 88823d876..17c227045 100644 --- a/src/som/vm/VmSettings.java +++ b/src/som/vm/VmSettings.java @@ -88,7 +88,9 @@ public class VmSettings implements Settings { BASE_DIRECTORY = System.getProperty("som.baseDir", System.getProperty("user.dir")); - USE_PINNING = getBool("som.usePinning", true); + String osName = System.getProperty("os.name", "generic").toLowerCase(); + boolean isLinux = osName.contains("linux"); + USE_PINNING = getBool("som.usePinning", true) && isLinux; } private static boolean getBool(final String prop, final boolean defaultVal) {