建立一个OTP应用

http://www.javaeye.com/topic/374167

以下是在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确保您的预期,如果发生错误,那么就大胆的表达出来。

时间: 2024-11-14 12:26:44

建立一个OTP应用的相关文章

c语言:写一个函数建立一个有3名学生数据的单向动态链表

写一个函数建立一个有3名学生数据的单向动态链表. 解:程序: #include<stdio.h> #include<stdlib.h> #define LEN sizeof(struct Student) struct Student { long num; float score; struct Student *next; }; int n; struct Student *creat(void)//定义函数返回一个指向链表头的指针 { struct Student *head

如何建立一个GPU加速的研究计算集群(一)

世界上某些最快的计算机是集群组成的.集群是有多个计算机通过高速网络连接起来的一个计算系统.集群计算机比单台计算机可以达到更高的可用性,可靠性和伸缩性.随着对基于GPU的高性能计算采用越来越广,英伟达GPU逐渐成为世界上最厉害的超级计算集群的一部分.世界前500的超级计算机中,包括差不多50个采用了英伟达的的GPU,并且目前世界上最快的计算机泰坦,使用了大约18000个英伟达开普勒GPU. 在这个帖子中,我将会一步一步的介绍设计.部署和管理一个小型的GPU集群整个过程.我会介绍GPU集群的组成部分

Hyperledger Fabric 建立一个简单网络

p { margin-bottom: 0.25cm; line-height: 120% } Building you first network 网络结构: 2个Orgnizations(每个Org包含2个peer节点)+1个solo ordering service 打开fabric-sample下的示例first-network p { margin-bottom: 0.25cm; line-height: 120% } 其中byfn.sh为启动这个网络的启动脚本,启动脚本中除建立一个包含

如何建立一个自己的网站,建网站的步骤

引导语:其实建好一个网站,除了把网站设计出来之外,还需要域名空间等,那么,具体建立一个网站的步骤是什么呢?接下来由小编给大家带来收集整理的建网站的步骤,希望看完对你有帮助! 网站建设步骤 1.网站方案策划(主要是网站定位,功能,界面风格等) 2.注册域名 3.网站制作(可自己制作,也可选择专业的网站建设公司) 4.购买虚拟主机(或配置独立主机) 5.配置域名.主机及调整程序开通网站 6.网站内容增加 7.网站推广 (一)域名(Domain Name),是由一串用点分隔的名字组成的Internet

Java界面编程-建立一个可以画出图形的简单框架

引子:总共使用3个.java文件,建立一个简单界面编程的框架. 第1个文件:NotHelloWorldComponent.java //NotHelloWorldComponent.java 1 import java.awt.*; 2 import java.awt.geom.*; 3 import javax.swing.*; 4 5 public class NotHelloWorldComponent extends JComponent { 6 public static final

权限管理:建立一个经理组

1.权限管理:建立一个经理组jingli 在系统根下建立一个目录名为public,并切换public目录所属组为jingli 建立aaa bbb ccc三个用户.将aaa bbb两个用户加到jingli组中. groupadd jingli mkdir /pub chgrp jingli /pub/ ll /pub/ useradd aaa useradd bbb useradd ccc passwd aaa passwd bbb passwd ccc usermod -G jingli aaa

【转】如何建立一个样式新颖的CSS3搜索框

在线演示 搜索框大概是web开发中最常用的UI元素之一,我想基本没有必要去介绍如何使用它.无论是网站还是web应用,都会为了增强用户体验而添加它,那么你是不是也想过设计一个别致的搜索框? 在今天的文章中,大家将会学到如何使用伪元素来创建一个超酷的CSS3搜索框.当然在开始介绍前你也可以下载源代码或者查看在线演示. HTML举例: 正如接下来你所看到的,标记很少,并且很容易理解: <form class=“cf form-wrapper”> <input type=“text” place

Hibernate学习——建立一个简单的Hibernate项目

最近老师让做个web小应用,大三的时候学习过一点J2EE的东西,也做过一些web相关的XXX管理系统,都是用servlet,jsp这些完成的,虽然勉强能够完成任务,但其中各种代码掺杂在一起,不好看而且维护起来也很麻烦,出了一点问题要调试好久才能解决.这次打算让自己多学一点东西,在项目的架构上我使用了struts2实现了多层代码的分离,在数据库方面,因为以往的经历都需要对连接数据库进行一个封装,里面包含有数据库的连接,记录的添加,查询,修改和删除等操作,每次使用的过程中都需要先实现一个连接对象然后

虚基类练习:动物(利用虚基类建立一个类的多重继承,包括动物(animal,属性有体长,体重和性别),陆生动物(ter_animal,属性增加了奔跑速度),水生动物(aqu_animal,属性增加了游泳速度)和两栖动物(amp_animal)。)

Description 长期的物种进化使两栖动物既能活跃在陆地上,又能游动于水中.利用虚基类建立一个类的多重继承,包括动物(animal,属性有体长,体重和性别),陆生动物(ter_animal,属性增加了奔跑速度),水生动物(aqu_animal,属性增加了游泳速度)和两栖动物(amp_animal).其中两栖动物保留了陆生动物和水生动物的属性. Input 两栖动物的体长,体重,性别,游泳速度,奔跑速度(running_speed) Output 初始化的两栖动物的体长,体重,性别,游泳速度