Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Experiment: AvoidJSArrayConstr for Varargs to optimize the Wasm backend#5148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed

Conversation

tanishiking
Copy link
Contributor

@tanishikingtanishiking commentedMar 26, 2025
edited
Loading

This is more like an experiment report for discuss based on the results of this change.


Currently in Scala.js, varargs call likeList(1, 2, 3), it is translated into the IR formjs.WrappedArray(JSArrayConstr(...)). That requires JS interop for constructing the array and accessing its elements. Since Wasm-to-JS calls are expensive, this is undesirable for performance.

This commit experiments avoidingJSArrayConstr for varargs. Instead, varargs are transformed into something likenew WrappedArray$ofInt(ArrayValue(1, 2, 3)) (ornew ArraySeq$ofInt(...) on 2.13) to explore potential Wasm-specific optimizations.

Note1: While reducing JS interop can improve performance on the Wasm backend, the same does not apply the JS backend. We'd need to re-optimize back toJSArrayConstr-based code during the Optimizer for the JS backend.

Note 2: How aboutWrappedArray.make instead of directly instantiating specializedWrappedArray? I found that runtime type checks inmake appear to be very slow, and in some micro-benchmarks, usingmake performed slightly worse than the originalJSArrayConstr-based code.


Unfortunately, the performance improvements were negligible.

For example, in the following code:

defmain(args:Array[String]):Unit= {valstartTime=System.nanoTime()valxs=Seq(1,2, ...,20)  xs.foreach(x=> assert(x>0))valendTime=System.nanoTime()  println(s"elapsed:${endTime- startTime} ns")}

Both versions (with and withoutJSArrayConstr) reported similar timings of ~540000–580000 ns.

Benchmarks run usingsjrd/scalajs-benchmarks/wasm also did not show any significant performance differences.

BenchmarkbeforeafterRatio (after / before)
sha51212403.9581612737.424971.0269
sha512int12259.0236313313.696551.0860
queens2.9547780672.9203962370.9873
list60.5631687860.521638290.9993
richards87.4971444887.778077251.0032
cd32866.3546131672.24860.9637
gcbench104672.8678121351.25531.1588
tracerFloat870.5680015876.49621621.0068
tracer784.3968099783.22973650.9985
sudoku3634.1650463609.8138570.9933
nbody23722.0308424192.392111.0198
permute262.9023071265.9492281.0116
deltaBlue525.4683864511.87227240.9742
kmeans206339.5187202615.00220.9820
brainfuck2352.5188832357.0649591.0019
json288.1723513280.10018470.9720
bounce33.1244367433.018212620.9978

(It might be because there's not so much varargs in the benchmark)

There may still be room for further optimization in the non-JSArrayConstr implementation.

… BackendCurrently in Scala.js, varargs call like `List(1, 2, 3)`, it is translated into the IR form `js.WrappedArray(JSArrayConstr(...))`. That requires JS interop for constructing the array and accessing its elements.Since Wasm-to-JS calls are expensive, this is undesirable for performance.This commit experiments avoiding `JSArrayConstr` for varargs.Instead, varargs are transformed into something like `new WrappedArray$ofInt(ArrayValue(1, 2, 3))` (or `new ArraySeq$ofInt(...)` on 2.13) to explore potential Wasm-specific optimizations.Note1: While reducing JS interop can improve performance on the Wasm backend, the same does not apply the JS backend.We'd need to re-optimize back to `JSArrayConstr`-based code during the Optimizer for the JS backend.Note 2: How about `WrappedArray.make` instead of directly instantiating specialized `WrappedArray`?I found that runtime type checks in `make` appear to be very slow, and in some micro-benchmarks, using `make` performed slightly worse than the original `JSArrayConstr`-based code.---Unfortunately, the performance improvements were negligible.For example, in the following code:```scaladef main(args: Array[String]): Unit = {  val startTime = System.nanoTime()  val xs = Seq(1, 2, ..., 20)  xs.foreach(x => assert(x > 0))  val endTime = System.nanoTime()  println(s"elapsed: ${endTime - startTime} ns")}```Both versions (with and without `JSArrayConstr`) reported similar timings of ~540000–580000 ns.Benchmarks run using [`sjrd/scalajs-benchmarks/wasm`](https://github.com/sjrd/scalajs-benchmarks/tree/wasm) also did not show any significant performance differences.| Benchmark   | before       | after      | Ratio (after / before) ||-------------|--------------|--------------|----------------------|| sha512      | 12403.95816  | 12737.42497  | 1.0269               || sha512int   | 12259.02363  | 13313.69655  | 1.0860               || queens      | 2.954778067  | 2.920396237  | 0.9873               || list        | 60.56316878  | 60.52163829  | 0.9993               || richards    | 87.49714448  | 87.77807725  | 1.0032               || cd          | 32866.35461  | 31672.2486   | 0.9637               || gcbench     | 104672.8678  | 121351.2553  | 1.1588               || tracerFloat | 870.5680015  | 876.4962162  | 1.0068               || tracer      | 784.3968099  | 783.2297365  | 0.9985               || sudoku      | 3634.165046  | 3609.813857  | 0.9933               || nbody       | 23722.03084  | 24192.39211  | 1.0198               || permute     | 262.9023071  | 265.949228   | 1.0116               || deltaBlue   | 525.4683864  | 511.8722724  | 0.9742               || kmeans      | 206339.5187  | 202615.0022  | 0.9820               || brainfuck   | 2352.518883  | 2357.064959  | 1.0019               || json        | 288.1723513  | 280.1001847  | 0.9720               || bounce      | 33.12443674  | 33.01821262  | 0.9978               |There may still be room for further optimization in the non-`JSArrayConstr` implementation.
@tanishikingtanishiking changed the title[DO NOT MERGE] Experiment: AvoidingJSArrayConstr for Varargs to optimize the Wasm backendExperiment: AvoidingJSArrayConstr for Varargs to optimize the Wasm backendMar 26, 2025
@tanishikingtanishiking changed the titleExperiment: AvoidingJSArrayConstr for Varargs to optimize the Wasm backendExperiment: AvoidJSArrayConstr for Varargs to optimize the Wasm backendMar 26, 2025
@tanishikingtanishiking deleted the array-varargs branchApril 9, 2025 00:09
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers
No reviews
Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

1 participant
@tanishiking

[8]ページ先頭

©2009-2025 Movatter.jp