`
litaocheng
  • 浏览: 337136 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Erlang开发建议(杂记版)

阅读更多
以下是在erlang项目开发中的一些记录,即包含很多通俗易懂的原则,也包含一些似是而非的建议,比较混乱,还没有积累到一个可以分门别类的地步,各位就将就看吧..
:)

* 确保没有任何编译警告

* Erlang中String采用list实现,32位系统中,其1个字符用8个字节的空间(4个保存value, 4个保存指针)。因此string速度较慢,空间占用较大

* 在Server中,总是尽力书写尾递归(tail-recursive)的函数

* 使用'++'时,left list会被拷贝,然后添加到right list的头部,因此最好把length较短的list放在左侧

* 避免使用regexp,如果需要正则表达式,请使用re

* timer模块的大部分函数实现,依赖于一个process,如果过多使用timer,会导致这个process负载过大,影响效率。
  推荐使用erlang:send_after/3及erlang:start_timer/3

* 避免使用list_to_atom/1,因为erlang中atom数量最大为1048576, 且不进行GC控制。因此如果持续性的调用list_to_atom/1
  可能很容易达到系统上限,从而导致emulator terminate。请使用list_to_existing_atom/1。

* list内部实现为一个列表,因此length(List), 需要遍历整个list比较耗时

* 对于不同的数据类型,使用不同的size函数:tuple_size/1, byte_size/1, bit_size/1

* 使用binary match来进行binary的分割,而不使用split_binary/2

* 如果两个list都拥有很多数据,那么请不要使用'--',而是将数据转化到ordsets,然后调用ordsets:substract/2.

* 对于binary相关操作可以进行binary优化(bin_opt_info编译选项)代码框架:

*   f(<<Pattern1,...,Rest/bits>>,...) -> 
       ... % Rest is not used here 
       f(Rest,...); 
    f(<<Pattern2,...,Rest/bits>>,...) -> 
      ... % Rest is not used here 
      f(Rest,...); 
    ... 
    f(<<>>, ...) -> 
      ReturnValue.

* 调用lists:flatten/1可以将list扁平化,这个操作代价很大,比'++'还要昂贵。下面这些时候我们可以避免:
    将数据发送给port时
    调用list_bo_binary/1和iolist_to_binary前

* 小的函数可以让您方便的找出错误的函数和代码

* 不要在同一行出现相同的符号
20    some_fun() ->
21       L = [{key1, v1}, {key2, [some_record#v21, v22]}],
22      ...
编译时,会提示line 21 '[' 语法错误, 因为21行有多个 '[' ,所以这个bug不能准确定位,你需要花时间去排查代码。
好的做法是:
20 some_fun() ->
21      L = [{key1, v1},
22            {key2, [some_record#v21, v22]}
23            ],
      ...
这样,编译其会提示你 line 22 '[' 语法错误,你很开就知道是那个地方错了。

* 使用 CTRL + \ 或 init:stop(), 可以退出Erlang, 使用CTRL + G 及 CTRL + C 弹出菜单选项,可以选择是否退出Erlang。
其中CTRL + G可以用来连接其他的shell, CTRL + C可以查看其他一些系统信息
Ctrl + C abort 是野蛮的退出方式

* use "open_port({fd,0,2}, [out])" make erlang program write standard error to unix system

* If you don't run experiments before you start designing a new system, your entire system will be an experiment!

* standard data structure desc:

Module Description
sets sets, i.e. a collection of unique elements.
gb_sets sets, but based on a general balanced data structure
gb_tree a general balanced tree
dict maps, also called associative arrays
ets hash tables and ordered sets (trees)
dets on-disk hash tables

Suggestion:
elments count: 0 - 100 | 100 - 10000  |  10000 -
our select   :  list   |      ets     |  gb_tree

* 通过code:clash/0 检测代码中是否有module冲突现象(sticky)

* epmd -d -d 启动 epmd 可以查看erlang node之间的通讯

* 将正常的逻辑代码和错误处理代码分离,发生错误时,尽管错误。由另一个错误处理模块进行处理

* 类似于操作系统,我们的程序也可以分为kernel 和 user 两层, 对于kernel绝对不能出现错误, 对于user可以出现错误,进行恢复

* process顶层loop涉及的代码及函数,最好在一个module中实现

* process 的register name和module名称一致, 便于寻找代码

* 每个process具有一个单一的角色,比如:supervisor 用来进行错误恢复, work 工作者,可以出现错误, trusted worker 不会出现错误

* 通过函数调用可以实现的功能,就不要使用sever实现(如gen_server, 及类似的loop 实现)

* 给消息加一个tag,在发生错误的时候,可以定位到消息,同时也有利于程序的稳健

* 在消息循环中,对于unknown的消息,请调用lib:flush_receive/0 将其清除,减轻process msg queue的长度

* server中总是书写尾递归的循环

* 尽量使用record, 而不是原始的tuple来表现数据结构, 在使用record时,使用select match:
#person{name = Name, age = Age} = Person

* 对于返回值,最好也添加一个tag,用来说明返回值类型,或者执行成功与否

* 尽可能少的使用catch和try,在erlang程序中,不推荐主动捕获异常。只有当我们的逻辑特别复杂,我们可以使用throw来返回数据,使用catch来获取返回值。

* 当然程序与外界交互,外界数据不可靠时,需要使用catch和try

* 慎重使用process dictory, 当你使用get/1, put/1时,你的应用会具有很大的slide effect。可以通过加入一个新的参数来保存原本需要存储到process dictory中数据

* 如果不想使自己糊涂,请不要使用import

* 使用export时,将功能类似的接口组合在一起,并添加合理的注视,这样你的接口更清晰,别人使用起来更方便

* 不要书写嵌套太深的代码

* 不要书写太长的module

* 不要书写太长的函数

* 每行代码不能太长

* 避免使用 "_" 匿名变量,请为每个变量选择有意义的名称,如够某个变量暂时不使用,请以下划线 "_" 开始

* {error, enfile} enfile error in socket 是以为内linux系统中 ulimit 限制, 在root下修改:ulimit -n 25000

* {error, enotconn} 表示socket已经关闭

* 在erlang开发时,慎重使用macro,因为erlang的single assign的缘故,同时调用某个marco,而macro又定义了某个变量,可能导致badmatch错误。
比如:
-define(ADDLINEINFO1(F),
        (
        begin
        Str1 = lists:concat(["[Mod:", ?MODULE, " Line:", ?LINE, "]"]),
        Str1 ++ F
        end
        )).
-define(WARN(Log, F, D), log4erl:warn(Log, ?ADDLINEINFO(F), D)).
如果连续使用 WARN, 会出现此错误

* erlang中可以定义很多环境变量:
ERL_MAX_ETS_TABLES 设置最大的ets数目 默认1400
ERL_MAX_PORTS erlang最大的port数目 默认1024

* .app文件中的start_phases, 选项既可以用来作为include applications之间的同步启动,也可以用来对单个application进行分布启动。
顺序如下
包含included app:

application:start(prim_app)
=> prim_app_cb:start(normal, [])
=> prim_app_cb:start_phase(init, normal, [])
=> prim_app_cb:start_phase(go, normal, [])
=> incl_app_cb:start_phase(go, normal, [])
ok

无included app:
application:start(prim_app)
=> prim_app_cb:start(normal, [])
=> prim_app_cb:start_phase(init, normal, [])
=> prim_app_cb:start_phase(go, normal, [])
ok

* 任何时候,都要重视函数的返回值,通过match确保您的预期,如果发生错误,那么就大胆的表达出来。
分享到:
评论
8 楼 ShiningRay 2009-05-07  
第一句话应该是“确保”吧?
7 楼 mryufeng 2009-04-27  
chaoslawful 写道
引用
* 对于不同的数据类型,使用不同的size函数:tuple_size/1, byte_size/1, bit_size/1

这一点是否有具体原因?

看beam代码感觉size/1和tuple_size/1、byte_size/1的效率应该没什么差别,都需要判断一次具体类型,长度计算方法是一样的,实际测试也没发现有差异。

R13A代码中:
* size/1实现在erts/emulator/beam/erl_bif_guard.c@L186
* bit_size/1实现在上面文件的L207
* byte_size/1实现在上面文件的L239
* tuple_size/1实现在erts/emulator/beam/bif.c@L2079

CTRL \ 和 q()推出的方式差别很大. q()是调用init:stop会做模块的反初始化, 比如说mnesia不做这一步就可能数据损害。
6 楼 mryufeng 2009-04-27  
chaoslawful 写道
引用
* 对于不同的数据类型,使用不同的size函数:tuple_size/1, byte_size/1, bit_size/1

这一点是否有具体原因?

看beam代码感觉size/1和tuple_size/1、byte_size/1的效率应该没什么差别,都需要判断一次具体类型,长度计算方法是一样的,实际测试也没发现有差异。

R13A代码中:
* size/1实现在erts/emulator/beam/erl_bif_guard.c@L186
* bit_size/1实现在上面文件的L207
* byte_size/1实现在上面文件的L239
* tuple_size/1实现在erts/emulator/beam/bif.c@L2079

效率应该是不是最大的考虑 主要是从名字上让程序更容易明白。
5 楼 chaoslawful 2009-04-27  
引用
* 对于不同的数据类型,使用不同的size函数:tuple_size/1, byte_size/1, bit_size/1

这一点是否有具体原因?

看beam代码感觉size/1和tuple_size/1、byte_size/1的效率应该没什么差别,都需要判断一次具体类型,长度计算方法是一样的,实际测试也没发现有差异。

R13A代码中:
* size/1实现在erts/emulator/beam/erl_bif_guard.c@L186
* bit_size/1实现在上面文件的L207
* byte_size/1实现在上面文件的L239
* tuple_size/1实现在erts/emulator/beam/bif.c@L2079
4 楼 cryolite 2009-04-25  
mryufeng 写道
CTRL + \  触发SIGQUIT, 调用erl_exi退出更野蛮。


q().看上去少其实也要敲五个字母
3 楼 Arbow 2009-04-25  
Good Job!收藏了
2 楼 mryufeng 2009-04-25  
CTRL + \  触发SIGQUIT, 调用erl_exi退出更野蛮。
1 楼 dogstar 2009-04-24  
well done .再接再厉

相关推荐

    二郎助手erlang开发工具、erlang编辑器

    【二郎助手:Erlang开发的利器】 在IT领域,Erlang是一种强大的编程语言,尤其在并发处理和分布式系统方面表现出色。为了更好地支持Erlang的开发,二郎助手应运而生,它是一款专为Elang语言定制的开发工具,旨在...

    Erlang开发环境搭建

    Erlang开发环境搭建 Erlang是一种功能强大且灵活的编程语言,广泛应用于 telecommunications、金融、电子商务等领域。然而,要充分发挥Erlang的潜力,需要搭建合适的开发环境。本文将指导读者如何在Windows平台下...

    Erlang开发及应用

    Erlang开发及应用

    erlang_版本24.3.4.4

    Erlang是一种面向并发的、函数式编程语言,由瑞典电信设备制造商Ericsson开发,主要用于构建高可用性、分布式和实时系统。版本24.3.4.4是Erlang的一个更新版本,包含了对先前版本的改进和修复。Erlang以其强大的错误...

    eclipse erlang 开发工具插件 2011-3 月 the stable releases

    Eclipse Erlang 开发工具插件是为Eclipse IDE量身定制的一款扩展,旨在提供一个高效、便捷的环境来编写、测试和调试Erlang代码。这款插件名为"Erlide",它在2011年3月发布了稳定版本,以满足开发者对Erlang语言日益...

    Erlang的windows版本

    Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的windows版本Erlang的...

    erlang25.0 windows版本

    作为“源码软件”,Erlang 25.0同样提供了源代码,开发者可以深入研究其内部工作原理,进行定制化开发,或者为Erlang社区贡献代码。对于开发者而言,理解Erlang的源码可以帮助他们更好地利用这个平台,实现更高效、...

    erlang开发简介

    erlang

    erlang绿色解压版 otp_win64 21.0.1.zip

    erlang绿色解压版 otp_win64 21.0.1 OTP 20.0 下载,OTP (Open Telecom Platform) 是一个开源的 Erlang 分发和一个用 Erlang 编写的应用服务器,由爱立信开发。Erlang / OTP 21.0.1 是一个新的主要版本,新增了一些新...

    Erlang程序设计中文版

    **Erlang程序设计中文版**是一本深入探讨Erlang编程语言的书籍,旨在帮助开发者理解和掌握这种在并发处理和分布式系统中广泛使用的语言。Erlang以其强大的错误恢复能力、热代码替换以及对大规模并发的支持而闻名,是...

    最新最全rabbitmq与erlang版本匹配-2020-04-23.docx

    - 为了获得最佳的性能和安全性,建议始终使用最新版本的Erlang/OTP,同时确保该版本与当前运行的RabbitMQ版本兼容。 - 定期检查RabbitMQ和Erlang的更新,以确保及时修补安全漏洞和修复已知问题。 - 在生产环境中,...

    erlang23.2版windows64位.zip

    Erlang是一种面向并发的、函数式编程语言,由瑞典电信设备制造商Ericsson开发,用于构建高可用性、分布式和实时系统。Erlang因其在处理大量并发连接和容错能力上的优秀表现,广泛应用于电信、银行、互联网服务等领域...

    Erlang程序设计中文版(完整书签)

    Erlang程序设计中文版(完整书签),清晰版!!! Erlang开发必备

    erlang开发入门教程

    erlang是爱立信开发的程序开发语言,融合了函数式编程与面向对象编程,并行处理内建与程序语言内部,特别适合创建并发行、容错性、分布性要求比较高的软实时系统,掌握它程序员必备的一种编程技能,与它相似的语言...

    Erlang游戏开发

    Erlang游戏开发.ppt

    linux下erlang22版本和rabbitmq3.7版本

    4. **API一致性**:改进了REST API和管理命令,使其更加一致,便于开发和管理。 5. **兼容性增强**:与多种编程语言的客户端库有更好的兼容性,如Python、Java、Ruby等。 在CentOS 7和8上安装Erlang 22和RabbitMQ ...

    Erlang / OTP 21.0 版本下载

    官网下载实在是困难,我把当前Erlang / OTP 21.0 版本提交到这里提供给大家和自己下载 原先积分0的现在都这么高了,为了方便大家,放出云盘地址:https://pan.百度.com/s/1hb8vPiMslXxNuJC8PvnKgg提取码wmx8

    程序员开发erlang的资料

    6. **Eclipse插件Erlide**:Erlide是Erlang开发的Eclipse集成开发环境插件,提供代码编辑、调试、重构和项目管理等功能,帮助开发者提高Erlang编码效率。 7. **Erlang实践**:从文件名erlang_practice.pdf来看,...

Global site tag (gtag.js) - Google Analytics