<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">As Jacob suggested, I think the compiler has just optimised out the term_to_binary call. On my machine, your original benchmark gives:<div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">1> c(tconvert).</font></div><div class=""><font face="Courier New" class="">{ok,tconvert}</font></div><div class=""><font face="Courier New" class="">2> tconvert:run(a, 1000000).</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">term_to_binary/1 RETURN VALUE:<<131,100,0,1,97>></font></div><div class=""><font face="Courier New" class="">REQUEST COUNT:1000000</font></div><div class=""><font face="Courier New" class="">ELAPSED TIME (usec):4707</font></div><div class=""><font face="Courier New" class="">TIME PER REQUEST (usec): 0.004707</font></div><div class=""><font face="Courier New" class="">PROJECTED RATE (req/sec): 212449543.23348203</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">binary_to_term/1 RETURN VALUE:a</font></div><div class=""><font face="Courier New" class="">REQUEST COUNT:1000000</font></div><div class=""><font face="Courier New" class="">ELAPSED TIME (usec):142883</font></div><div class=""><font face="Courier New" class="">TIME PER REQUEST (usec): 0.142883</font></div><div class=""><font face="Courier New" class="">PROJECTED RATE (req/sec): 6998733.229285499</font></div><div class=""><br class=""></div><div class="">So that factor-of-30 difference, similar to what you reported. I change the two loops to use the value from term_to_binary / binary_to_term:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">do_term_to_bin( Term, _, 0 ) -> term_to_binary( Term );</font></div><div class=""><font face="Courier New" class="">do_term_to_bin( Term, _, N )</font></div><div class=""><font face="Courier New" class="">-></font></div><div class=""><font face="Courier New" class=""> X = term_to_binary( Term ),</font></div><div class=""><font face="Courier New" class=""> do_term_to_bin( Term, X, N-1 )</font></div><div class=""><font face="Courier New" class="">.</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">do_bin_to_term( <<Bin/binary>> , _, 0 ) -> binary_to_term( Bin );</font></div><div class=""><font face="Courier New" class="">do_bin_to_term( <<Bin/binary>> , _, N )</font></div><div class=""><font face="Courier New" class="">-></font></div><div class=""><font face="Courier New" class=""> X = binary_to_term( Bin ),</font></div><div class=""><font face="Courier New" class=""> do_bin_to_term( Bin , X, N-1 )</font></div><div class="">.</div></div><div class=""><br class=""></div><div class="">And that resulted in:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">3> c(tconvert). </font></div><div class=""><font face="Courier New" class="">{ok,tconvert}</font></div><div class=""><font face="Courier New" class="">4> tconvert:run(a, 1000000).</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">term_to_binary/1 RETURN VALUE:<<131,100,0,1,97>></font></div><div class=""><font face="Courier New" class="">REQUEST COUNT:1000000</font></div><div class=""><font face="Courier New" class="">ELAPSED TIME (usec):68587</font></div><div class=""><font face="Courier New" class="">TIME PER REQUEST (usec): 0.068587</font></div><div class=""><font face="Courier New" class="">PROJECTED RATE (req/sec): 14580022.45323458</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">binary_to_term/1 RETURN VALUE:a</font></div><div class=""><font face="Courier New" class="">REQUEST COUNT:1000000</font></div><div class=""><font face="Courier New" class="">ELAPSED TIME (usec):130298</font></div><div class=""><font face="Courier New" class="">TIME PER REQUEST (usec): 0.130298</font></div><div class=""><font face="Courier New" class="">PROJECTED RATE (req/sec): 7674714.884342046</font></div></div><div class=""><br class=""></div><div>So binary_to_term about twice as slow as term_to_binary, which is very much in line with what Jacob measured</div><div><br class=""><blockquote type="cite" class=""><div class="">On 8 Jun 2021, at 08:28, Valentin Micic <<a href="mailto:v@micic.co.za" class="">v@micic.co.za</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">As I was surprised with the measurement myself, I am sure that compiler did some significant optimisation — I am attaching the file with the source code, so you could review it yourself.</div><div class="">Also, it would be interesting to see how this performs on R22 (I haven’t installed it yet).</div><div class=""><br class=""></div><div class="">In my view, it doesn’t really mattar how fast the testing code is. What matter here is that there’s an order of magnitude difference in performance between the two BIFs. </div><div class=""><br class=""></div><div class="">The calling syntax for the tconvert:run/2 is: tconvert:run( a, 10000000 ).</div><div class=""><br class=""></div><div class="">The first argument is a term to be converted, and the second represents a number of iterations — higher this number, more accurate the measurement will be (at least in my opinion).</div><div class=""><br class=""></div><div class="">After reading your email I’ve looked at my code again, and noticed a potential slow-down for binary_to_term/1 portion of the test. </div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">do_bin_to_term( <<Bin/binary>> , 0 ) -> binary_to_term( Bin );</font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">do_bin_to_term( <<Bin/binary>> , N )</font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">-></font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class=""> <b class=""><font color="#e32400" class="">binary_to_term( <<Bin/binary>> ),</font></b></font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class=""> do_bin_to_term( Bin , N-1 )</font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">.</font></div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">When written as </div><div class=""><br class=""></div><div class=""><div class=""><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">do_bin_to_term( <<Bin/binary>> , 0 ) -> binary_to_term( Bin );</font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">do_bin_to_term( <<Bin/binary>> , N )</font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">-></font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class=""> <b class=""><font color="#4e7a27" class="">binary_to_term( Bin ),</font></b></font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class=""> do_bin_to_term( Bin , N-1 )</font></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><font face="Courier New" class="">.</font></div></div></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class="">It speeds up the code by factor 2 (<b class="">well,</b> <b class="">duh! </b>Cynic would say — so much for compiler optimisation ;-))</div><div class=""><br class=""></div><div class="">After this “fix”, binary_to_term/1 portion of the test runs “only” 14 times slower.</div><div class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">(cig@MacBook-Pro)322> tconvert:run( a, 10000000 ). </span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89); min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">term_to_binary/1 RETURN VALUE:<<131,100,0,1,97>></span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">REQUEST COUNT:10000000</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">ELAPSED TIME (usec):94664</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">TIME PER REQUEST (usec): 0.0094664</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">PROJECTED RATE (req/sec): <b class="">105636778</b>.50080284</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89); min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">binary_to_term/1 RETURN VALUE:a</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">REQUEST COUNT:10000000</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">ELAPSED TIME (usec):1385235</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">TIME PER REQUEST (usec): 0.1385235</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">PROJECTED RATE (req/sec): <b class="">7218991</b>.723425989</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgba(227, 227, 227, 0.89);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">ok</span></div><div class=""> </div><div class=""><br class=""></div><div class="">Kind regards</div><div class=""><br class=""></div><div class="">V/</div><div class=""><br class=""></div><div class=""></div></div><span id="cid:CDF526CB-3A19-4F22-93D4-10EBCB91F3EC"><tconvert.erl></span><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""></div><div class=""><br class=""></div><br class=""><div class=""><br class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On 08 Jun 2021, at 07:45, Jacob <<a href="mailto:jacob01@gmx.net" class="">jacob01@gmx.net</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi,<br class=""><br class="">I've tried to reproduce the measurement, but according to my<br class="">measurements, there is just a factor of 2 on Erlang/OTP 22.<br class=""><br class="">1> timer:tc(fun () -> bench:t2b(a, 1000000) end)<br class="">{109357,<<131,100,0,1,97>>}<br class="">2> timer:tc(fun () -> bench:b2t(<<131,100,0,1,97>>, 1000000) end).<br class="">{199488,a}<br class=""><br class=""><br class="">If I do not use the result of each term_to_binary call, the factor (~14)<br class="">is much closer to your measurements:<br class=""><br class="">3> timer:tc(fun () -> bench:broken_t2b(a, 1000000) end).<br class="">{14404,<<>>}<br class=""><br class="">Are you indeed sure, that the compiler did not optimise away the entire<br class="">call?<br class=""><br class="">/Jacob<br class=""><br class="">======================== bench.erl ==============================<br class="">-module(bench).<br class=""><br class="">-export([t2b/2, b2t/2, broken_t2b/2]).<br class=""><br class=""><br class="">t2b(T, N) -> t2b(T, N, undefined).<br class=""><br class="">t2b(_, 0, R) -> R;<br class="">t2b(T, N, _) -> R = term_to_binary(T), t2b(T, N-1, R).<br class=""><br class="">b2t(T, N) -> b2t(T, N, undefined).<br class=""><br class="">b2t(_, 0, R) -> R;<br class="">b2t(T, N, _) -> R = binary_to_term(T), b2t(T, N-1, R).<br class=""><br class="">broken_t2b(T, N) -> broken_t2b(T, N, undefined).<br class=""><br class="">broken_t2b(_, 0, R) -> R;<br class="">broken_t2b(T, N, R) -> _ = term_to_binary(T), broken_t2b(T, N-1, R).<br class="">=================================================================<br class=""><br class=""><br class="">On 06.06.21 02:07, Valentin Micic wrote:<br class=""><blockquote type="cite" class="">Hi all,<br class=""><br class="">I did some performance measurement recently that included conversion of<br class="">an arbitrary erlang term to its external binary representation via<br class="">term_to_binary/1, as well as reversing the result using binary_to_term/1.<br class=""><br class="">I’ve noticed that term_to_binary/1 is significantly faster than<br class="">binary_to_term/1.<br class=""><br class="">Also, I’ve observed that binary_to_term/1 performance gets considerably<br class="">worse as complexity of specified term increases, whilst term_to_binary/1<br class="">maintains (more-less) steady performance.<br class=""><br class="">(cig@MacBook-Pro)40> tconvert:run( a, 10000000 ).<br class=""><br class="">term_to_binary/1 RETURN VALUE:<<131,100,0,1,97>><br class="">REQUEST COUNT:10000000<br class="">ELAPSED TIME (usec):97070<br class="">TIME PER REQUEST (usec): 0.009707<br class="">PROJECTED RATE (req/sec): *103018440*.30081384<br class=""><br class="">binary_to_term/1 RETURN VALUE:a<br class="">REQUEST COUNT:10000000<br class="">ELAPSED TIME (usec):3383483<br class="">TIME PER REQUEST (usec): 0.3383483<br class="">PROJECTED RATE (req/sec): *2955534*.2822765773<br class="">ok<br class=""><br class="">(cig@MacBook-Pro)41> tconvert:run( {a,<<1,2,3>>, b, [1,2,3], c, {1,2,3},<br class="">d, #{a=>1, b=>2, c=>3}}, 10000000 ).<br class=""><br class="">term_to_binary/1 RETURN<br class="">VALUE:<<131,104,8,100,0,1,97,109,0,0,0,3,1,2,3,100,0,1,<br class=""> <br class="">98,107,0,3,1,2,3,100,0,1,99,104,3,97,1,97,2,97,<br class=""> <br class="">3,100,0,1,100,116,0,0,0,3,100,0,1,97,97,1,100,<br class=""> 0,1,98,97,2,100,0,1,99,97,3>><br class="">REQUEST COUNT:10000000<br class="">ELAPSED TIME (usec):97307<br class="">TIME PER REQUEST (usec): 0.0097307<br class="">PROJECTED RATE (req/sec): *102767529*.57135664<br class=""><br class="">binary_to_term/1 RETURN VALUE:{a,<<1,2,3>>,<br class=""> b,<br class=""> [1,2,3],<br class=""> c,<br class=""> {1,2,3},<br class=""> d, <br class=""> #{a => 1,b => 2,c => 3}}<br class="">REQUEST COUNT:10000000<br class="">ELAPSED TIME (usec):8747426<br class="">TIME PER REQUEST (usec): 0.8747426<br class="">PROJECTED RATE (req/sec): *1143193*.4377038456<br class="">ok<br class=""><br class=""><br class=""><br class="">I’ve performed testing on R21.1.<br class="">Any thoughts?<br class=""><br class="">V/<br class=""></blockquote><br class=""></div></div></blockquote></div><br class=""></div></div></div></div></blockquote></div><br class=""></div></body></html>