erlang list 的使用建议

原文 2014-10-24 19:16:20 发表于 CSDN,这里对以前写的文章做下收录。

erlang有两种复合结构,tuple和list,两者的区别是tuple子元素的个数是固定不变的,声明后就不能改变了;而list是可变的,可以通过[H|T]来取出或插入新元素。上篇文章讲了tuple相关的内容,本篇就讲erlang list方面的知识,主要说一些基本操作和常用的list函数,再讲一些可以优化的点。
list基本操作

1> A = [1, 2, 3, "abc"].
[1,2,3,"abc"]
2> length(A).
4
3> is_list(A).
true
4> list_to_binary(A).
<<1,2,3,97,98,99>>
5> list_to_bitstring(A).
<<1,2,3,97,98,99>>

6> [A1|A2] = A.
[1,2,3,"abc"]
7> A1.
1
8> A2.
[2,3,"abc"]
9> hd(A).
1
10> tl(A).
[2,3,"abc"]
11> B = [0|A].
[0,1,2,3,"abc"]

继续阅读erlang list 的使用建议

erlang catch 异常处理

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

在说 erlang 异常捕获处理(catch)前,不得不说 erlang 内部数据(Eterm)。Eterm 是 Erlang Term 的简写,用来表示 erlang 中任意类型的数据,也就是说,erlang 可以用到的任意数据,都能 Eterm 表示。比如常见的 atom、数字、列表、元组,甚至 pid,port,fun,ets 表等等都用Eterm可以表示。 

Eterm

Eterm 在 VM 中主要分为三大类:列表,boxed 对象,立即数。(这么分法主要是复杂的数据无法单靠1个机器字表示,在32位机器上,一个字长4字节,在64位机器上是8字节。)

继续阅读erlang catch 异常处理

erlang时间校正机制

原文 2015-04-29 00:34:06 发表于 CSDN,这里对以前写的文章做下收录。

很多人会注意到这个问题,erlang提供了2个时间函数,erlang:now() 和 os:timestamp()。用法一样,都是返回当前的时间。具体时间是从1970年1月1日零时算起,到现在经过的时间,结果为{MegaSecs, Secs, MicroSecs}。

这两个函数有什么区别?
os:timestamp() 获取到的时间为操作系统的时间,不做任何修正;而erlang:now(),每次获取都会确保生成了唯一的时间,就是说,erlang:now()在实现上对时间做了一个校正,每次都生成一个单调向前的唯一值。

erlang:now()的特点:

Monotonic
erlang:now() never jumps backwards – it always moves forward
Interval correct
The interval between two erlang:now() calls is expected to correspond to the correct time in real life (as defined by an atomic clock, or better)
Absolute correctness
The erlang:now/0 value should be possible to convert to an absolute and correct date-time, corresponding to the real world date and time (the wall clock)
System correspondence
The erlang:now/0 value converted to a date-time is expected to correspond to times given by other programs on the system (or by functions like os:timestamp/0)
Unique
No two calls to erlang:now on one Erlang node should return the same value
继续阅读erlang时间校正机制

erlang tuple 和 record

原文 2014-06-16 23:19:36 发表于 CSDN,这里对以前写的文章做下收录。

erlang有两种复合结构,tuple和list,两者的区别是tuple子元素的个数是固定不变的,声明后就不能改变了;而list是可变的,可以通过[H|T]来取出或插入新元素。record有点像C/C++里面的结构体,实际上是语法糖,方便我们的开发,代码汇编时转成tuple表达形式。

Tuple
tuple的表示方法如:
{Term1,…,TermN}

下面以例子说明erlang tuple及一些基本操作:

1> A = {1,2}.
{1,2}
2> tuple_size(A).
2
3> is_tuple(A).
true
4> tuple_to_list(A).
[1,2]
5> element(1, A).
1
6> setelement(2, A, 3).
{1,3}

Record
record有点像C/C++里面的结构体,表示方法如:

-record(Name, {Field1 [= Value1],
               ...
               FieldN [= ValueN]}).

继续阅读erlang tuple 和 record

erlang 二进制与位语法

原文 2013-09-11 20:28:16 发表于 CSDN,这里对以前写的文章做下收录。

Erlang的位语法(Erlang Bit Syntax)提供了一种方法来表示和匹配二进制数据,这使得Erlang二进制对象在某种程度上等同于其他Erlang对象,如元组和列表。也因为其快速高效,使得在Erlang中,二进制对象被广泛使用,尤其是在协议编程方面。(官方文档

位语法/比特语法(bit syntax)
Erlang的位语法表达式,即Erlang二进制的表示形式:
<<>>
<<E1,…,En>>

每个元素Ei指定了一段二进制串(bit string)。每个元素Ei都是一个值,后面可以带有可选参数Size、TypeSpecifierList,如下:
Ei = Value |
Value:Size |
Value/TypeSpecifierList |
Value:Size/TypeSpecifierList
继续阅读erlang 二进制与位语法

erlang 监听高并发socket

原文 2014-05-29 22:58:26 发表于 CSDN,这里对以前写的文章做下收录。

看了erlang的一些开源网络框架RabbitMQ、Ranch,他们都使用多个进程同时accept一个socket。这种方式在使得socket端口监听的工作分担了更多的调度机会,但是,在erlang中,socket接受一个新连接后,如果想让另一个进程处理消息,就要显式的调用gen_tcp:controlling_process(Socket, Pid)。

所以问题来了,erlang多个进程同时监听一个socket安全吗?
这种方式在早期的erlang是不安全的,但R11B03 版本之后,erlang做了改进,允许多个进程同时监听同一个socket。

erlang R11B03 更新日志
OTP-6416 gen_tcp now allows for several processes to issue accept calls to the same listen-socket simultaniously. The different accepting processes will get connected sockets on a first-come-first-served basis.

当多个进程同时accept一个socket,erlang 内部将使用队列保存acceptor信息,以先来先服务的原则将新的连接关联到acceptor,再给acceptor投递消息 {inet_async, L, Ref, Result}。
具体看\erts\emulator\drivers\common\inet_drv.c 的 tcp_inet_ctl 函数,erlang对socket的处理都集中在inet_drv.c

erlang配合{backlog, N},监听新连接效果更佳
backlog是erlang用来设置socket等待连接队列。N为队列的长度,默认值5,显然太小了