Archive

Author Archive

R13B04在细化Binary heap

January 14th, 2010 2 comments

从github otp的更新日志可以清楚的看到otp R13B04在binary heap的细化上做了很多工作:

1. 提供参数 限制binary的最小limit.

2. binary_to_term 加多参数来保证安全, 对于外来binary解码的安全性检查 比如说 避免atom的滥用.

3. 更高效率的处理binary fragment.

4. 加强GC对binary碎片的回收操作.

这个对于服务器性能很大帮助.

Categories: Erlang探索 Tags: , ,

R13B03 binary vheap有助减少binary内存压力

November 29th, 2009 Comments off

R13B03 binary vheap有助减少binary内存压力.

参看:http://www.erlang.org/download/otp_src_R13B03.readme

OTP-8202 A new garbage collecting strategy for binaries which is more
aggressive than the previous implementation. Binaries now has
a virtual binary heap tied to each process. When binaries are
created or received to a process it will check if the heap
limit has been reached and if a reclaim should be done. This
imitates the behavior of ordinary Erlang terms. The virtual
heaps are grown and shrunk like ordinary heaps. This will
lessen the memory footprint of binaries in a system.

原来的binary和其他类型的eterm是混在一起的,当进程的heap用完的时候,才进行GC,腾出空间。现在是把binary单独抽取出来,单独计数, 当binary用量过大的时候,马上就GC。

这个策略对于我们的服务器程序很有帮助,因为我们的服务器程序基本上包都是binary, 很容易出现binary无法及时回收,导致内存耗光的情况。

具体的改进效果待进一步的观察。

Categories: Erlang探索 Tags: , ,

erl_nif Erlang的ffi 扩展erlang的另外一种方法

November 26th, 2009 11 comments

我们知道扩展erl有2种方法, driver和port. 这2个方法效率都低,因为都要经过 port机制,对于简单的模块,这个开销有时候是不可接受的。这时候nif来救助了。今天发布的R13B03已经支持了,虽然是实验性质的。 erl_nif的代表API functions for an Erlang NIF library。 参考文档:
erl_nif.html 和 erlang.html#erlang:load_nif-2 以及 reference_manual/code_loading.html#id2278318 。

我们来用nif写个最简单的hello, 来展现nif的威力和简单性。
不啰嗦,直接上代码:

root@nd-desktop:~/niftest# cat niftest.c
/* niftest.c */
#include "erl_nif.h"
static ERL_NIF_TERM hello(ErlNifEnv* env)
{
return enif_make_string(env, "Hello world!");
}
static ErlNifFunc nif_funcs[] =
{
{"hello", 0, hello}
};
ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)
root@nd-desktop:~/niftest# cat niftest.erl
-module(niftest).
%-on_load(init/0).
-export([init/0, hello/0]).
init() ->
ok=erlang:load_nif("./niftest", 0), true.
hello() ->
"NIF library not loaded".

编译:

root@nd-desktop:~/niftest# gcc -fPIC -shared -o niftest.so niftest.c -I   /usr/local/lib/erlang/usr/include  #你的erl_nif.h路径

运行:

root@nd-desktop:~/niftest# erl
Erlang R13B03 (erts-5.7.4) [source][/source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]</code>

Eshell V5.7.4  (abort with ^G)
1> c(niftest).
{ok,niftest}
2> niftest:hello().
"NIF library not loaded"
3> niftest:init().
ok
4> niftest:hello().
"Hello world!"
5>

现在重新修改下 niftest.erl 把on_load的注释去掉

root@nd-desktop:~/niftest# erl
Erlang R13B03 (erts-5.7.4) [source][/source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]</code>

Eshell V5.7.4  (abort with ^G)
1&gt; c(niftest).
{ok,niftest}
2&gt; niftest:hello().
"Hello world!"
3&gt;

综述: nbif很简单,而且高效。

Categories: Erlang探索 Tags:

escript的高级特性

November 25th, 2009 7 comments

escript Erlang scripting support, 可以让erl模块转身变成unix script来使用,大大方便用户,具体的使用参看otp文档。我这里要演示的是些比较被忽视的高级特性:

