-
erlang tcp发包速度测试
这段时间我们的项目遇到广播包的一些性能问题,想起之前看到yufeng老大提到的1s广播40K包的问题,我也想测试测试我们机器的IO能力。
这次仅仅测试发包的能力,采用的是一对一的方式。
测试代码: Read More »
没有评论 -
Erlang中计算16位的MD5字符串
erlang的bif中自带了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(X) end, L).
int_to_hex(N) when N < 256 ->
[hex(N div 16), hex(N rem 16)].
hex(N) when N < 10 ->
$0+N;
hex(N) when N >= 10, N < 16 ->
$a + (N-10).
英文链接 http://sacharya.com/md5-in-erlang/
-
Erlang中粘包处理
开始时用的传统思路(循环读取):
recv(ClientSock, PacketLenOld, Remain)
when is_integer(PacketLenOld) and is_binary(Remain) ->
case gen_tcp:recv(ClientSock, 0) of
{ok, B} ->
Bin = <<Remain/binary, B/binary>>,
%% read the packet length
if PacketLenOld =:= 0 andalso erlang:byte_size(Bin) > 2
-> <<PacketLen:16, Remain2/binary>> = Bin;
true -> Remain2 = Bin, PacketLen = PacketLenOld
end,
?DEBUG("packet length ~p", [PacketLen]),
if
erlang:byte_size(Remain2) >= PacketLen
-> {RealData, Next} = split_binary(Remain2, PacketLen),
MainData = decode(RealData),
{ok, MainData, 0, Next};
true -> {continue, PacketLen, Remain2}
end;
{error, closed} ->
?DEBUG("socket closed ~p ~n", [ClientSock]),
{error, closed};
{error, Reason} ->
?ERROR_MSG("socket closed ~p with reason: ~p ~n", [ClientSock, Reason]),
{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(ClientSock, 2) of
{ok, PacketLenBin} -> <<PacketLen:16>> = PacketLenBin,
case gen_tcp:recv(ClientSock, PacketLen) of
{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.
-
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 More »
-
rabbitmq代码摘录(1)
诸多erlang应用都是基于erlang现有的一些application,rabbitmq也不例外,在rabbitmq中,需要的application有sasl、os_mon、mnesia。而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(Iterate, Do, Undo, SkipError, ErrorTag, Apps) ->
Iterate(fun (App, Acc) ->
case Do(App) of
ok -> [App | Acc];
{error, {SkipError, _}} -> Acc;
{error, Reason} ->
lists:foreach(Undo, Acc),
throw({error, {ErrorTag, App, Reason}})
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中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(1, 10) > 0){
return $a + $b;
}
}
function except($a, $b)
{
try {
if (mt_rand(1, 10) > 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(1, 1);
}
echo microtime(true) - $begin;
echo "\r\n";
echo "2. with exception, time is:";
$begin = microtime(true);
for ($i=0; $i< T; $i++)
{
except(1, 1);
}
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还要流畅。
-
本地Service browser中调试amfphp注意一则
注意关闭本地web服务器的keepalive功能,否则可能会出现刚刚修改的代码要隔断时间才能失效的问题。目前只在apache环境下发现这个问题。
-
PHP扩展之自定义全局变量
跟踪了一下PHP中$_GET、$_POST的产生过程,发现通过zend提供的函数和宏可以很方便注册自己的全局数组。相关的函数和宏:
END_API int zend_register_auto_global(
char *name, //全局数组名
uint name_len, //数组名称长度- 1
zend_auto_global_callback auto_global_callback TSRMLS_DC //数组初始化回调函数
);
#define ZEND_SET_SYMBOL(symtable, name, var) \
{ \
char *_name = (name); \
\
ZEND_SET_SYMBOL_WITH_LENGTH(symtable, _name, strlen(_name)+1, var, 1, 0); \
}
下面来注册我们的全局变量,假设我们的扩展名为test,我们在MINIT中进行注册操作。
zend_bool ming_global_callback(char *name, uint name_len TSRMLS_DC)
{
zval *tmp;
MAKE_STD_ZVAL(tmp);
array_init(tmp);
add_next_index_long(tmp,2222);
ZEND_SET_SYMBOL(&EG(symbol_table), name, tmp);
}
PHP_MINIT_FUNCTION(test)
{
/* If you have INI entries, uncomment these lines
REGISTER_INI_ENTRIES();
*/
zend_register_auto_global("_MING", sizeof("_MING") - 1, ming_global_callback TSRMLS_DC);
return SUCCESS;
}
运行PHP代码
<?php
var_dump($_MING);
结果:
array(1) {
[0]=>
int(2222)
}
-
xampp下 Pear安装出错Call to undefined method PEAR_Error::set()
简单的解决办法:删除PHP文件夹下的php.ini
-
PHP源代码分析之HashTable
从PHP的zval结构体可以看出PHP使用HashTable来保存数组信息,PHP的HashTable使用了一些技巧,这些技巧是PHP高效数组操作的直接原因,源代码在PHP源代码目录的Zend/zend_hash.h Zend/zend_hash.c 中。先来看看Zend HashTable的定义:
.png)
-
PHP源代码分析资料收集
在PHP源代码分析的过程参考了不少优秀的相关资料,而很多资料由于各种原因在网上慢慢的就找不到了(例如www.phpinternals.com 这个网站是有不少优秀的文章可以参考,但最近才发现blog已经关闭了),所以就把一些资料罗列出来给大家。
版权信息在文件里面都已经包含了,我就不重复了。
PDFs:
1 the-php-life-cycle 讲解PHP生命周期的,web server以Apache为例
2. Sams.Extending.and.Embedding.PHP.May.2006 这个不用说了,经典!
3. sara_golemon-tutorial_extension_writing 包括的内容非常广
4. php_extension_writing (OSCON 2007上的PPT)
SITEs:
1. http://cn.php.net/manual/en/internals2.php PHP core
2. http://devzone.zend.com/tag/Extension
3. http://www.yanbin.org/ 抚琴居
4. http://www.laruence.com/ 风雪之隅
有优秀的资料,麻烦跟我推荐一下
-
PHP源代码分析之变量
在PHP中所有变量都使用zval结构体来存放:
.png)
.png)
在PHP中可以使用函数 debug_zval_dump($var); 查看变量的引用信息。
相对于PHP的内核而已,我们编写的PHP代码都属于“用户空间”(user space),用户空间中的任何PHP变量都是由两部分组成:变量名(label)和变量值,从上面已经看到变量值存放在zval结构体中,那么变量名是放在哪里的呢? 下篇将继续分析PHP的HashTable结构体。
说明:本文中的图片均截自Marcus BörgerWez, FurlongSara, Golemon 三人的PHP ENTENSION WRITING (OSCON 2007)
在PHP 5.2.6中源码稍有不同,不过含义一样,无关大雅。
refcount用来表示有多少个变量指向本结构体,is_ref用来标示是否是引用。看两个例子:
$a = 5;
$b = $a;
$b = 10;
$a = 5 => value.lval = 5, refcount = 1, type = IS_LONG, is_ref = 0
$b = $a => value.lval = 5, refcount = 2, type = IS_LONG, is_ref = 0
$b = 10 => 1 value.lval = 5, refcount = 1, type = IS_LONG, is_ref = 0 $a
2 value.lval = 10, refcount = 1, type = IS_LONG, is_ref = 0 $b
在第三步时,PHP又产生了一个新的结构体用于保存变量$b, 原因在于原来$b指向的结构体的is_ref 成员的值为0. 这就是PHP的Copy on Write机制。
再看下一种情况:
$a = 123;
$b = &$a;
$b = 456;
则按下图保存
-
PHP源代码分析之PHP生命周期
无论PHP通过何种方式启动,其初始化、响应单个请求、代码编译运行、结束请求、卸载过程都是相同的。
1.进程初始化

