Interesting article and fun questions about it regarding the code size and execution times.
I did go ahead and build it locally to see what is going on.
Differences in size
Regarding @DZakh mentioning the minified size, all the *.bs.js
files together minified was 13.7kb, and the JS implementation was 6.9kb. So still longer. (Btw, I didn’t do anything fancy, just catted the files if necessary and pasted them here: https://skalman.github.io/UglifyJS-online/.)
As to why it is more bytes…take a look at some of the generated code:
var bit = function (v) {
var a = regA.contents;
setFlag(zero, Caml_obj.caml_equal(Int8.band(a, v), Int8.int8_of_int(0)));
setFlag(negative, Caml_obj.caml_notequal(Int8.band(v, Int8.int8_of_int(128)), Int8.int8_of_int(0)));
return setFlag(overflow, Caml_obj.caml_notequal(Int8.band(v, Int8.int8_of_int(64)), Int8.int8_of_int(0)));
};
Not terse! Lots of casting code that isn’t present in the JS implementation. Also you see Caml_obj.caml_equal
and Caml_obj.caml_notequal
, which is a lot more characters than the couple of characters for the operator in the JS implementation. You’ve got function calls for bitwise operations versus the inline bitwise ops for the JS implementation. You’ve got a lot of currying increasing the size as well. About 100 or so lines looking like this:
eor(Curry._1(funarg.readMem, Curry._1(zp, undefined)));
You could imagine writing some of the things mentioned above a bit differently and saving a lot of size.
Differences in exec time
I didn’t bother profiling things so obviously just speculation, but…a lot of the things above leading to code size increase will also not favor well against direct JS. E.g., the currying, the casting functions, writing bitwise operations as functions rather than just doing them inline like in the JS version. If you wrote the rescript differently, you could avoid some of this and possibly make a difference in runtime.
Also, I didn’t see the rescript compiler inlining too many function calls in the code output. Not sure why that is as I would need to look at it longer, but it’s interesting. The main module MOS6502
is basically a big functor and all the main types (Int16
, and Int8
) are abstract, so that may be part of it.
Anyway, really cool blog post and pretty neat that the original author implemented the same thing in a few different compile-to-JS languages.
It would be fun to take the JS implementation and convert it to ReScript using this method and see how much you could improve the ReScript generated code. I imagine someone could make a sizable (pun intended) difference if that was the aim.