erlang binary 数据转换问题

原文 2015-01-12 00:11:27 发表于 CSDN,这里对以前写的文章做下收录。

erlang 提供 binary_to_term,把一个二进制数据转为原始的 erlang 数据。但是,这个函数也有副作用。如果直接将对端传来的数据做一次 binary_to_term,就有可能导致VM crash掉。

binary_to_term 副作用
这是因为二进制数据带有原子时,binary_to_term 会生成这些原子。但VM原子总数是有限制,而且原子不参与GC。假如数据带有原子数量超过erlang VM限制,就会导致VM crash
所以,针对这个问题,erlang提供了另外一个函数 binary_to_term(Binary, [safe]),这个函数不会生成新的的原子,在这点上,这两个函数关系也像 list_to_atom 和 list_to_existing_atom

1> term_to_binary(atom).
<<131,100,0,4,97,116,111,109>>
2> binary_to_term(v(1), [safe]).
atom
3> binary_to_term(v(1)).
atom
4> binary_to_term(<<131,100,0,4,116,101,115,116>>, [safe]).
%%这里会抛出异常
** exception error: bad argument
     in function  binary_to_term/2
        called as binary_to_term(<<131,100,0,4,116,101,115,116>>,[safe])
5> binary_to_term(<<131,100,0,4,116,101,115,116>>).
test
6> binary_to_term(<<131,100,0,4,116,101,115,116>>, [safe]).
%%这里就不会抛出异常
test

term_to_binary二进制压缩
与 binary_to_term 相反,term_to_binary 则是把erlang数据转成一个二进制数据。默认情况下,term_to_binary 后的二进制数据是不经过压缩的,比较大,erlang也提供了另外一个函数,用于压缩生成的二进制数据。

term_to_binary(Term, [{compressed, Level}]
Level 取值范围1-9,表示压缩率,1是压缩比最低,但最少消耗时间,9是最高压缩比。 也可以是0,表示不压缩。
实际上,1已经能满足要求,又不会太消耗时间。而且,term_to_binary/2压缩后的二进制对 binary_to_term 影响不大
另外,term_to_binary做二进制压缩,必然带有一定的开销,但比term_to_binary后使用 zlib:zip 压缩数据来说,开销就小了很多,而且接收端还要zlib:unzip数据。显然term_to_binary/2 是在注重流量的场合比较适合。

发表评论

邮箱地址不会被公开。 必填项已用*标注