+bin_opt_info option doesn't print anything

I’ve created a mix project with a single file which looks like this

defmodule Bins do
  def my_binary_to_list(<<h, t::bytes>>), do: [h | my_binary_to_list(t)]
  def my_binary_to_list(<<>>), do: []

  def after_zero(<<0, t::bytes>>), do: t
  def after_zero(<<_, t::bytes>>), do: after_zero(t)
  def after_zero(<<>>), do: <<>>

  def all_but_zeros_to_list(buffer, acc, 0), do: {:lists.reverse(acc), buffer}
  def all_but_zeros_to_list(<<0, t::bytes>>, acc, remaining), do: all_but_zeros_to_list(t, acc, remaining - 1)
  def all_but_zeros_to_list(<<byte, t::bytes>>, acc, remaining), do: all_but_zeros_to_list(t, [byte | acc], remaining - 1)

  def not_opt_eq([h | t1], <<h, t2::bytes>>), do: not_opt_eq(t1, t2)
  def not_opt_eq([_ | _], <<_, _::bytes>>), do: false
  def not_opt_eq([], <<>>), do: true

  def opt_eq(<<h, t1::bytes>>, [h | t2]), do: opt_eq(t1, t2)
  def opt_eq(<<_, _::bytes>>, [_ | _]), do: false
  def opt_eq(<<>>, []), do: true

  def match_body([0 | _], <<_h, _::bytes>>), do: :done

  def match_head(list, <<_::10, data::bytes>>), do: match_body(list, data)

  def count1(<<_, t::bytes>>, count), do: count1(t, count + 1)
  def count1(<<>>, count), do: count

  def count2(<<h, t::binary>>, count), do: count2(t, count + 1)
  def count2(<<>>, count), do: count

  def count3(<<_h, t::binary>>, count), do: count3(t, count + 1)
  def count3(<<>>, count), do: count
end

but when I run

ERL_COMPILER_OPTIONS=bin_opt_info mix compile

no warnings about about binary optimizations are printed. What am I doing wrong?

The code is from http://erlang.org/doc/efficiency_guide/binaryhandling.html

What about?

ERL_COMPILER_OPTIONS='+bin_opt_info' mix compile

If you are using an SH-style shell that is.

env ERL_COMPILER_OPTIONS="+bin_opt_info" mix compile                                               
Ignoring bad term in ERL_COMPILER_OPTIONS

and env ERL_COMPILER_OPTIONS=bin_opt_info mix compile doesn’t cause this error. I’m using fish shell.

mix compile --erl "+bin_opt_info" also doesn’t output anything, just compiles the file.

I’m on Erlang/OTP 20 and Elixir 1.4.5.

The messages are only printed when a module is being compiled. If it’s already compiled, it won’t print anything. An option is to either touch the module before compiling or use mix compile --force.

3 Likes
> mix compile --erl "+bin_opt_info" --force
Compiling 1 file (.ex)
Generated example app
> touch lib/example.ex
> mix compile --erl "+bin_opt_info"
Compiling 1 file (.ex)

didn’t work … But this however worked

> env ERL_COMPILER_OPTIONS=bin_opt_info mix compile --force
Compiling 1 file (.ex)
warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:2

warning: NOT OPTIMIZED: sub binary is used or returned
  lib/example.ex:5

warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:6

warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:12

warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:15

warning: NOT OPTIMIZED: called function not_opt_eq/2 does not begin with a suitable binary matching instruction
  lib/example.ex:19

warning: INFO: matching anything else but a plain variable to the left of binary pattern will prevent delayed sub binary optimization; SUGGEST changing argument order
  lib/example.ex:19

warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:23

warning: INFO: matching anything else but a plain variable to the left of binary pattern will prevent delayed sub binary optimization; SUGGEST changing argument order
  lib/example.ex:27

warning: NOT OPTIMIZED: called function match_body/2 does not begin with a suitable binary matching instruction
  lib/example.ex:29

warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:31

warning: OPTIMIZED: creation of sub binary delayed
  lib/example.ex:37

Generated example app

Touching and calling env ERL_COMPILER_OPTIONS=bin_opt_info mix compile also works.

The command should be ERL_COMPILER_OPTIONS=bin_opt_info mix compile, the +bin_opt_info is an option to erlc, not erl, so the --erl flag won’t work.

1 Like

A bit off-topic, but in this simple benchmark

defmodule BinBench do
  use Benchfella

  @list for i <- 1..10_000, do: i
  @bin to_string(@list)

  bench "opt_eq" do
    Bins.opt_eq(@bin, @list)
  end

  bench "not_opt_eq" do
    Bins.not_opt_eq(@list, @bin)
  end
end

the optimized version is much faster than the not optimized one:

Settings:
  duration:      1.0 s

## BinBench
1/2: not_opt_eq
2/2: opt_eq

Finished in 6.83 seconds

## BinBench
benchmark n iterations   average time
opt_eq         1000000   1.93 µs/op
not_opt_eq      500000   7.62 µs/op
1 Like