Will/does adding type-based guards make code faster with the JIT?

I recall reading that there are more type-based enhancements are coming with the ongoing work on the JIT.

Will adding guards to functions so that Erlang knows what types things will be make any impact on performance?


Yes, adding guards may improve performance. For more details, see the blog post Type-Based Optimizations in the JIT.


Has anyone ever looked into writing a parse transform that enforces specs as guards on simple functions? That could be really helpful in this case, I don’t want to litter my code with two sets of type definitions if not necessary. A compound type check would be nice for this, by the wy, something like is_tuple_with_types.


@bjorng will have to correct me if I’m wrong, but I think in a majority of cases, adding guards will not lead to any performance benefits. There are cases where they do help, but if you automatically add guards to all your functions I think you will see a performance loss rather than gain.


Yes, that is correct.

I should have expressed myself more clearly. Adding guards may improve performance but it may also reduce performance. It all depends on how expensive the guards are and how much useful type information they provide to the compiler and how much optimisation the compiler and/or JIT can do with the help of it. The most likely outcome of adding guards is that there will be no noticeable impact on performance.

The way you phrase it, I get the impression that you writes specs for both local and exported functions. It is generally not necessary. If you write specs for only the exported functions, Dialyzer will in most cases be able to infer the types for the local functions. Similarly, the compiler will infer types for local functions based on the patterns and guards for the exported functions.


I did some test mathy benchmarks with 25.0-rc2 a couple days ago for fun. Basically, it’s a ton faster than python, it’s “almost” as fast as pypy (about 50% slower give or take), it’s not at all bad. :slight_smile:


Is there a way to add type information for the JIT without the runtime overhead? Languages such as Gleam, PureScript, and Hamler have near perfect type information and could provide a lot of hints.


No, the Erlang compiler and the JIT will not accept hints and will not generate unsafe code.

You will have to use your type information in Gleam, PureScript, or Hamlet to generate actual guard tests in strategic places in the code. For example, by placing type tests in all exported functions, the compiler will in principle propagate the type information to all local functions within the module. You could also place guard tests that establishes ranges before sequences of arithmetic instructions (because those operations are the ones that gain most from having good type information).


Brilliant, thank you.

Is there any documentation on how to effectively use guards with the JIT? Something similar to the Erlang efficiency guide perhaps?


No, and we don’t have any plans to document it for OTP 25 because we expect most of the advice would be out of date for OTP 26 (especially that one must use band instead of relational operators to establish ranges).