[erlang-questions] binary optimization

Mikael Pettersson <>
Sat Jul 18 13:41:22 CEST 2009


Richard Carlsson writes:
 > Joel Reymont wrote:
 > > This doesn't fly either...
 > > 
 > > src/flashbot.erl:117: Warning: NOT OPTIMIZED: sub binary is used or
 > > returned
 > > 
 > > handle_info({tcp, _Sock, <<A:32, B:32, C:32, Bin/binary>>}, Where,
 > > State) ->
 > >     Delta = timer:now_diff(now(), {A, B, C}),
 > >     Where(Bin, State#state{latency = Delta});
 > 
 > You missed the important point in Mikael's mail:
 > "presumably the callee in the tailcall must be known at compile-time,
 > and must presumably only be called with a delayed sub binary."
 > 
 > In the above, Bin gets passed to Where, which could be anything
 > as far as the compiler knows. Either you ignore the warning, if you
 > think that restructuring the code is not worth it here, or you
 > try to rewrite the whole thing so you get a single main loop with
 > direct self-recursive tail calls (if that is at all doable).

Well, lowering this higher-order code to first-order code is
always possible (cite Reynolds 1972 or thereabouts), but those
transformations tend to destroy the structure of the code.

In this code, either enumerate the possible values for Where and
invoke them via an explicit case expression, or specialise handle_info/3
into a set of handle_info_.../2 functions, one for each possible Where.

Or just live with the fact that this call cancels delayed sub binary
optimisation.

 > > src/flashbot.erl:81: Warning: NOT OPTIMIZED: sub binary used by
 > > erlang:setelement/3
 > > 
 > > no_token(<<?TOKEN, _:32, Token/binary>>, State) ->
 > >     send([?SUBSCRIBE, size(?TOPIC), ?TOPIC],
 > >          State#state{token = Token},
 > >          not_subscribed).
 > 
 > Well, it is. Token gets inserted into State.

To elaborate, storing Token in an aggregate and passing that elsewhere
forces the implementation to convert Token from the delayed sub binary
representation to a proper Erlang term, which requires memory allocation
and initialisation. A possible solution is to change send/3 to send/4
with Token as an additional parameter, and then hope that send/4 is nice
enough so that the compiler can keep Token in its delayed sub binary
representation.


More information about the erlang-questions mailing list