在模块的MINIT过程中可以添加你自定义的常量、变量、类、资源、流以及Filter句柄等等。
2.接受请求
3.解析编译运行代码
Zend Engine首先将代码编译成Zend Opcode,然后再使用Zend虚拟机来解释执行。
4.请求结束
.png)
5.进程退出
.png)
-
Linux之路 — SSH篇
需要的windows软件:SecureCRT,WinSCP
一、前言
即使Linux本身的安全性已经相当好,我们仍然需要在实际操作中关注某些安全要点。目前大部分的Linux管理都采用远程控制来进行,如果保证远程控制中数据的安全是一个合格的linux管理员必须熟悉的技能。
各种黑客行为、尝试给我们的网络带来了大量的破坏,但不可否认这些行为和尝试也给计算机安全带来了极大的促进。从理论上来说,网络传输中任何对称加密算法都是不安全的,所以我们在日常的linux管理中应该采用非对称加密算法来进行权限验证。SSH是一种加密传输数据的方式(不同于telnet等的明文数据传输),是目前最通用的linux远程安全控制方案,它提供两种认证方式:密码认证和密匙认证。关于非对称加密的相关知识请看 http://baike.baidu.com/view/554866.htm
本文以Centos 5.3 为例并假设你已经有一个安装好的Linux主机或者虚拟机,我这里采用的是虚拟机。 Read More »
-
Linux之路 — 工具准备篇:SecureCRT配色显示
SecureCRT的配置功能非常强大,可以完全的显示Linux下的颜色显示。设置如下:
会话设置