首先crack erts/etc/common/escript.c:33 static int debug = 1; 让之显示调用参数。

root@nd-desktop:~# cat &gt;factorial
[color=red]#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable -sname factorial -mnesia debug verbose[/color]
main([String]) ->
try
N = list_to_integer(String),
F = fac(N),
io:format("factorial ~w = ~w\n", [N,F])
catch
_:_ ->
usage()
end;
main(_) ->
usage().

usage() ->
io:format("usage: factorial integer\n"),
halt(1).

fac(0) -> 1;
fac(N) -> N * fac(N-1).

CTRL+D

root@nd-desktop:~# chmod +x factorial
root@nd-desktop:~# ./factorial  10

[color=red]erl +B -boot start_clean -noshell -smp enable -sname factorial -mnesia debug verbose -run escript start -extra ./factorial 10[/color]
factorial 10 = 3628800

特性1:

摘抄文档。。。
On the third line (or second line depending on the presence of the Emacs directive), it is possible to give arguments to the emulator, such as

%%! -smp enable -sname factorial -mnesia debug verbose

Such an argument line must start with %%! and the rest of the line will interpreted as arguments to the emulator.

我们可以看到 这些选项被传递给了 erl

特性2:
-mode(compile).

这个选项是在escript.erl这个模块处理的。默认情况下 escript是被解释执行的,如果你的脚本很复杂,那么效率估计会是瓶颈。这种情况下, 你可以通过这个选项来让escript来先编译你的模块成opcode, 在vm里面运行。

特性3:
-d 选项 用来调试script的
-c 编译执行
-i 解释执行
-s 只检查不执行
root@nd-desktop:~# escript -d ./factorial 10
我们就可以看到 调试界面如下图
escript_debug

特性4:
可以把一个beam文件作为script

root@nd-desktop:/usr/src# cat hello.erl
-module(hello).
-export([start/0,main/1]).

main(_)->
start().

start()->
io:format("hello world~n",[]).
root@nd-desktop:/usr/src# erlc hello.erl
root@nd-desktop:/usr/src# cat &gt;hello
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable -sname factorial -mnesia debug verbose

CTRL+D

root@nd-desktop:/usr/src# cat hello.beam &gt;&gt;hello
root@nd-desktop:/usr/src# chmod +x hello
root@nd-desktop:/usr/src# ./hello
hello world

特性5:
可以把一个zip文件作为script

root@nd-desktop:/usr/src# cat hello.erl
-module(hello).
-export([start/0,main/1]).

main(_)->
start().

start()->
io:format("hello world, fac(10)=~w ~n",[fac:fac(10)]).
root@nd-desktop:/usr/src# cat fac.erl
-module(fac).
-export([fac/1]).

