Boxed types in OCaml, and other thoughts
blog.ajour.io
blog.ajour.io
Implementations like SBCL have a similar overhead for a function call containing arithmetic. However, if you're doing more arithmetic within the function, the bit shifts etc. are only done once as a part of the function's pre/postamble. In fact, fully unboxed 64-bit arithmetic with integers or floats can be done if these values aren't crossing function boundaries or into the garbage-collected heap. (The latter, a memory read/write, is way more costly than a bit shift anyway.)
The term of art is "inlining" or "open-coding" arithmetic. Raw arithmetic can be open-coded, but data formats must be respected across function call boundaries and in the heap. Therefore, if you inline the function containing the arithmetic, you eliminate the pre/postamble overhead too. This is the same as in C-like languages as well, it's just that their pre/postambles are different.
"Block" or "whole-program compilation" can also sometimes eliminate these extra instructions, at some modest expenses (compile wall clock time, implementation complexity, increased size of compilation units, multiple function entry points, modularity, etc.).
OCaml's built-in Flambda [1,2] is a project/technology that will automatically leverage some of the above techniques (especially inlining) to achieve higher performance.
To squeeze out performance, you have to detect when polymorphic functions are actually used on int and decide if you want to compile and store a special cased version which avoid the unboxing-boxing shuffle. There is a balance to find between compile time, program size and speed of running code which is fairly hard to get right.
Jane Street's blog explains the reasoning in detail[0]
[0] https://blog.janestreet.com/what-is-gained-and-lost-with-63-...
"x * y is translated to CPU instructions (x >> 1) * (y - 1) + 1" namely that it now at least 3 extra highlevel operations to do simple multiplication.
I spent 3 years at Morgan Stanley writing A+ and loved it. A+ is dead but kdb lives on, and is widely used at top hedge funds.
As to the point of studying boxing, well, it’s fairly basic compiler theory. It will be hard to avoid if you have even the slightest interest in PL.
You'd be better off measuring actual performance on real world tasks before inferring anything. Modern CPUs overlap execution of instructions very aggressively.
As a side note it took me a second to realize that the multiplication being done is not actually xx, but rather (x (x<<1))
In OCaml, the type system is strong and statically typed, ergo the type of a value is known at compile-time.
So...why would it need to do this to check if the type is an integer?
It’s about compiled code by the way, a lot lower down the stack. That’s the joy of working on a compiler. You deal with both very high level concepts and very low level issues.