Skip to content

Instantly share code, notes, and snippets.

@tanishiking
Last active July 11, 2024 02:58
Show Gist options
  • Save tanishiking/4a55c9661558397a60ed82442b67dacb to your computer and use it in GitHub Desktop.
Save tanishiking/4a55c9661558397a60ed82442b67dacb to your computer and use it in GitHub Desktop.
scalajs benchmark with wasm

Benchmarked against https://github.com/tanishiking/scala-js/tree/opt%2Btyped-closures that contains the following changes.

The benchmark is

with the following changes

diff --git a/build.sbt b/build.sbt
index 2e3f9aa..6f5d281 100644
--- a/build.sbt
+++ b/build.sbt
@@ -22,6 +22,18 @@ ThisBuild / scalaJSLinkerConfig ~= { prev =>
     .withSemantics(_.optimized)
     .withModuleKind(ModuleKind.ESModule)
     .withOutputPatterns(OutputPatterns.fromJSFile("%s.mjs"))
+    .withExperimentalUseWebAssembly(false)
+    .withOptimizer(true)
+    .withSemantics { sems =>
+      sems
+       .withAsInstanceOfs(Unchecked)
+       .withArrayIndexOutOfBounds(Unchecked)
+       .withArrayStores(Unchecked)
+       .withNegativeArraySizes(Unchecked)
+       .withNullPointers(Unchecked)
+       .withStringIndexOutOfBounds(Unchecked)
+       .withModuleInit(Unchecked)
+    }
 }
 
 ThisBuild / jsEnv := {
@@ -35,7 +47,7 @@ val defaultSettings: Seq[Setting[_]] = projectSettings ++ Seq(
       "-unchecked",
       "-feature",
       "-encoding", "utf8"
-  )
+  ),
 )
 
 def envInfo(compiler: String, esVersion: String,
diff --git a/common/js/src/main/scala/org/scalajs/benchmark/Benchmark.scala b/common/js/src/main/scala/org/scalajs/benchmark/Benchmark.scala
index 20c34ca..cd20cd6 100644
--- a/common/js/src/main/scala/org/scalajs/benchmark/Benchmark.scala
+++ b/common/js/src/main/scala/org/scalajs/benchmark/Benchmark.scala
@@ -123,11 +123,14 @@ abstract class Benchmark {
   /** Run the benchmark the specified number of milliseconds and return
    *  the mean execution time and SEM in microseconds.
    */
-  def runBenchmark(timeMinimum: Long, runsMinimum: Int): (Double, Double) = {
-    if (scala.scalajs.runtime.linkingInfo.isWebAssembly)
-      runBenchmarkWasm(timeMinimum, runsMinimum)
-    else
-      runBenchmarkJS(timeMinimum, runsMinimum)
+  def runBenchmark(timeMinimum: Long, runsMinimum: Int): (Double, Double, String) = {
+    if (scala.scalajs.runtime.linkingInfo.isWebAssembly) {
+      val res = runBenchmarkWasm(timeMinimum, runsMinimum)
+      (res._1, res._2, "wasm")
+    } else {
+      val res = runBenchmarkJS(timeMinimum, runsMinimum)
+      (res._1, res._2, "js")
+    }
   }
 
   /** Run the benchmark the specified number of milliseconds and return
@@ -215,10 +218,10 @@ abstract class Benchmark {
 
     setUp()
     warmUp()
-    val (mean, sem) = runBenchmark(3000, 20)
+    val (mean, sem, env) = runBenchmark(3000, 20)
     tearDown()
 
     val envInfo = g.ScalaJSBenchEnvInfo.asInstanceOf[String]
-    s"$prefix;$envInfo;${Benchmark.userAgent};$mean;$sem"
+    s"$env$prefix;$envInfo;${Benchmark.userAgent};$mean;$sem"
   }
 }

benchmark

wasm js wasm / js js / wasm (x faster)
sha512 12389.60957 69356.554 0.1786364641 5.597961227
sha512int 12078.45649 18342.09272 0.6585102731 1.518579194
queens 3.544551536 9.262363477 0.3826832692 2.613127044
list 75.7047963 142.8739845 0.5298711069 1.887251422
richards 92.16190248 130.1592505 0.7080703225 1.412289102
cd 51769.70971 62085.45494 0.8338460233 1.19926218
gcbench 115556.3845 135005.6104 0.8559376468 1.168309402
tracerFloat 2542.721593 1280.901067 1.985103813 0.5037519919
tracer 1679.48498 1032.582152 1.626490423 0.6148207122
sudoku 8334.011331 2366.552282 3.521583443 0.2839631706
nbody 23308.29491 31724.07897 0.7347193572 1.361063909
permute 615.0088721 217.1844323 2.831735524 0.3531403238
deltaBlue 1089.914288 358.4833364 3.040348537 0.3289096588
kmeans 536533.0292 154106.1958 3.481579871 0.2872259253
brainfuck 3309.31457 3759.650596 0.8802186493 1.13608136
json 1311.736054 347.0163458 3.780041113 0.2645473872
bounce 21.58278436 23.84516687 0.9051219676 1.104823478

code size (fullLinkJS)

The code size of test-suite2_13 / Test / fullLinkJS

  • closure compiler: 4.1M
  • without GCC: 14.5M
  • wasm: 6.4M

  • typed-closure achived much better performance 🎉
  • we might be able to further optimization with js-string-builtins?
  • code sizes hadn't changed from previous report

https://x.com/bashorov/status/1798413839232581987

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment