变量不是不可变

xiaoxiao2026-08-14  35

erlang的变量是不可变的 这是语法层面的事情,照理是绕不过的。但是hipe,erlang的jit模块打开了这扇门,请看: sf bay facory 来自Facebook的Eugene Letuchy在ppt [url]http://www.erlang-factory.com/upload/presentations/31/EugeneLetuchy-ErlangatFacebook.pdf[/url] 里面提到: hipe_bifs Cheating single assignment ▪ Erlang is opinionated: ▪ Destructive assignment is hard because it should be ▪ hipe_bifs:bytearray_update() allows for destructive array assignment ▪ Necessary for aggregating Chat users’ presence ▪ Don’t tell anyone! 这是一个很好的绕过变量不可变的方法, 我再挖掘下google, 发现如下的文章: [url]http://erlang.org/pipermail/erlang-questions/2007-February/025331.html[/url] Per Gustafsson <> Thu Feb 22 17:41:01 CET 2007 * Previous message: [erlang-questions] Deforesting tuple updates * Next message: [erlang-questions] Is UBF still going, or did it morph/fade? * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] Joel Reymont wrote: > I don't think it works for floats or doubles. It's just bytes or > fixnums if I remember it correctly. > > On Feb 22, 2007, at 3:32 PM, Daniel Luna wrote: > > >>As long as the values in the array are simple terms, you can use >>hipe_bifs:bytearray/2. > > > -- > http://wagerlabs.com/ > > > > > > _______________________________________________ > erlang-questions mailing list > > http://www.erlang.org/mailman/listinfo/erlang-questions You could use this code: -module(floats). -export([new/1,update/3,sum/1, new2/1,update2/3,sum2/1, test/0]). new(N) -> hipe_bifs:bytearray(N*8,0). update(Arr,N,Float) -> <<A1,A2,A3,A4,A5,A6,A7,A8>> = <<Float/float>>, Start=N*8, hipe_bifs:bytearray_update(Arr,Start,A1), hipe_bifs:bytearray_update(Arr,Start+1,A2), hipe_bifs:bytearray_update(Arr,Start+2,A3), hipe_bifs:bytearray_update(Arr,Start+3,A4), hipe_bifs:bytearray_update(Arr,Start+4,A5), hipe_bifs:bytearray_update(Arr,Start+5,A6), hipe_bifs:bytearray_update(Arr,Start+6,A7), hipe_bifs:bytearray_update(Arr,Start+7,A8). sum(Bin) -> sum(Bin,0.0). sum(<<Float/float,Rest/binary>>, Acc) -> sum(Rest,Float+Acc); sum(<<>>,Acc) -> Acc. Performance is not that great, about 4-5 times faster updates than gb_trees for arrays of 100000 floats, and summing is slower. Per 试验下: root@yufeng-desktop:~# cat floats.erl -module(floats). -export([new/1,update/3,sum/1]). new(N) -> hipe_bifs:bytearray(N*8,0). update(Arr,N,Float) -> <<A1,A2,A3,A4,A5,A6,A7,A8>> = <<Float/float>>, Start=N*8, hipe_bifs:bytearray_update(Arr,Start,A1), hipe_bifs:bytearray_update(Arr,Start+1,A2), hipe_bifs:bytearray_update(Arr,Start+2,A3), hipe_bifs:bytearray_update(Arr,Start+3,A4), hipe_bifs:bytearray_update(Arr,Start+4,A5), hipe_bifs:bytearray_update(Arr,Start+5,A6), hipe_bifs:bytearray_update(Arr,Start+6,A7), hipe_bifs:bytearray_update(Arr,Start+7,A8). sum(Bin) -> sum(Bin,0.0). sum(<<Float/float,Rest/binary>>, Acc) -> sum(Rest,Float+Acc); sum(<<>>,Acc) -> Acc. root@yufeng-desktop:~# erl Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.7.2 (abort with ^G) 1> F = floats:new(5). <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>> 2> rp(F). <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0>> ok 3> floats:update(F, 1, 1234.00). <<0,0,0,0,0,0,0,0,64,147,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,...>> 4> rp(F). <<0,0,0,0,0,0,0,0,64,147,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0>> ok 5> floats:update(F, 2, 5678.00). <<0,0,0,0,0,0,0,0,64,147,72,0,0,0,0,0,64,182,46,0,0,0,0,0, 0,0,0,0,0,...>> 6> rp(F). <<0,0,0,0,0,0,0,0,64,147,72,0,0,0,0,0,64,182,46,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>> ok 7> floats:sum(F). 6912.0 8> 1234+ 5678=6912. 6912 9> 恩 没问题的, 不错。 再到源码去挖掘下 ...\otp_src_R13A-0\erts\emulator\hipe\hipe_bif0.tab bif hipe_bifs:bytearray/2 bif hipe_bifs:bytearray_sub/2 bif hipe_bifs:bytearray_update/3 bif hipe_bifs:bitarray/2 bif hipe_bifs:bitarray_sub/2 [color=red]bif hipe_bifs:bitarray_update/3 bif hipe_bifs:array/2 bif hipe_bifs:array_length/1 bif hipe_bifs:array_sub/2 bif hipe_bifs:array_update/3[/color] bif hipe_bifs:ref/1 bif hipe_bifs:ref_get/1 bif hipe_bifs:ref_set/2 root@yufeng-desktop:~# erl Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.7.2 (abort with ^G) 1> A=hipe_bifs:array(10, []). 2135987033931617136292706780490918553627426255794015745390464377869606912860751039403868490301435 2> rp(A). 2135987033931617136292706780490918553627426255794015745390464377869606912860751039403868490301435 ok 3> hipe_bifs:array_length(A). 10 4> hipe_bifs:array_update(A, 2, 1). 2135987033931617136292706780490918553627426255794015745390464377869527684698900857852928490209275 5> 5> hipe_bifs:array_update(A, 1, atom). 2135987033931617136292706780490918553627426255794015745390464377869527684698882411121018128039931 6> hipe_bifs:array_sub(A,1). atom 7> hipe_bifs:array_sub(A,2). 1 8> R=hipe_bifs:ref(1). 31 9> hipe_bifs:ref_get(R). 1 10> hipe_bifs:ref_set(R, 10). 175 11> hipe_bifs:ref_get(R). 10 O Yeah 这些也都OK. 还有很多hipe_bifs的导出在相应的.tab文件里面,读者自己挖掘了。这样我们就可以把状态更新, 无需通过消息 或者 ets, 大大加快效率。 附上8皇后的hipe源码。 相关资源:多核时代_Erlang的时代
转载请注明原文地址: https://www.6miu.com/read-5051233.html

最新回复(0)