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

继续阅读erlang binary 数据转换问题

erlang二进制数据垃圾回收

原文 2014-06-10 01:01:57 发表于 CSDN,这里对以前写的文章做下收录。

erlang 二进制数据在内存中有两种存在形式,当数据大小不到 64 bytes,就直接存在进程堆内,如果超过了 64 bytes,就被保存到进程外的共享堆里,可以给节点内所有进程共享。

erlang 有两种二进制容器:heap binaries 和 refc binaries。
heap binaries

Heap binaries are small binaries, up to 64 bytes, that are stored directly on the process heap. They will be copied when the process is garbage collected and when they are sent as a message. They don't require any special handling by the garbage collector.

这个就是进程堆二进制,是一些比较小的二进制数据,每个数据大小不超过 64bytes,这些数据保存在进程堆内。对于这里的二进制数据,垃圾回收走的是进程堆数据的回收机制,参考这里。如果发给其他进程的消息含有这些数据,erlang 将直接复制一份到别的进程堆内。
继续阅读erlang二进制数据垃圾回收

lua 开发防坑指南

原文 2015-09-27 10:47:28 发表于 CSDN,这里对以前写的文章做下收录。

Lua可以被C/C++ 代码调用,反过来也可以调用C/C++的函数,这使得Lua被广泛应用。Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以运行。文章列举lua使用中遇到的坑点,做个汇总。

if判断

lua把 nil 和false 视为“假”,其他都为“真”

逻辑运算符 and or

lua的and or 可以用来构成三元表达式,如下:

> = 1 == 1 and 1 or 2
1

但如果是这样写,就不是你想要的结果了:

> = 1 == 1 and false or true
true

这是因为,and 运算符判定 false不成立,就继续执行了 or 运算符的结果
如果你一定要返回 true 或 false,要这么写:

> = ( 1 == 1 and {false} or {true} )[1]
false

继续阅读lua 开发防坑指南

erlang 开发防坑指南

原文 2015-02-12 23:25:02 发表于 CSDN,这里对以前写的文章做下收录。

任何语言在使用中都会遇到这样那样的问题,erlang也是。这里整理下我遇到的一些问题,避免继续踩坑。说实话,“防坑指南”这个标题有点过于招摇,不过还是希望引起重视,避免在实际开发中重复犯这些问题。

'--' 运算与 '++'运算

1> [1,2,3,4] -- [1] -- [2]. 
[2,3,4]

算是erlang经典的问题了。这是从后面算起的,先算 [1] -- [2] ,得到 [1] 后被 [1,2,3,4] --,最后得到 [2,3,4]
 '++'运算也是一样的,也是从后面开始算起。

2> [1,2,3,4] -- [1] ++ [2,3,4].
[]

另外,以下这种情况也要注意,只会减去遇到的第一个元素。

3> [1,2,3,2] -- [2].
[1,3,2]

继续阅读erlang 开发防坑指南

erlang 判断导出函数问题

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

erlang 本身提供一个接口 erlang:function_exported/3,可以用来检查模块是否有导出函数,但是有时候这个接口无法正常使用。
下面重现一下这个问题:

1> erlang:function_exported(crypto,start,0).
false
2> crypto:start().
ok
3> erlang:function_exported(crypto,start,0).
true

注意:例子中并不是说一定要 crypto:start() 才能使用这个函数,只是说这个函数确实存在。
继续阅读erlang 判断导出函数问题

erlang 热更新实现分析

原文 2015-02-10 01:08:22 发表于 CSDN,这里对以前写的文章做下收录。

Joe Armstrong 在描述 Erlang 的设计要求时,就提到了软件维护应该能在不停止系统的情况下进行。在实践中,我们也因为这种不停止服务的热更新获益良多。那么 Erlang 是如何做到热更新的呢?这就是本文要讨论的问题。

erlang VM 为每个模块最多保存 2 份代码,当前版本'current'和旧版本'old',当模块第一次被加载时,代码就是'current'版本。如果有新的代码被加载,'current'版本代码就变成了'old'版本,新的代码就成了'current'版本。erlang 用两个版本共存的方法来保证任何时候总有一个版本可用,对外服务就不会停止。

前言

为什么代码热更新时不影响进程运行?
为什么进程要使用外部调用(M:F/A)才能切换到新代码?
为什么可以同时使用2个版本的代码?
为什么只能一个模块一个模块热更?
....

我们总会有很多疑问,但一切的答案都在源码上。现在深入剖析下 erlang 热更新实现机制,相信你的疑惑可以找到答案。
继续阅读erlang 热更新实现分析