选择Xterm

选择颜色方案

全局配置

修改颜色,文件目录和文件中注释默认显示为深蓝色,看起来相当的吃力

我选择修改为兰色,你可以根据自己的喜好修改

链接终端, # vim /etc/ssh/sshd_config
vim 下键入syntax enable,打开语法着色功能。效果如下:

如果没有显示出颜色,而且你确认你的终端支持颜色显示,请先退出VIM,输入如下命令:
TERM=xterm-color; export TREM
用于告诉VIM你的终端是支持颜色显示的。最后,祝你有个愉快的Linux之旅。
-
Centos 5下默认网关设置
Centos/Fedora下都有多种方法可以设置默认网关,即使是配置文件也有多处。以前感觉的是方便,今天感觉却是郁闷。描述一下情况:
本地虚拟机中安装了个Centos 5.2,安装过程填网关时输错,之后虚拟机中一直无法ping通外部网络,通过route add default gw 192.168.159.2命令添加后可ping通,但是重启后失效。之后直接写配置文件/etc/sysconfig/network,添加 GATEWAY 192.168.158.2,但是奇怪的是依然无法ping通(网络服务、机器均重启)。 没办法只好直接在/etc/sysconfig/network-scripts/ifcfg-eth0中添加GATEWAY 192.168.158.2,重启,OK!
猜测是其他地方的配置文件设置的依然是错误的网关配置,而且优先级大于/etc/sysconfig/network中的配置。但是没有找到这个文件,有知道的麻烦指点一下。
-
su后“不能”使用某些超级命令的解决
一个基础问题而已。从普通用户使用su之后,某些命令无法使用,如:
bash: usermod: command not found
命令存在,也有了root权限,为何提示“命令找不到”,想一想就明白了是环境变量的问题(PATH)。man su,第一个参数告诉了我们真相。
-, -l, –login
make the shell a login shell使用这个选项用于在su的同时(成功的情况下)更换到对应用户的shell,也就是说正常情况下,我们su之后只是获得了root权限,但是shell还是之前的普通权限用户的shell,而普通用户shell的PATH通常是没有/usr/sbin等目录的。解决方法:
1.添加这些超级工具目录到PATH
2.使用su – 来切换到root权限
3.使用命令的完全路径,如/usr/sbin/usermod
-
读 《构建可扩展的Web站点》笔记
从目录中就可以看出来, 这是一本超越纯粹代码范畴的书. 涉及到开发工具, 开发方法, 开发过程, 体系结构, 应用分层, 常用web功能举例和注意事项, 性能瓶颈, 扩展并提出一些解决方法, 最后还涉及到性能的监控方法.
扩展Web应用程序
一、概念
简单的来说,如果一个系统可扩展,那么你可以通过扩展来提供系统的性能。这代表着系统能够容纳更高的负载、更大的数据集,并且系统是可维护的。扩展和语言、某项具体的技术都是无关的。扩展可以分为两种:
1. 垂直扩展(stade up),通俗的说就是将某台单一的机器的性能提升的更高,如添加内存、更换更强的处理器等等。
2. 水平扩展(out),通俗的说就是添加新的机器。
对比可以发现,水平扩展比垂直扩展有更强大的扩展性,可以说是“无限”扩展,毕竟单台的机器的性能总是有限的,硬件的技术发展还赶不上web的发展。但同时,水平扩展也来了更高的维护成本。实际中,需要根据具体情况来寻求一个平衡点。 Read More »
-
折腾了许久WP,终于找到了比较好的高亮方案
WP固然强大,但是其编辑器一直是比较鸡肋的。今晚折腾了挺久终于放弃了WP自带的编辑器,而改用强大的FCK。之后就可以不使用代码高亮插件了,方法如下:
1.本地将IDE编写的代码复制进WORD
2.拷贝WORD的代码,如浏览器有访问剪切板的提示则选择允许,OK,代码高亮了。
限制:某些IDE的代码拷贝到WORD后颜色会丢失(基于Java开发的貌似都不会,而DW之内的则会丢失)