变量不是不可变

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源码。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值