I needed a noise generator for a simple game I'm m...
# javascript
i
I needed a noise generator for a simple game I'm making and thought it would be interesting to port one to MPP and see how JS compares to the JVM when significant amounts of math ops are required. Apparently the answer is really poorly. https://github.com/ToxicBakery/Accidental-Noise-Generator If you're interested in watching your browser cry,
./gradlew :terrain-preview-web:run
. Has anyone tried anything similar for say some simple 3d backed by Kotlin JS? Wondering if you saw similar performance concerns doing quat maths or similar at higher frame rates.
a
Hi, I am preparing the release 3d geometry constructor for particle physics event display fully written in kotlin-multiplatform: https://github.com/mipt-npm/dataforge-vis (no documentation so far). Currently I use transformations from three-js library for js back-end, but it is possible to create a stand-alone version and there was a discussion about it. Could you file an issue here: https://github.com/mipt-npm/kmath/issues?
🆒 1
i
I'm not using either of those libs though. Seems more of an issue to post to keep.
a
KEEP is for language proposals. Quaternions won't be handled on the language level. Kmath has some basic abstractions to work with algebra and it is quite easy to add quaternions there.
So either there is a stand-alone library for it, or we can add functionality to one of existing ones. I prefer the second approach since it allows to conserve community efforts.
i
Oh sorry, I didn't specify why the performance was bad in my post. Quick look over it appears that long math eats most of the time so the keep proposal would be for improvement around that conversion but I haven't spent time looking at exactly what pieces are performing poorly. At least that seems like the correct approach to me. My question about quats was purely because it seemed likely that someone tried that vs a noise library which seems less likely but both would be sufficiently math heavy.
My lib is not using quats to be clear
a
The problem with JS is that memory allocations (and thus object creation) are quite expensive compared to JVM. Also, JVM has a quite smart inlining and escape analysis so some objects declared in code are never allocated on the heap. It is just not possible in JS. So in order to get reasonable performance, you need to have pooling of some kind. You can't fix it in the language.
i
I'm on vacation but I was hoping to find some time in the next two weeks to do some stacktrace comparisons of the jvm to the js compiled code so I can more accurately highlight what explains for the massive performance difference. The jvm compiled code is literally over 10000 times faster give or take.
Even when it's all primitives? I don't really have much allocation happening of objects
a
I am quite sure that the problem is with object allocation and subsequent GC. My tests show reasonable performance of JS when using pooled objects.
i
Interesting. How do you pool primitives like Long?
At the high level, I do have object instantiation but it seems all the time is being spent in loops that are just primitive and array manipulation
a
The primitives also could pose a proble since GC is also not quite fast on JS, but we need to be sure, you use primitives. For primitives in most cases you do not use pooling, but reuse hidden class-level variables. On JVM this practice is discouraged because you create middle level mutable state and JVM optimizes it anyway. But on JS you can save a lot on that. If I will have time, I will lool through your code later.
i
I see what you're saying. That's good info, thank you. If I have some time I'll see if I can pull some variable allocations out of the loops to see if that changes the performance behaviors on JS
a
I am not sure, where is the bottleneck right now, but the first thing to check is this allocation: https://github.com/ToxicBakery/Accidental-Noise-Generator/blob/b9a4319d830819326dff3131ca504dc05ec80712/terrain-preview-web/src/main/kotlin/main.kt#L64. the array could be reused.
i
when I was glancing through the chrome profile, time spent was in the nested looping such as in the fractal module which is inherently extremely heavy.
a
Oh, I missed the dependency
i
I believe it was loops like this one that lots of time would get spent, again I can't run it right now since im mobile unfortunately so just going from memory https://github.com/ToxicBakery/Accidental-Noise-Generator/blob/master/generator/src/commonMain/kotlin/com/sudoplay/joise/module/ModuleFractal.kt#L338
while that loop seems like not much, the sources create a nest of sub loops to go through
a
This one seems to be fine. No object allocations. If it is indeed so slow, than it makes sense to create an issue on youtrack. But before it should be isolated in a separate reproducable example. Also one needs to check memory comsumption. You should remember that JS is just not meant for heavy computations. Still, modern V8 engine is not up to JVM standards, but it should not be that much slower.
Iv'e cloned the project. Seems like there still a lot of time inside GC, so allocation is an issue, I will poke it a bit more
The problem is in this function: https://github.com/ToxicBakery/Accidental-Noise-Generator/blob/b9a4319d830819326dff3131ca504dc05ec80712/generator/src/commonMain/kotlin/com/sudoplay/joise/noise/Noise.kt#L1263. I am not sure what this function does, but it seems that at least parts of it could be cached. The second botleneck is transformation from int to long, which is specific to JS. I think that performance could be improved by avoiding operations on longs.