fac(0) ->
1;
fac(N) -> N * fac(N-1).
root@nd-desktop:/usr/src# erlc *.erl
root@nd-desktop:/usr/src# erl
Erlang R13B03 (erts-5.7.4)
[smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4  (abort with ^G)
1&gt; zip:zip("hello.zip", ["hello.beam", "fac.beam"]).
{ok,"hello.zip"}
2&gt;
root@nd-desktop:/usr/src# cat &gt;hello
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable -sname factorial -mnesia debug verbose -escript main hello

CTRL+D

root@nd-desktop:/usr/src# cat hello.zip &gt;&gt;hello
root@nd-desktop:/usr/src# chmod +x hello
root@nd-desktop:/usr/src# ./hello
hello world, fac(10)=3628800

特性6:
在独立的包里面 把escript伪装成我们的应用程序

root@nd-desktop:/usr/src# cat &gt;hello.escript
-module(hello).
-export([start/0,main/1]).

main(_)->
start().

start()->
io:format("hello world~n",[]).

CTRL+D

root@nd-desktop:/usr/src#  cp `which escript` hello
root@nd-desktop:/usr/src# ./hello
hello world

规则是 escript 改名成xxxx 执行xxxx的时候 实际上要读取的脚本是 xxxx.escript

综述: escript是很强大的 未来的erlang standalone全靠它。

Categories: Erlang探索 Tags: , , , ,

erl命令行工具链的设计思路

November 25th, 2009 2 comments

erlang otp标准发布包里面的命令行工具都在bin目录下
dialyzer
erlc
escript
typer

erlang的这些命令行工具基本上都是erl模块的c的wrapper, 最后都是调用erl来运行相应的模块完成任务。

实验如下:

root@nd-desktop:~# touch test.erl

root@nd-desktop:~# erlc -d test.erl
 erl -noinput -mode minimal -boot start_clean -s erl_compile compile_cmdline @cwd /root @files test.erl

首先crack erts/etc/common/escript.c:33 static int debug = 1; 让之显示调用参数

root@nd-desktop:~# escript test.erl
 erl +B -boot start_clean -noshell -run escript start -extra test.erl

我们可以清楚的看到是如何调用相应的模块的。

那我们再看下 erl

root@nd-desktop:/usr/src/otp_src_R13B03# cat bin/erl
#!/bin/sh
#
# %CopyrightBegin%
# 
# Copyright Ericsson AB 1996-2009. All Rights Reserved.
# 
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
# 
# %CopyrightEnd%
#
ROOTDIR=/usr/src/otp_src_R13B03
BINDIR=$ROOTDIR/bin/i686-pc-linux-gnu
EMU=beam
PROGNAME=`echo $0 | sed 's/.*\///'`
export EMU
export ROOTDIR
export BINDIR
export PROGNAME
exec $BINDIR/erlexec ${1+"$@"}

这个erl程序其实是个shell script, 简单的设置下环境变量 然后调用erlexec来调用相应的VM。

但是为什么其他的都是binary程序, 唯独erl是script呢。 我能想出的唯一理由是: OTP team的人为了我们方便修改erl的行为 特地用脚本来写, 这样用户就可以很方便的定制erl.

如果我的猜测没错的话,那么erlang真的很细心。

Categories: Erlang探索 Tags: , ,

rlwrap方便行编辑

November 25th, 2009 6 comments

GNU libreadline 为行编辑提供了统一的接口和方便的编辑能力,在使用中感觉非常爽。但是不是所以的应用程序都使用了readline库来读取用户输入,大部分C程序只是简单的调用fgets。这样的程序在输入的时候非常痛苦。比如erl,为了移植性没用到readline,而是自己实现了类似readline那样的基本的行编辑,但是非常难用,例如不支持CTRL A, CTRL E等等。

这时候rlwrap来救助了。
rlwrap runs the specified command, intercepting user input in order to provide readline’s line editing, persistent history and completion.

简单的说 这个程序就是让不支持readline的程序也可以享用这个库的好处。

在ubuntu下只要简单的 apt-get -y install rlwrap 就安装好了

使用也很简单:

rlwrap cmd

比如 rlwrap erl 这样就可以在erl shell里面以熟悉的emacs按键快速输入,舒服哦。

在linux shell下还可以在.profile里面加入别名, 比如

alias erl='rlwrap erl'

那么就不露神色的修改了erl的行为。

PS. piboyeliu同学说:

新版本的要使用 rlwrap -a erl 才可以正确运行

Categories: 杂七杂八 Tags: , ,

Go lang的emacs mode设置

November 12th, 2009 5 comments

昨天新发布的Go还是很不错的,而且随机带了个emacs的模式 用起来很方便。

root@nd-desktop:/usr/src/golang# pwd
/usr/src/golang
root@nd-desktop:/usr/src/golang#  ls misc/emacs/
go-mode.el  go-mode-load.el

root@nd-desktop:/usr/src/golang# cp misc/emacs/*.el ~/.emacs.d

root@nd-desktop:/usr/src/golang# cat &gt;&gt; ~/.emacs
<code>(setq load-path (cons (expand-file-name "~/.emacs.d/") load-path))
(require 'go-mode-load)</code>

CTRL+D
搞定收工。

Categories: 杂七杂八 Tags: , ,