该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-07-31
见附件的图 但是你仔细看下他的测试方式What do we measure and how?We use a 16 node cluster running at SICS. We plot throughput vs. parallel load.
这个比较是非常不公平的 apache的链接处理机制是 开线程或者进程来处理请求 按它的测试方法 你非常慢速的8w请求 导致apache开大量的线程来处理。而能开多少线程取决于操作系统的能力 这还是其次 大量的线程处理活跃的链接导致大量的thread content switch。 apache 挂了不奇怪。 而erlang的线程相大于c语言的一个数据结构 erl_process你开多少取决于你的内存 大量的但是慢速的链接刚好适合poll事件dispatch, 以epoll的能力(俺测试过epoll30w)能够轻松处理。 这个测试与其说测试web服务器的性能 不如说 测试服务器的进程生成能力。 俺的测试是这样的:../yaws --conf yaws.conf --erlarg "+K true +P 1024000" #epoll 最多1024000个进程 内核都已经调优过 yaws.conf 的内容: auth_log = false max_num_cached_files = 8000 max_num_cached_bytes = 6000000 <server test_yaws=""></server> 大家都用 ab -c 1000 -n 1000000 http://192.168.0.98:8000/bomb.gif 来测 果然发现yaws的性能也是非常一般 大概也就是3K左右. 各位看下 strace 的结果就知道了: accept(10, {sa_family=AF_INET, sin_port=htons(5644), sin_addr=inet_addr("192.168.0.97")}, [16]) = 11fcntl64(11, F_GETFL) = 0x2 (flags O_RDWR) fcntl64(11, F_SETFL, O_RDWR|O_NONBLOCK) = 0 getsockopt(10, SOL_TCP, TCP_NODELAY, [0], [4]) = 0 getsockopt(10, SOL_SOCKET, SO_KEEPALIVE, [0], [4]) = 0 getsockopt(10, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 getsockopt(10, SOL_IP, IP_TOS, [0], [4]) = 0 getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 setsockopt(11, SOL_IP, IP_TOS, [0], 4) = 0 setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 setsockopt(11, SOL_SOCKET, SO_KEEPALIVE, [0], 4) = 0 setsockopt(11, SOL_IP, IP_TOS, [0], 4) = 0 setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 setsockopt(11, SOL_TCP, TCP_NODELAY, [0], 4) = 0 setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 recv(11, "GET /bomb.gif HTTP/1.0\r\nUser-Age"..., 8192, 0) = 100 getpeername(11, {sa_family=AF_INET, sin_port=htons(5644), sin_addr=inet_addr("192.168.0.97")}, [16]) = 0 clock_gettime(CLOCK_MONOTONIC, {110242, 326908594}) = 0 stat64("/var/www/html/bomb.gif", {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0 access("/var/www/html/bomb.gif", R_OK) = 0 access("/var/www/html/bomb.gif", W_OK) = 0 clock_gettime(CLOCK_MONOTONIC, {110242, 327135982}) = 0 time(NULL) = 1185894828 clock_gettime(CLOCK_MONOTONIC, {110242, 327222643}) = 0 stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=405, ...}) = 0 writev(11, [{NULL, 0}, {"HTTP/1.1 200 OK\r\nConnection: clo"..., 231}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"... , 4096}], 3) = 4327 close(11 这里面充斥着大量的无用的昂贵的系统调用 (至少有20个*10us = 200us 的系统调用是无效的) 对文件的access 2 次 连文件的cache都没有 每次 打开文件 读文件 然后写到socket去 。 这个case是小文件(4k)的情况。 看下大文件(40k)的情况 open("/var/www/html/bomb.gif", O_RDONLY|O_LARGEFILE) = 19 大量的epoll_ctl 调用 clock_gettime的调用 足够让系统的速度变的非常慢。 比对下lighttpd的性能。 lighttpd用到了cache,用到了aio,还是完全用c语言小心编写, 他处理小文件大概是并发1w. 而yaws这个的处理方式打个3折我看差不多。 所以请各位大佬介绍erlang的性能时候不要 再用这个apache vs yaws的例子了 误导太多人了.
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-07-31
这么说 Erlang 是自己实现了线程机制, 自己调度的哦. 容量比操作系统提供的线程机制要大, 结果是并发数量高了不少, 不过单线程的效率注定要低些.
但是 Erlang 的线程调度应该和 CPU 硬件联系不紧密吧, 给一个比较高层次的语言实现一个软件线程机制确实相对要容易, 而且目前 CPU核心 还不是很多的情况下可能也能占不少便宜. 不过以后CPU核心数到上千的时候, 我觉得可能就比不过操作系统线程了. 但是目前 内存容量/CPU核心数 这个比例还是比较大, 严重并发的场合Erlang这种机制应该还是有用武之地吧. |
|
返回顶楼 | |
发表时间:2007-07-31
它说的是并发能力而不是性能,它的测试条件也很明确,16台机器,第1台跑WEB服务器,第2台用来做测试,其它服务器用来建立大量连接,但只是“makes a very slow request to fetch a one byte file from machine 1”,这就是故意造成高并发,但不是测试性能。在大量并发情况下,测试第2台读取页面的响应情况,这个图就是说明这个的,图上可以表明,erlang的软实时做得还是不错的,大量进程没有严重影响到单个进程,这个数量自己用线程+进程都是难以达到的。
erlang的优势就是高并发而非高性能,性能方面谁敢跟C比,erlang也是C写的内核。 |
|
返回顶楼 | |
发表时间:2007-07-31
erlang根本没有进程机制 就是简单的erl_process 结构 里面有message queue 在epoll返回的时候 把socket来的数据变形 然后放到process的queue里面去 再来个循环出来process里面的message而已。 和普通的event dispatch程序(如用libevent)的没有区别。
|
|
返回顶楼 | |
发表时间:2007-07-31
这样的并发俺的event dispatch的程序 单进程 单线程也能轻松达到10w哦
|
|
返回顶楼 | |
发表时间:2007-08-01
erts的1xw代码俺基本上已经读过一遍了 erlang的emulator实现总体来讲效能还是蛮高的 个人感觉erlang的优势在于dist和得益于fp语言特性的lockfree 和code hot replacement.
|
|
返回顶楼 | |
发表时间:2007-08-01
mryufeng 写道 这样的并发俺的event dispatch的程序 单进程 单线程也能轻松达到10w哦
即使是并发,erlang也不能和C相比,毕竟是C实现的。你自己实现这样一个当然是可以,不过如何把文件、数据库、网络调用都纳入到一个统一的框架中?erlang相当于完成了一个异步调用框架,所有符合它的规范的都可以融为一体,最终形成一个一致的界面。比如一个数据库调用模块,用C NODE方式,为了性能不受网络影响太大,需要使用一个线程池来完成调用。以后该数据库的接口升级了,支持异步调用了,就可以单个线程完成,对于这个C程序来说,修改相对比较小,因为它不面向具体业务。对于erlang来说,调用方式也没有改变,这正是最理想的方式嘛,想了N久没能力搞出来的东西。完全用erlang做项目我目前感觉不是特别必要,看中的是它的分布式和热代码替换。 对了,你上面strace抓的也太恐怖了,这么多重复的调用?很多调用看参数根本都是可以省略的,比如: setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 有种想扁人的感觉。。 |
|
返回顶楼 | |
发表时间:2007-08-01
erlang的driver机制还是单线程的event dispatch机制 只有在具体的driver使用async的时候才用线程池(也就是+A n)来辅助处理。async还是后来引进来的 所以erlang的emulator基本上就是一个事件反转的调用框架, 和 ACE和Reactor概念上是一样的。其实这个东西ACE作的也不错 但是ACE的抽象原语偏低,使用起来容易出错。
|
|
返回顶楼 | |
发表时间:2007-08-01
呼呼,有个文章说yaws做得还不够好
性能方面,俄罗斯的nginx服务器我自己测试下来是现在最快的,静态文件性能有apache2的两倍。有趣的是nginx也支持热配置更新和本身代码热更新,做法和erlang差不多:给master进程发信号说要升级拉,还在工作的worker继续,但别接新任务了等做完再更新,现在发呆着的worker马上更新然后等着去接新任务。 BTW, 楼主要小心别沾染标题党的“必看”恶习呵呵 |
|
返回顶楼 | |
发表时间:2007-08-01
mryufeng 写道 erlang根本没有进程机制 就是简单的erl_process 结构
说到底,操作系统所谓的Process和Thread 也只不过是一个Context结构,用指针保存每个Stack Frame,然后按时间片切换Context.有任何区别吗? 用最简单的stack_t ,sigaltstack和longjmp 就能做一个最简单的micro thread. |
|
返回顶楼 | |