Comparing programming languages XIII: Retaking this series with ReScript

I wrote a short entry about ReScript

https://marioarias.hashnode.dev/comparing-programming-languages-xiii-retaking-this-series-with-rescript

8 Likes

Thank you for sharing this benchmark.

Getting a slower runtime by porting to ReScript contradicts my experience, so I inspected your implementation.

Most of the runtime difference is caused by unnecessary indirection by Option.flatMap and Option.forEach in hot loops, the additional cost of Array.prototype.forEach, and the early return difference.

After switching Option.flatMap to inline pattern-matching and forEach() to a while loop with early return, I got performance on par with the TypeScript version.

One tip is that if you rewrite all the loops as recursive functions, the compiler will pre-optimize tail recursion and automatically change it into a while loop ahead of time. Then you can visually identify which parts of the entire loop are already optimized and which are not.

Of course, for-loop and control-flow improvements are one of the major milestones of ReScript.

3 Likes

Fantastic, I’ll have a look and update the post.

My theory wasn’t far off then, overhead due to Option operations.

Update 1:

Interesting; in Scala, map is faster than match/switch, partially due to JVM optimisations

1 Like

It is not ideal that using operators included in the stdlib would result in a ~20% performance overhead. These are mostly native features of JavaScript, but we can selectively avoid them.

Once we stabilize the stdlib API surface in v12, we could introduce some compile-time optimizations. Moreover, it would be worth investigating optimizations that automatically transform dot-free calls to procedural syntax, like MoonBit.

3 Likes

Merged.

Sorry if my code wasn’t easy to work with.

Thanks. I’ll update the blog soon.

2 Likes

Not at all. Actually it was pretty nice for exploring

And a ReScript codebase that can be directly compared to TS is an essential resource for compiler improvement. Thanks again for trying ReScript!

4 Likes

i was about to respond initially but i felt i was being to criticizing so i never did. i appreciate almost any exposure rescript gets, and so i appreciate your article as well. there are a few things to note though:

  1. comparing computational performance of nodejs apps is rather futile. if you want high computational performance, you off-load to something other than nodejs

  2. you can do actual stop conditions in loops without mutations/refs by doing recursive ā€œauxilliaryā€ inner functions, which is the way to do it in the ocaml world. this is hard to read for most js:ers though. actually scratch that, it’s hard to read no matter where you’re coming from. this is what rust gets right: a balance of imperative and functional idioms. in essence, i agree that (and have voiced it on this forum a handful of times) early returns being absent is a major issue for rescript. i’m sure we’ll get it at some point.

  3. i accept the naming conventions - i don’t even have a problem with them. the only reason you do is likely that you’re used to seeing something else. i actually like them more than others now that i’m used to rescript. what i don’t like is that module names are *partially case-sensitively" extracted from filenames: ā€œmyfile.resā€ → Myfile, ā€œMyfile.resā€ → Myfile, ā€œMyFile.resā€ → MyFile, ā€œmyFile.resā€ → MyFile. it’s an ugly, ugly wart of the language, but i guess necessary. i dislike using the casing of filenames to name modules. rescript even mentions this in its docs:

Justification: The file system is a tree, but your code’s dependencies are a graph.

(from Project Structure | ReScript Language Manual)

but still wants to tie the two together by pulling names from one into the other. i would rather have modulenames determine by some single-line ā€œmodule ModuleNameā€ as the first line in the file. i would actually like to go one step further and be able to declare multiple top-level modules in one file. this is ergonomic and makes sense in certain situations.

  1. also, comparing generated js of 12-alpha.12 and e.g. 11, there’s a huge difference where 12-alpha.12 drops unnecessary calls to stdlib functions and instead uses native js functionality. this contributes to performance (and i assume that there are tests in place to ensure determinism; i love doing if myarray != [] in rescript, for example).

it’s an absolutely fantastic language and no other js-world language stands a chance imnsho. but features are missing, and some things need to be tidied up. (once you see how broken ts is, there’s no unseeing it - but yeah, ts still has its place)

oh and 5. the autoformatter is a headache at times, it moves my comments out of blocks and does all sorts of random maneuvers that drives me crazy at times, but i’m thinking it’s because it’s still young!

anyway, thanks for the write-up!

1 Like