forked from jonas/scala-js-benchmarks
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cross-compile the benchmarks on the JVM.
- Loading branch information
Showing
19 changed files
with
156 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,23 @@ | ||
# Scala.js Benchmarks | ||
|
||
This is a port of the Dart | ||
[benchmark harness](https://github.com/dart-lang/benchmark_harness) to | ||
[Scala.js](https://github.com/scala-js/scala-js). | ||
|
||
You can see the benchmarks in action | ||
[here](http://jonas.github.io/scala-js-benchmarks/). | ||
Benchmarks for [Scala.js](https://www.scala-js.org/) | ||
|
||
All derivative work is the copyright of their respective authors and | ||
distributed under their original license. All original work unless otherwise | ||
stated is distributed under the [same license as | ||
Scala.js](https://github.com/jonas/scala-js-benchmarks/LICENSE). | ||
Scala.js](https://github.com/sjrd/scala-js-benchmarks/LICENSE). | ||
|
||
## Get started | ||
|
||
To run the benchmarks, first install the Scala.js compiler by following the | ||
instructions in the [Scala.js README](https://github.com/lampepfl/scala-js). | ||
|
||
Next, open `sbt` either in the root folder or in the folder of the benchmark | ||
you want to run. Issue `packageJS` to compile the Scala code to JavaScript. | ||
For benchmarks with a web version, open the `index-dev.html` of the in your | ||
favorite Web browser. For benchmarks without a web version execute the | ||
`run.sh` script inside the benchmark folder. | ||
|
||
During development, it is useful to use `~packageJS` in sbt, so that each | ||
time you save a source file, a compilation of the project is triggered. | ||
Hence only a refresh of your Web page is needed to see the effects of your | ||
changes. | ||
|
||
## The optimized version | ||
|
||
Instead of running `packageJS`, you can also run `optimizeJS` to generate | ||
a much more compact version of the JavaScript code. While `index-dev.html` | ||
refers to the JavaScript emitted by `packageJS`, `index.html` refers to the | ||
optimized JavaScript emitted by `optimizeJS`. | ||
|
||
The optimization phase is performed by the Advanced Optimizations of the | ||
[Google Closure Compiler](https://developers.google.com/closure/compiler/), | ||
which make | ||
[strong assumptions](https://developers.google.com/closure/compiler/docs/api-tutorial3) | ||
about the code being compiled. | ||
|
||
All the code generated by Scala.js respects these assumptions. But if you | ||
modify `exports.js`, make sure that you comply with them if you want to be | ||
able to use `optimizeJS`. | ||
Open `sbt` and run the benchmarks with the `run` command of every project. | ||
For example, | ||
|
||
## Troubleshooting | ||
> richardsJS/run | ||
|
||
### I have unresolved dependencies on `scala-js-...` | ||
To test the fullOpt version, use, as usual: | ||
|
||
You have probably forgotten to execute `publishLocal` from the sbt prompt in | ||
Scala.js. | ||
> set scalaJSStage in Global := FullOptStage | ||
|
||
### WARNING - dangerous use of the global this object | ||
The benchmarks cross-compiled and can be run with the JVM too: | ||
|
||
This warning is emitted by the Google Closure Compiler when running | ||
`optimizeJS`. The global `this` object is used in the `exports.js` | ||
script as an alternative to `window` to export symbols used by the | ||
various startup code. This allows the benchmarks to run both in the web | ||
browser and in the `d8` (the V8 shell), which does not define global | ||
objects like `window`. | ||
> richardsJVM/run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,100 @@ | ||
import org.scalajs.core.tools.sem.CheckedBehavior.Unchecked | ||
|
||
val projectSettings = Seq( | ||
val projectSettings: Seq[Setting[_]] = Seq( | ||
organization := "scalajs-benchmarks", | ||
version := "0.1-SNAPSHOT" | ||
) | ||
|
||
val defaultSettings = projectSettings ++ Seq( | ||
val defaultSettings: Seq[Setting[_]] = projectSettings ++ Seq( | ||
scalaVersion := "2.11.8", | ||
scalacOptions ++= Seq( | ||
"-deprecation", | ||
"-unchecked", | ||
"-feature", | ||
"-encoding", "utf8" | ||
), | ||
) | ||
) | ||
|
||
val defaultJSSettings: Seq[Setting[_]] = Seq( | ||
scalaJSSemantics ~= { _.withAsInstanceOfs(Unchecked) }, | ||
persistLauncher := true | ||
) | ||
|
||
scalaJSUseRhino in Global := false | ||
|
||
lazy val parent = project.in(file(".")). | ||
settings(projectSettings: _*). | ||
settings( | ||
name := "Scala.js Benchmarks", | ||
publishArtifact in Compile := false | ||
).aggregate( | ||
common, | ||
deltablue, | ||
richards, | ||
sudoku, | ||
tracer | ||
) | ||
|
||
lazy val common = project. | ||
enablePlugins(ScalaJSPlugin). | ||
lazy val common = crossProject. | ||
settings(defaultSettings: _*). | ||
settings( | ||
name := s"Scala.js Benchmarks - Common", | ||
moduleName := "common", | ||
persistLauncher := false | ||
name := "Scala.js Benchmarks - Common", | ||
moduleName := "common" | ||
) | ||
|
||
lazy val deltablue = project. | ||
enablePlugins(ScalaJSPlugin). | ||
lazy val commonJVM = common.jvm | ||
lazy val commonJS = common.js | ||
|
||
lazy val deltablue = crossProject.crossType(CrossType.Pure). | ||
settings(defaultSettings: _*). | ||
jsSettings(defaultJSSettings: _*). | ||
settings( | ||
name := s"Scala.js Benchmarks - DeltaBlue", | ||
name := "Scala.js Benchmarks - DeltaBlue", | ||
moduleName := "deltablue" | ||
). | ||
dependsOn(common) | ||
|
||
lazy val richards = project. | ||
enablePlugins(ScalaJSPlugin). | ||
lazy val deltablueJVM = deltablue.jvm | ||
lazy val deltablueJS = deltablue.js | ||
|
||
lazy val richards = crossProject.crossType(CrossType.Pure). | ||
settings(defaultSettings: _*). | ||
jsSettings(defaultJSSettings: _*). | ||
settings( | ||
name := s"Scala.js Benchmarks - Richards", | ||
name := "Scala.js Benchmarks - Richards", | ||
moduleName := "richards" | ||
). | ||
dependsOn(common) | ||
|
||
lazy val sudoku = project. | ||
enablePlugins(ScalaJSPlugin). | ||
lazy val richardsJVM = richards.jvm | ||
lazy val richardsJS = richards.js | ||
|
||
lazy val sudoku = crossProject.crossType(CrossType.Pure). | ||
settings(defaultSettings: _*). | ||
jsSettings(defaultJSSettings: _*). | ||
settings( | ||
name := s"Scala.js Benchmarks - Sudoku", | ||
name := "Scala.js Benchmarks - Sudoku", | ||
moduleName := "sudoku" | ||
). | ||
dependsOn(common) | ||
|
||
lazy val tracer = project. | ||
enablePlugins(ScalaJSPlugin). | ||
lazy val sudokuJVM = sudoku.jvm | ||
lazy val sudokuJS = sudoku.js | ||
|
||
lazy val tracer = crossProject. | ||
settings(defaultSettings: _*). | ||
jsSettings(defaultJSSettings: _*). | ||
settings( | ||
name := s"Scala.js Benchmarks - Tracer", | ||
name := "Scala.js Benchmarks - Tracer", | ||
moduleName := "tracer" | ||
). | ||
dependsOn(common) | ||
|
||
lazy val sha512 = project. | ||
enablePlugins(ScalaJSPlugin). | ||
lazy val tracerJVM = tracer.jvm | ||
lazy val tracerJS = tracer.js | ||
|
||
lazy val sha512 = crossProject.crossType(CrossType.Pure). | ||
settings(defaultSettings: _*). | ||
jsSettings(defaultJSSettings: _*). | ||
settings( | ||
name := s"Scala.js Benchmarks - SHA-512", | ||
name := "Scala.js Benchmarks - SHA-512", | ||
moduleName := "sha512" | ||
). | ||
dependsOn(common) | ||
|
||
lazy val sha512JVM = sha512.jvm | ||
lazy val sha512JS = sha512.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
88 changes: 88 additions & 0 deletions
88
common/jvm/src/main/scala/org/scalajs/benchmark/Benchmark.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* __ *\ | ||
** ________ ___ / / ___ __ ____ Scala.js Benchmarks ** | ||
** / __/ __// _ | / / / _ | __ / // __/ (c) 2003-2016, LAMP/EPFL ** | ||
** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ ** | ||
** /____/\___/_/ |_/____/_/ | |__/ /____/ ** | ||
** |/____/ ** | ||
\* */ | ||
|
||
package org.scalajs.benchmark | ||
|
||
/** Simple benchmarking framework. | ||
* | ||
* The `run` method has to be defined by the user, who will perform the | ||
* timed operation there. | ||
* | ||
* This will run the benchmark a minimum of 5 times and for at least 2 | ||
* seconds. | ||
*/ | ||
abstract class Benchmark { | ||
|
||
def main(args: Array[String]): Unit = { | ||
main() | ||
} | ||
|
||
def main(): Unit = { | ||
val status = report() | ||
println(s"$prefix: $status") | ||
} | ||
|
||
/** This method should be implemented by the concrete benchmark. | ||
* It will be called by the benchmarking code for a number of times. | ||
* | ||
* @see setUp | ||
* @see tearDown | ||
*/ | ||
def run(): Unit | ||
|
||
/** Run the benchmark the specified number of milliseconds and return | ||
* the average execution time in microseconds. | ||
*/ | ||
def runBenchmark(timeMinimum: Long, runsMinimum: Int): Double = { | ||
var runs = 0 | ||
val startTime = System.nanoTime() | ||
var stopTime = startTime + timeMinimum.toLong * 1000000L | ||
var currentTime = startTime | ||
|
||
do { | ||
run() | ||
runs += 1 | ||
currentTime = System.nanoTime() | ||
} while (currentTime < stopTime || runs < runsMinimum) | ||
|
||
val elapsed = currentTime - startTime | ||
(elapsed / 1000).toDouble / runs | ||
} | ||
|
||
/** Prepare any data needed by the benchmark, but whose execution time | ||
* should not be measured. This method is run before each call to the | ||
* benchmark payload, 'run'. | ||
*/ | ||
def setUp(): Unit = () | ||
|
||
/** Perform cleanup operations after each 'run'. For micro benchmarks, | ||
* think about using the result of 'run' in a way that prevents the JVM | ||
* to dead-code eliminate the whole 'run' method. For instance, print or | ||
* write the results to a file. The execution time of this method is not | ||
* measured. | ||
*/ | ||
def tearDown(): Unit = () | ||
|
||
/** A string that is written at the beginning of the output line | ||
* that contains the timings. By default, this is the class name. | ||
*/ | ||
def prefix: String = getClass().getName() | ||
|
||
def warmUp(): Unit = { | ||
runBenchmark(1000, 5) | ||
} | ||
|
||
def report(): String = { | ||
setUp() | ||
warmUp() | ||
val avg = runBenchmark(2000, 5) | ||
tearDown() | ||
|
||
s"$avg us" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,4 +36,4 @@ trait App extends org.scalajs.benchmark.BenchmarkApp { | |
} | ||
} | ||
|
||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
tracer/jvm/src/main/scala/org/scalajs/benchmark/dom/CanvasRenderingContext2D.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.scalajs.benchmark.dom | ||
|
||
class CanvasRenderingContext2D { | ||
var fillStyle: String = "" | ||
|
||
def fillRect(x: Double, y: Double, w: Double, h: Double): Unit = ??? | ||
} |
3 changes: 3 additions & 0 deletions
3
tracer/jvm/src/main/scala/org/scalajs/benchmark/tracer/App.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package org.scalajs.benchmark.tracer | ||
|
||
trait App |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.