Some additional information on the state of WASM as of now.
I work on a project which would really benefit from multiplatform and WASM in particular if it would work well. Right now there is a small and a big problem with the WASM implementation.
The small problem is that it is basically non-documented. Small, because it is actually not that much effort to build a WASM module from a multiplatform project. The blogs mentioned in this discussion helps a lot.
The big problem is the performance. Right now the very same project compiled into JavaScript is faster than the WASM compilation.
I haven’t done anything really special, check this code out:
val t = IntArray(1000000)
var i = 0
while (i < t.size) {
t[i] = i
i ++
}
JavaScript execution time for this is:
- 6 ms in Safari
- 5 ms in Firefox
WASM execution time is:
- 106 ms in Safari
- 11 ms in Firefox
This in itself puts a big question mark on WebAssembly for me.
I’ve ran some better tests also. In these measurements build basically just puts stuff into an IntArray, render goes over that array and calculates stuff.
Find the run times below, the bigger test runs 10 times to let VMs warm up.
Let’s say that the difference between the JVM and JavaScript is acceptable. But WASM simply does not worth the effort, it is slower than JavaScript.
I don’t know if this difference is because of the Kotlin to WASM compiler or WASM itself. But this do not change my conclusion: Kotlin/Native WASM is not ready for production. The way to go is Kotlin/Js or simply native JavaScript to avoid the Kotlin overhead.
I would be glad to head other opinions / experiences on this. Also, if you find any errors in my reasoning, please let me know. I really like the multiplatform concept and I understand that it is difficult to build a good toolchain for each platform. On the other hand, I have to make viable products, so I can’t go into directions which really undermine the performance of the code I write.
WASM (Safari)
[Log] ==== Measuring Performances ==== (common.wasm.js, line 290)
[Log] put 1000000 entries into an IntArray: 106ms (common.wasm.js, line 290)
[Log] put 1000000 entries into a FloatArray: 41.0ms (common.wasm.js, line 290)
[Log] round 1: build: 1.40s create engine: 14.0ms render: 3.45s (common.wasm.js, line 290)
[Log] round 2: build: 1.35s create engine: 168ms render: 3.01s (common.wasm.js, line 290)
[Log] round 3: build: 1.33s create engine: 153ms render: 3.14s (common.wasm.js, line 290)
[Log] round 4: build: 1.34s create engine: 166ms render: 3.00s (common.wasm.js, line 290)
[Log] round 5: build: 1.32s create engine: 155ms render: 3.05s (common.wasm.js, line 290)
[Log] round 6: build: 1.32s create engine: 157ms render: 2.98s (common.wasm.js, line 290)
[Log] round 7: build: 1.29s create engine: 158ms render: 3.08s (common.wasm.js, line 290)
[Log] round 8: build: 1.36s create engine: 157ms render: 3.58s (common.wasm.js, line 290)
[Log] round 9: build: 1.70s create engine: 181ms render: 3.91s (common.wasm.js, line 290)
[Log] round 10: build: 1.75s create engine: 164ms render: 3.24s (common.wasm.js, line 290)
[Log] ==== Done ==== (common.wasm.js, line 290)
JavaScript (Safari)
[Log] ==== Measuring Performances ==== (1.chunk.js, line 58074)
[Log] put 1000000 entries into an IntArray: 6.00ms (1.chunk.js, line 58074)
[Log] put 1000000 entries into a FloatArray: 14.0ms (1.chunk.js, line 58074)
[Log] round 1: build: 1.75s create engine: 12.0ms render: 1.46s (1.chunk.js, line 58074)
[Log] round 2: build: 1.32s create engine: 6.00ms render: 1.20s (1.chunk.js, line 58074)
[Log] round 3: build: 1.15s create engine: 5.00ms render: 1.09s (1.chunk.js, line 58074)
[Log] round 4: build: 1.25s create engine: 5.00ms render: 1.14s (1.chunk.js, line 58074)
[Log] round 5: build: 1.16s create engine: 5.00ms render: 1.12s (1.chunk.js, line 58074)
[Log] round 6: build: 1.15s create engine: 5.00ms render: 1.11s (1.chunk.js, line 58074)
[Log] round 7: build: 1.17s create engine: 5.00ms render: 1.13s (1.chunk.js, line 58074)
[Log] round 8: build: 1.15s create engine: 5.00ms render: 1.12s (1.chunk.js, line 58074)
[Log] round 9: build: 1.17s create engine: 5.00ms render: 1.09s (1.chunk.js, line 58074)
[Log] round 10: build: 1.17s create engine: 5.00ms render: 1.11s (1.chunk.js, line 58074)
[Log] ==== Done ==== (1.chunk.js, line 58074)
Kotlin (JVM 8)
==== Measuring Performances ====
put 1000000 entries into an IntArray: 6.78ms
put 1000000 entries into a FloatArray: 7.13ms
round 1: build: 475ms create engine: 11.8ms render: 129ms
round 2: build: 223ms create engine: 1.59ms render: 82.2ms
round 3: build: 155ms create engine: 2.66ms render: 168ms
round 4: build: 287ms create engine: 1.97ms render: 102ms
round 5: build: 168ms create engine: 2.84ms render: 71.7ms
round 6: build: 190ms create engine: 1.45ms render: 25.1ms
round 7: build: 127ms create engine: 1.37ms render: 106ms
round 8: build: 115ms create engine: 626us render: 37.6ms
round 9: build: 140ms create engine: 480us render: 34.3ms
round 10: build: 167ms create engine: 441us render: 207ms
==== Done ====