erlang的变量是不可变的 这是语法层面的事情,照理是绕不过的。但是hipe,erlang的jit模块打开了这扇门,请看:
sf bay facory 来自Facebook的Eugene Letuchy在ppt
http://www.erlang-factory.com/upload/presentations/31/EugeneLetuchy-ErlangatFacebook.pdf 里面提到:
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, 发现如下的文章:
http://erlang.org/pipermail/erlang-questions/2007-February/025331.html
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
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
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源码。