Erlang

erlang tcp发包速度测试

 

这段时间我们的项目遇到广播包的一些性能问题,想起之前看到yufeng老大提到的1s广播40K包的问题,我也想测试测试我们机器的IO能力。

这次仅仅测试发包的能力,采用的是一对一的方式。

测试代码: READ THE FULL ARTICLE >>

Erlang

Erlang中计算16位的MD5字符串

 

erlangbif中自带了md5计算函数,但是结果却是二进制的,即使转成list,也是10进制表示,google了一下得到一段代码用于获得字符串形式的md5结果(16位):

md5(S) ->        

Md5_bin =  erlang:md5(S), 

Md5_list = binary_to_list(Md5_bin), 

lists:flatten(list_to_hex(Md5_list)). 

 

list_to_hex(L) -> 

lists:map(fun(X) -> int_to_hex(XendL). 

 

int_to_hex(Nwhen N < 256 -> 

[hex(N div 16), hex(N rem 16)]. 

hex(Nwhen N < 10 -> 

       $0+N

hex(Nwhen N >= 10N < 16 ->      

$a + (N-10).

英文链接  http://sacharya.com/md5-in-erlang/

Erlang

Erlang中粘包处理

 

开始时用的传统思路(循环读取):

recv(ClientSockPacketLenOldRemain

  when is_integer(PacketLenOldand is_binary(Remain) ->

case gen_tcp:recv(ClientSock0of

{ok, B} ->

Bin = <<Remain/binary, B/binary>>,

%% read the packet length

if PacketLenOld =:= 0 andalso erlang:byte_size(Bin) > 2

 -> <<PacketLen:16Remain2/binary>> = Bin;

   true -> Remain2 = BinPacketLen = PacketLenOld

end,

?DEBUG("packet length ~p", [PacketLen]),

if 

erlang:byte_size(Remain2) >= PacketLen

  -> {RealDataNext} = split_binary(Remain2PacketLen),

 MainData = decode(RealData),

 {ok, MainData0Next};

true -> {continue, PacketLenRemain2}

end;

{error, closed} ->

?DEBUG("socket closed ~p ~n", [ClientSock]),

{error, closed};

{error, Reason} ->

?ERROR_MSG("socket closed ~p with reason: ~p ~n", [ClientSockReason]),

{error, Reason}

end.

翻了翻文档发现实际上在erlang中没有必要这样麻烦

The Length argument is only meaningful when the socket is in raw mode and denotes the number of bytes to read. 

If Length = 0, all available bytes are returned. If Length > 0, exactly Length bytes are returned, or an error;

recv(ClientSock) ->

case gen_tcp:recv(ClientSock2of

{ok, PacketLenBin} -> <<PacketLen:16>> = PacketLenBin,

case gen_tcp:recv(ClientSockPacketLenof

{ok, RealData} ->

?DEBUG("recv data ~p", [RealData]),

{ok, decode(RealData)};

{error, Reason} ->

?ERROR_MSG("read packet data failed with reason: ~p", [Reason]),

{error, Reason}

end;

{error, Reason} -> 

?ERROR_MSG("read packet length failed with reason: ~p", [Reason]),

{error, Reason}

end.

Erlang

OTP中supervisor启动过程

 

rabbit_sup模块开始看起:

rabbit_sup模块的start_link是被rabbit app模块的start/2方法所调用的

rabbit.erl文件:

start(normal, []) ->

{ok, SupPid} = rabbit_sup:start_link(),

rabbit_sup.erl文件:

-define(SERVER?MODULE).

start_link() ->

supervisor:start_link({local, ?SERVER}, ?MODULE, []).

这里的?SERVER和?MODULE是一样的值,都为rabbit_sup 。 READ THE FULL ARTICLE >>

Erlang

rabbitmq代码摘录(1)

 

诸多erlang应用都是基于erlang现有的一些applicationrabbitmq也不例外,在rabbitmq中,需要的applicationsaslos_monmnesia。而rabbitmq启动这些application(包括其自身)的代码写的相当的巧妙:(源码基于rabbitmq 1.7.0

文件 rabbit.erl

-define(APPS, [os_mon, mnesia, rabbit]).

start() ->

    try

        ok = prepare(),

        ok = rabbit_misc:start_applications(?APPS

    after

        %%give the error loggers some time to catch up

        timer:sleep(100)

    end.

stop() ->

    ok = rabbit_misc:stop_applications(?APPS).

文件 rabbit_misc.erl

manage_applications(IterateDoUndoSkipErrorErrorTagApps) ->

    Iterate(fun (AppAcc) ->

                    case Do(Appof

                        ok -> [App | Acc];

                        {error, {SkipError_}} -> Acc;

                        {error, Reason} ->

                            lists:foreach(UndoAcc),

                            throw({error, {ErrorTagAppReason}})

                    end

            end, [], Apps),

    ok.

start_applications(Apps) ->

    manage_applications(fun lists:foldl/3,

                        fun application:start/1,

                        fun application:stop/1,

                        already_started,

                        cannot_start_application,

                        Apps).

stop_applications(Apps) ->

    manage_applications(fun lists:foldr/3,

                        fun application:stop/1,

                        fun application:start/1,

                        not_started,

                        cannot_stop_application,

                        Apps).

顺序启动或者关闭几个application,在失败的情况下首先判断操作失败的原因,如果是已经启动或者已经停止,则跳过;如果是启动失败或者停止失败,则先依次停止或者启动之前已经操作成功的application,之后抛出异常结束进程。

PHP高级应用

PHP中Exception性能简单测试及结论

关于是否使用exception风格(个人的说法,也就是非正常的返回值都以抛异常的形式返回)来编码,我产生了一些疑问,经过和同事的一些讨论,我决定做些简单的性能测试。

<?php

/**

 * Exception 简单的性能测试

 * @author Qingliang.Cn  qing.liang.cn@gmail.com

 * @created 2009-11-18 

 * @lastmodified 2009-11-18

 */

define(‘T’1000000);

function no_except($a$b)

{

    if (mt_rand(110) > 0){

        return $a $b;

    }

}

function except($a$b)

{

    try {

        if (mt_rand(110) > 5){ //  0.5的概率抛出异常

            return $a $b;

        }else{

            throw new Exception(1);

        }

    }catch (Exception $e){

        return $e->getMessage();

    }

}

echo "1. with no exception, time is:";

$begin = microtime(true);

for ($i=0$i< T; $i++)

{

    no_except(11);

}

echo microtime(true) - $begin;

echo "\r\n";

echo "2. with exception, time is:";

$begin = microtime(true);

for ($i=0$i< T; $i++)

{

    except(11);

}

echo microtime(true) - $begin;

echo "\r\n";

结果:

100000 (10W)

1. with no exception, time is:3.2554759979248

2. with exception, time is:4.2815051078796

1000000(100W)

1. with no exception, time is:31.89279794693

2. with exception, time is:39.047714948654

上面的测试结果可以看出消耗的时间是相当稳定的,直接的结果是exception比直接return要慢。 

继续分析

抛出异常的概率为0.5,也就是说:50w次的异常处理导致了11秒的性能损失。每次exception处理的消耗大概是 20 微秒,这个消耗是相当的小的。 因为一般情况下,web请求的时间都是ms级别的。

同时这里还有两点需要注意:

1. 没有使用异常的时候,代码中的逻辑判断分值必然会加多,也是一定的消耗。

2. 多数的程序exception命中率不会如上面代码中那么高(50%)。

所以在PHP中应用exception是不需要考虑性能问题的。

如有不同的观点,欢迎拍砖和讨论。 email: qing.liang.cn at gmail.com

暂未分类

Windows7试用

这几天折腾了一下Windows7,总体的感觉不错。从体验上来说,各方面的设置都和XP类似,即使是有变化也是过渡的非常平稳。唯一感觉不太好的是Windows7的画面感觉不太舒服,看起来非常的累,我的显卡是蓝宝4830的,应该不是卡的问题,舍友安装后也觉得电影的画面看起来有格子的感觉,可能是驱动的问题。

可能是因为我刚换的4核CPU,感觉windows7的操作似乎比xp还要流畅。

Flex

本地Service browser中调试amfphp注意一则

注意关闭本地web服务器的keepalive功能,否则可能会出现刚刚修改的代码要隔断时间才能失效的问题。目前只在apache环境下发现这个问题。