OTP监控树笔记

这是Learn You Some Erlang中的Building an Applications with Otp的笔记.

在文中, OTP被戏称为Onion Theory Platform, 监控树像洋葱一样, 一层又一层.

OTP的哲学是工人-监工, 工作进程做错事就让它死掉, 监督进程再开启新的工作进程来干活. 这样做有个让人觉得很麻烦的问题: 工作进程死掉了, 它的状态怎么办? 文中进行了讨论. 状态可以分成三类:

  • 静态的状态. 这从配置文件读回来就可以, 没什么问题.

  • 动态但可重新获取的状态. 就是那些可以利用初始状态计算而来的东西, 重新算就行了.

  • 动态且不可重新获取的状态. 比如说用户的输入, 外部事件等等.

如果工作进程只有前两类状态, 用监工的方法很容易的处理, 死了重启, 恢复状态就可以了.

第三类的状态需要放到不允许出错的地方(error kernel), 其实就是用try...catch包起来.

作者示范了一个进程池的设计.

所谓进程池, 就是可以容纳一定数量的进程同时运行, 当同时运行的进程数达到限制时, 把工作放入队列进行排队, 等待有空位时再开始新的任务.

做这么一个进程池, 需要有一个服务进程来计数同时运行的工作进程数 …

more ...

【Erl代码片段】cowboy的一处大小写处理代码

在cowboy的库cowlib中的cow_inline.hrl文件看到一堆很长的宏:

-define(INLINE_LOWERCASE(Function, Rest, Acc),
    $A -> Function(Rest, << Acc/binary, $a >>);
    $B -> Function(Rest, << Acc/binary, $b >>);
    $C -> Function(Rest, << Acc/binary, $c >>);
    $D -> Function(Rest, << Acc/binary, $d >>);
    $E -> Function(Rest, << Acc/binary, $e >>);
    $F -> Function(Rest, << Acc/binary, $f >>);
    $G -> Function(Rest, << Acc/binary …
more ...

【Erl代码片段】更快的proplists:get_value/3

在cowboy的cowboy_protocol.erl 文件中看到如这样一下函数:

%% Faster alternative to proplists:get_value/3.
get_value(Key, Opts, Default) ->
    case lists:keyfind(Key, 1, Opts) of
        {_, Value} -> Value;
        _ -> Default
    end.

做了一下测试, 考虑到proplist一般都不长, 用一个10个元素的列表进行测试, 结果这个函数比 proplists:get_value/3 快5倍, 对于更长的列表差别更大.

bench:get_value/3
Single Process:   13035909 call per sec,   16777216 times in  1287 ms …
more ...

Erlang数据项的size

Erlang中数据项(Erlang Term)的所占据的空间大小可以用各种size来获取.

  • 其中对于所有数据项都通用的有: erlang:external_size/1, erts_debug:size/1, erts_debug:flat_size/1

  • 适用于二进制串有: erlang:size/1, erlang:byte_size/1, erlang:bit_size/1

  • 适用于元组的有: erlang:size/1, erlang:tuple_size/1

erlang:external_size/1

erlang:external_size/1 用来获取erlang数据项的外部格式(External Term Format)最大大小. 所谓外部格式, 就是用term_to_binary/1 打包形成的格式, 如果要把数据项从一台节点发到另一个节点, 或是持久化装到数据库中 …

more ...

Erlang中IPv4地址与整数的转换

IPv4地址通常表示为 A.B.C.D, 其中A-D都是0-255之间的整数, 总长为32位, 因此, 可以使用单一个32位无符号整数表示一个IP地址.

Erlang 中可以使用以下方式进行转换:

ip_to_int({A,B,C,D}) ->
    << Int:32 >> = <<A:8, B:8, C:8, D:8>>,
    Int.

int_to_ip(Int) ->
    <<A:8, B:8, C:8, D:8>> = << Int:32 >>,
    {A,B,C,D}.

上面两个函数没考虑溢出的问题, 溢出的部分会被截断, 比如说 A 输入 257 会被视为 …

more ...

Erlang的大小比较

Erlang 里, 不只数字可以比较大小, 基本上所有变量都可以比较大小.

大小关系是:

数字 < 原子 < reference < 函数 < 端口 < pid < 元组 < 列表 < 二进制

也就是说, 数字总是比原子小, 原子总是比列表小...

也就是说, 即使 Val > 5true, 也不能保证 Val 是个数字.

而且, 同一种非数字类型也有大小, 比如说

    a > b         %% 假
    "b" > "aa"    %% 真

想不明白这样比较大小有啥意义, 真是个坑啊.


update: 2014年6月8日

所有数据项都可以比较, 在进行lists:sort/2的时候就会很方便.

而且, 要保证 Val 是个数字, 更合理的应该是 …

more ...