Search code examples
performanceerlang

Which of the following two pieces of code is faster or the same, and why?


-record(test, {a = 10}).

test(Test) when is_record(Test,test) -> somethings.

or

test(#test{} = Test) -> somethings.

which is faster or the same? why.


Solution

  • It's not too hard to test with the compiler. To do that, I wrote this module…

    -module my_mod.
    -export [t1/1, t2/1].
    
    -record(test, {a = 10}).
    
    t1(Test) when is_record(Test,test) -> somethings.
    
    t2(#test{} = _Test) -> somethings.
    

    Then, I run erlc -E my_mod.erl and this is the resulting expanded code:

    -file("my_mod.erl", 1).
    
    -module(my_mod).
    
    -export([t1/1,t2/1]).
    
    -record(test,{a = 10}).
    
    t1({test, _} = Test) when true ->
        somethings.
    
    t2({test, _} = _Test) ->
        somethings.
    

    So, basically… it's the same. Using is_record(Test, test) adds a useless guard (true) but that shouldn't make a difference in terms of speed.

    Furthermore, if you use erlc -S my_mod.erl, to generate assembly listings, you get:

    {module, my_mod}.  %% version = 0
    
    {exports, [{module_info,0},{module_info,1},{t1,1},{t2,1}]}.
    
    {attributes, []}.
    
    {labels, 9}.
    
    
    {function, t1, 1, 2}.
      {label,1}.
        {line,[{location,"my_mod.erl",6}]}.
        {func_info,{atom,my_mod},{atom,t1},1}.
      {label,2}.
        {test,is_tagged_tuple,{f,1},[{x,0},2,{atom,test}]}.
        {move,{atom,somethings},{x,0}}.
        return.
    
    
    {function, t2, 1, 4}.
      {label,3}.
        {line,[{location,"my_mod.erl",8}]}.
        {func_info,{atom,my_mod},{atom,t2},1}.
      {label,4}.
        {test,is_tagged_tuple,{f,3},[{x,0},2,{atom,test}]}.
        {move,{atom,somethings},{x,0}}.
        return.
    
    
    {function, module_info, 0, 6}.
      {label,5}.
        {line,[]}.
        {func_info,{atom,my_mod},{atom,module_info},0}.
      {label,6}.
        {move,{atom,my_mod},{x,0}}.
        {line,[]}.
        {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
    
    
    {function, module_info, 1, 8}.
      {label,7}.
        {line,[]}.
        {func_info,{atom,my_mod},{atom,module_info},1}.
      {label,8}.
        {move,{x,0},{x,1}}.
        {move,{atom,my_mod},{x,0}}.
        {line,[]}.
        {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
    

    As you can see, the two functions are, in fact, identical:

    {function, …, 1, …}.
      {label,…}.
        {line,[{location,"my_mod.erl",…}]}.
        {func_info,{atom,my_mod},{atom,…},1}.
      {label,…}.
        {test,is_tagged_tuple,{f,…},[{x,0},2,{atom,test}]}.
        {move,{atom,somethings},{x,0}}.
        return.