`
mryufeng
  • 浏览: 982255 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

质疑 apache和yaws的性能比较(必看)

阅读更多
http://www.sics.se/~joe/apachevsyaws.html 上比较yaws的性能 显示apache 4000就挂了 但是yaws 8w还在挺着。
见附件的图

但是你仔细看下他的测试方式

What do we measure and how?

We use a 16 node cluster running at SICS. We plot throughput vs. parallel load.

  • Machine 1 has a server (Apache or Yaws).
  • Machine 2 requests 20 KByte pages from machine 1. It does this in tight a loop requesting a new page as soon as it has received a page from the server. From this we derive a throughput figure, which is plotted in the horizontal scale on the graph. A typical value (800) means the throughput is 800 KBytes/sec.
  • Machines 3 to 16 generate load.

    Each machine starts a large number of parallel sessions.

    Each session makes a very slow request to fetch a one byte file from machine 1. This is done by sending very slow HTTP GET requests (we break up the GET requests and send them character at a time, with about ten seconds between each character)

这个比较是非常不公平的

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]) = 11
fcntl64(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
read(19, "\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"..., 10240) = 10240
writev(16, [{NULL, 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\0"..., 10240}], 2) = 10240
read(19, "\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"..., 10240) = 10240
writev(16, [{NULL, 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\0"..., 10240}], 2) = 10240
read(19, "\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"..., 10240) = 10240
writev(16, [{NULL, 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\0"..., 10240}], 2) = 10240
read(19, "\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"..., 10240) = 10240
writev(16, [{NULL, 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\0"..., 10240}], 2) = 7240
read(19, "", 10240)                     = 0
close(19)                               = 0
clock_gettime(CLOCK_MONOTONIC, {110574, 856508319}) = 0
epoll_ctl(3, EPOLL_CTL_DEL, 11, {0, {u32=11, u64=581990243524149259}}) = 0
epoll_ctl(3, EPOLL_CTL_DEL, 12, {0, {u32=12, u64=581990243524149260}}) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 16, {EPOLLOUT, {u32=16, u64=581990243524149264}}) = 0
epoll_wait(3, {}, 256, 0)               = 0
clock_gettime(CLOCK_MONOTONIC, {110574, 856677411}) = 0
clock_gettime(CLOCK_MONOTONIC, {110574, 856729274}) = 0

大量的epoll_ctl 调用 clock_gettime的调用 足够让系统的速度变的非常慢。


比对下lighttpd的性能。 lighttpd用到了cache,用到了aio,还是完全用c语言小心编写, 他处理小文件大概是并发1w.  而yaws这个的处理方式打个3折我看差不多。

所以请各位大佬介绍erlang的性能时候不要 再用这个apache vs yaws的例子了 误导太多人了.

 

  • 大小: 55.2 KB
分享到:
评论
21 楼 mryufeng 2007-08-01  
delay_send option的作用是 注册socket的写事件 当调用inet:send的时候不是马上调用系统sendv发送数据 而是先放到队列里面 等socket可写的时候 集中发出去 这样对改善服务器的吞吐量有很大帮助。
20 楼 qiezi 2007-08-01  
Trustno1 写道
是OTP库问题不是erlang本身的问题.
问题应该出在prim_inet里面.
...
不过你应该不用改动代码,直接使用async_accept/2即可跳过这段.

的确,直接用prim_inet:async_accept/2就没有这些调用了,一次accept变成这样了:
clock_gettime(CLOCK_MONOTONIC, {1293204, 894416432}) = 0
gettimeofday({1185954733, 787267}, NULL) = 0
accept(8, {sa_family=AF_INET, sin_port=htons(37370), sin_addr=inet_addr("127.0.0.1")}, [16]) = 9
fcntl64(9, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(9, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
write(0, "Socket #Port<0.122> connected\r\n", 31) = 31
clock_gettime(CLOCK_MONOTONIC, {1293204, 894949432}) = 0
accept(8, 0xbffff1c0, [28])             = -1 EAGAIN (Resource temporarily unavailable)
recv(9, 0xb7d03180, 1024, 0)            = -1 EAGAIN (Resource temporarily unavailable)
clock_gettime(CLOCK_MONOTONIC, {1293204, 895342432}) = 0
epoll_ctl(3, EPOLL_CTL_DEL, 8, {EPOLLIN, {u32=8, u64=8589934600}}) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 8, {EPOLLIN, {u32=8, u64=8589934600}}) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN, {u32=9, u64=8589934601}}) = 0
epoll_wait(3, 


{{EPOLLIN, {u32=9, u64=8589934601}}}, 256, 3575743) = 1
clock_gettime(CLOCK_MONOTONIC, {1293232, 316418432}) = 0
gettimeofday({1185954761, 209266}, NULL) = 0
recv(9, "11\r\n", 1024, 0)              = 4
clock_gettime(CLOCK_MONOTONIC, {1293232, 316673432}) = 0
epoll_wait(3, 

后面一半是prim_inet:recv调用。

mryufeng 写道

不单单是 setsockopt 或者 getsockopt有问题 这个倒好 因为是一次性的开销 毕竟一个连接才做一次你看下clock_gettime epoll_ctl也是无厘头的调用,这也问题不是很大,最大的问题是 read write反复调用这个才是大头 不过这个也可以用delay_send option来避免。所有这个erlang是有很多细节可以微调的,只有把这些问题都处理掉了,性能才会提升。


clock_gettime可能是receive或其它超时参数的负作用吧,虽然没设超时,但它并没有判断后减少这个调用。

上面这个epoll_ctl只是多了个del/add,也还说得过去,毕竟你的接收进程循环就是这么写的,如果你不想再accept,它还是放在epoll里面就多此一举了,增加了不必要的事件,如果不处理这些事件,但又让它停留在epoll里面,epoll_wait总是马上返回,这会让CPU占用非常高的。ACE的多线程reactor在处理一个socket的事件时,也会把这个socket从select/epoll中拿掉,防止多个线程操作同一个socket。这里情况稍有不同,实际上相当于是proactor的实现,需要读时发一个读请求,不需要时就把事件注册给取消掉了。
19 楼 mryufeng 2007-08-01  
不单单是 setsockopt 或者 getsockopt有问题 这个倒好 因为是一次性的开销 毕竟一个连接才做一次 你看下clock_gettime epoll_ctl也是无厘头的调用,这也问题不是很大,最大的问题是 read write反复调用 这个才是大头 不过这个也可以用delay_send option来避免。 所有这个erlang是有很多细节可以微调的,只有把这些问题都处理掉了,性能才会提升。
18 楼 Trustno1 2007-08-01  
是OTP库问题不是erlang本身的问题.
问题应该出在prim_inet里面.

accept0(L, Time) when port(L), integer(Time) ->
    case async_accept(L, Time) of
{ok, Ref} ->
    receive
{inet_async, L, Ref, {ok,S}} ->
    accept_opts(L, S);
{inet_async, L, Ref, Error} ->
    Error
    end;
Error -> Error
    end.

%% setup options from listen socket on the connected socket
accept_opts(L, S) ->
    case getopts(L, [active, nodelay, keepalive, delay_send, priority, tos]) of
{ok, Opts} ->
    case setopts(S, Opts) of
ok -> {ok, S};
Error -> close(S), Error
    end;
Error ->
    close(S), Error
    end.
不过你应该不用改动代码,直接使用async_accept/2即可跳过这段.
17 楼 qiezi 2007-08-01  
Trustno1 写道

这个至多是说yaws实现的问题,和Erlang本身无关.

我测试的结果,应该就是erlang底层实现问题,连接建立时都会有这种调用,对于长连接来说这个影响倒并不是很大:

$ strace -p xxxxx -T
.....
clock_gettime(CLOCK_MONOTONIC, {1287762, 170939432}) = 0 <0.000008>
gettimeofday({1185949291, 63789}, NULL) = 0 <0.000007>
accept(8, {sa_family=AF_INET, sin_port=htons(64671), sin_addr=inet_addr("127.0.0.1")}, [16]) = 11 <0.000013>
fcntl64(11, F_GETFL)                    = 0x2 (flags O_RDWR) <0.000008>
fcntl64(11, F_SETFL, O_RDWR|O_NONBLOCK) = 0 <0.000008>
getsockopt(8, SOL_TCP, TCP_NODELAY, [1], [4]) = 0 <0.000009>
getsockopt(8, SOL_SOCKET, SO_KEEPALIVE, [0], [4]) = 0 <0.000009>
getsockopt(8, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 <0.000007>
getsockopt(8, SOL_IP, IP_TOS, [0], [4]) = 0 <0.000009>
getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 <0.000008>
getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 <0.000008>
setsockopt(11, SOL_IP, IP_TOS, [0], 4)  = 0 <0.000008>
setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 <0.000011>
getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 <0.000007>
getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 <0.000008>
setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 <0.000007>
getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 <0.000008>
getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 <0.000008>
setsockopt(11, SOL_SOCKET, SO_KEEPALIVE, [0], 4) = 0 <0.000008>
setsockopt(11, SOL_IP, IP_TOS, [0], 4)  = 0 <0.000007>
setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 <0.000008>
getsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], [4]) = 0 <0.000007>
getsockopt(11, SOL_IP, IP_TOS, [0], [4]) = 0 <0.000008>
setsockopt(11, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000008>
setsockopt(11, SOL_SOCKET, SO_PRIORITY, [0], 4) = 0 <0.000008>
clock_gettime(CLOCK_MONOTONIC, {1287762, 172860432}) = 0 <0.000008>
accept(8, 0xbffff1c0, [28])             = -1 EAGAIN (Resource temporarily unavailable) <0.000010>
recv(11, 0xb7cfb970, 4, 0)              = -1 EAGAIN (Resource temporarily unavailable) <0.000009>
clock_gettime(CLOCK_MONOTONIC, {1287762, 173046432}) = 0 <0.000008>
clock_gettime(CLOCK_MONOTONIC, {1287762, 173098432}) = 0 <0.000008>
epoll_ctl(3, EPOLL_CTL_DEL, 8, {EPOLLIN, {u32=8, u64=8589934600}}) = 0 <0.000010>
epoll_ctl(3, EPOLL_CTL_ADD, 8, {EPOLLIN, {u32=8, u64=8589934600}}) = 0 <0.000009>
epoll_ctl(3, EPOLL_CTL_ADD, 11, {EPOLLIN, {u32=11, u64=8589934603}}) = 0 <0.000012>
epoll_wait(3, {}, 256, 3000)            = 0 <2.999371>

我的测试程序是一个进程accept,收到一个就建立一个新进程去recv,上面这个过程就是telnet上去什么也不做抓下来的。
16 楼 Trustno1 2007-08-01  
jackyz 写道
个人比较倾向于赞同 mryufeng 同学“质疑-询证”的独立思考与严谨求证态度。

我认为这里是两个问题:
A,以 c 的视角来看 erlang 的网络底层代码,在性能上有进一步提高的空间。profile 结果表明了这一点。

这个帖子实际上有几个问题.
bottle neck定位的问题.mryufeng 用profile 工具dump出来的information,的确有很大的价值.可惜他对bottle neck的定位并不准确.我手上没有什么profile工具,仅凭逻辑上的推断和ultraedit的search基本上可以确定,strace 出来的结果肯定不是Erlang以及OPT本身的问题.
erlang 所有的socket api的封装都是在kernel下的inet module里面,getopts,setopts和recv,send这些函数是分开实现的.erlang底层的代码就没有必要把recv和send里面再加入getopts的代码.有能力设计runtime库的作者都不会犯这种低级错误.
在inet上面opt又封装了一层gentcp.gentcp的recv,send唯一一个多余的操作是去inet_db去lookup Socket.对于正常的anscyn的网络程序管理一个socket queue这点恐怕也是逃不掉的.

那么唯一的那些耗时操作是yaws代码:
%% ret:  continue | done
'GET'(CliSock, Req, Head) ->
    SC=get(sc),
    ok = yaws:setopts(CliSock, [{packet, raw}, binary], is_ssl(SC#sconf.ssl)),
    flush(CliSock, Head#headers.content_length),
    ARG = make_arg(CliSock, Head, Req, undefined),
    handle_request(CliSock, ARG, 0).

这个至多是说yaws实现的问题,和Erlang本身无关.

关于Cache,Yaws的文档Chapter3里面明确写明了是支持Cache的


引用
YAWS acts very much like any regular webserver while delivering static pages.By default YAWS will cache
static content in RAM.The caching behavior is controlled by a number of global configuration directives.
Since the RAM caching occupies memory,it maybe interesting to tweak the default values for the caching
directives or even to turn it off completely.
The following configuration directives control the caching behavior
* max_num_cached_files=Integer YAWS will cache small files such as commonly accessed GIF images
in RAM.This directives ets a maximum number on the number of cached files.The default value is
400.
* max_num_cached_bytes=Integer This directive controls the total amount of RAM which can maxi-
mally be used for cached RAM files.The default value is 1000000,1 mega byte.
* max_size_cached_file=Integer
This directive sets a maximum size on the files that are RAM cached by YAWS . The default value i
8000,8 batters.
It maybe considered to be confusing,but the numbers specified in the above mentioned cache directives
are local to each server.Thus if we have specified max_num_cached_bytes=1000000 and have defined
3 servers,we mayactually use 3*1000000bytes.
15 楼 mryufeng 2007-08-01  
谢谢jackz的鼓励,俺一直在hack erlang这条路上work hard.
14 楼 jackyz 2007-08-01  
个人比较倾向于赞同 mryufeng 同学“质疑-询证”的独立思考与严谨求证态度。

我认为这里是两个问题:
A,以 c 的视角来看 erlang 的网络底层代码,在性能上有进一步提高的空间。profile 结果表明了这一点。
B,erlang 在并发/分布的高度复杂问题上提供了目前仅见的统一而且优雅的一揽子解决方案。这似乎是大家的共识。
我想这两个问题之间,并不存在非此即彼的逻辑。

更进一步, mryufeng 有难得的 c 网络编程视角与丰富的实践经验,我建议你继续深入 hack erlang 的源码,从性能角度优化 erlang 这部分 c 代码(比如,将 yaws 的 ab 测试的数据从 c3k 提升到 c100k 的性能水平?)。优化的成果,可以做成 patch 提交到 erlang-patch maillist。

倘若能够如此,将会是为整个 erlang 社区做出的巨大贡献。
13 楼 mryufeng 2007-08-01  
其实我要说的不是erlang的性能差或者不好 我个人对这个东西非常着迷 做了多年的网络程序 突然发现 erlang该有的东西都差不多有了。我要说的是 任何程序其实都有改进的余地 不要盲目相信。用profile工具收集证据 接着优化流程 优化代码,持续改进,才能把东西做成精品。
12 楼 Trustno1 2007-08-01  
qiezi 写道
Trustno1 写道
ACE那种,异步方式处理网络IO的C++框架,处理这种复杂逻辑就非常困难,不但难以调试和扩展,而且本身就会造成性能下降.在可伸缩性上,C/C++ 的实现更无法自然地扩展到集群上去.

用C++最终也能实现出来,只不过最后可能重新实现了一个erlang核心,而且调用界面反而不如erlang美观。。我看C++的各种完成并行计算或分布式的库甚至是编译器扩展,从语法上来看都比较丑陋,代码风格上也截然不同。

C++好像没有一个框架同时支持并发/并行/分布,把几个框架凑到一块的难度也不小。


什么时候向编程语言里加入新概念取决于“创造性扩展原则”:当程序出于技术原因变得过度复杂,但增加的复杂度和要解决的问题无关时,就可以引入新的概念了。引入的新概念应该简化程序。
11 楼 qiezi 2007-08-01  
Trustno1 写道
ACE那种,异步方式处理网络IO的C++框架,处理这种复杂逻辑就非常困难,不但难以调试和扩展,而且本身就会造成性能下降.在可伸缩性上,C/C++ 的实现更无法自然地扩展到集群上去.

用C++最终也能实现出来,只不过最后可能重新实现了一个erlang核心,而且调用界面反而不如erlang美观。。我看C++的各种完成并行计算或分布式的库甚至是编译器扩展,从语法上来看都比较丑陋,代码风格上也截然不同。

C++好像没有一个框架同时支持并发/并行/分布,把几个框架凑到一块的难度也不小。
10 楼 Trustno1 2007-08-01  
mryufeng 写道
erts的1xw代码俺基本上已经读过一遍了 erlang的emulator实现总体来讲效能还是蛮高的 个人感觉erlang的优势在于dist和得益于fp语言特性的lockfree 和code hot replacement.

对于Http这种应用一收一发,大不了搞搞Cache,逻辑简单,C++会有优势.但是一旦逻辑复杂起来,比如很多电信应用里面,一个客户端连上来需要数个服务器同时协调提供服务.ACE那种,异步方式处理网络IO的C++框架,处理这种复杂逻辑就非常困难,不但难以调试和扩展,而且本身就会造成性能下降.在可伸缩性上,C/C++ 的实现更无法自然地扩展到集群上去.
9 楼 Trustno1 2007-08-01  
mryufeng 写道
erlang根本没有进程机制 就是简单的erl_process 结构

说到底,操作系统所谓的Process和Thread 也只不过是一个Context结构,用指针保存每个Stack Frame,然后按时间片切换Context.有任何区别吗?
用最简单的stack_t ,sigaltstack和longjmp 就能做一个最简单的micro thread.

8 楼 cookoo 2007-08-01  
呼呼,有个文章说yaws做得还不够好

性能方面,俄罗斯的nginx服务器我自己测试下来是现在最快的,静态文件性能有apache2的两倍。有趣的是nginx也支持热配置更新和本身代码热更新,做法和erlang差不多:给master进程发信号说要升级拉,还在工作的worker继续,但别接新任务了等做完再更新,现在发呆着的worker马上更新然后等着去接新任务。

BTW, 楼主要小心别沾染标题党的“必看”恶习呵呵
7 楼 mryufeng 2007-08-01  
erlang的driver机制还是单线程的event dispatch机制 只有在具体的driver使用async的时候才用线程池(也就是+A n)来辅助处理。async还是后来引进来的 所以erlang的emulator基本上就是一个事件反转的调用框架, 和 ACE和Reactor概念上是一样的。其实这个东西ACE作的也不错 但是ACE的抽象原语偏低,使用起来容易出错。
6 楼 qiezi 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

有种想扁人的感觉。。
5 楼 mryufeng 2007-08-01  
erts的1xw代码俺基本上已经读过一遍了 erlang的emulator实现总体来讲效能还是蛮高的 个人感觉erlang的优势在于dist和得益于fp语言特性的lockfree 和code hot replacement.
4 楼 mryufeng 2007-07-31  
这样的并发俺的event dispatch的程序 单进程 单线程也能轻松达到10w哦
3 楼 mryufeng 2007-07-31  
erlang根本没有进程机制 就是简单的erl_process 结构 里面有message queue 在epoll返回的时候 把socket来的数据变形 然后放到process的queue里面去  再来个循环出来process里面的message而已。 和普通的event dispatch程序(如用libevent)的没有区别。
2 楼 qiezi 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写的内核。

相关推荐

    使用Erlang和Yaws开发REST式的服务

    Erlang是一种面向并发和分布式系统的语言,以其高可靠性而著称,而Yaws是由Claes Wikström用Erlang编写的高性能Web服务器,能够处理大量并发连接。 首先,Yaws提供了几种处理动态内容和构建REST服务的方式: 1. *...

    yaws:Yaws Web服务器

    这是Yaws,是用Erlang编写的动态内容的Web服务器。 准备构建 获取并安装一个Erlang系统( )。 要编译Yaws,需要Erlang / OTP 18.0或更高版本。 如果您已经从github克隆了源代码,并且想使用自动工具进行构建,请...

    yaws-开源

    5. **日志记录和性能监控**:Yaws具有详细的日志记录功能,可以帮助开发者分析和优化服务器性能。同时,它还提供了一套性能监控工具,便于管理员实时掌握服务器状态。 6. **自动压缩**:Yaws可以自动对发送给客户端...

    yaws:偏航(还有另一个网络抓取工具)

    yaws(Yet Another Web Scraper)是一种易于使用但功能强大的Node.js Web抓取工具,它支持多种常用的抓取技术,通过使用带有正则表达式的模式,通过导航DOM(JQuery样式)来定义对象。 它是一个进行中的工作,包括...

    yaws-json2:Yaws json2 库

    yaws-json2 yaws-json2 是来自网络服务器的编码器/解码器。安装在 rebar.config 中: { yaws_json2 , " .* " , { git , " git://github.com/myua/yaws-json2 " , { tag , " master " }}}用法使用yaws_json2:decode_...

    高性能网关设备与服务实践

    随着技术的进步,诸如Nginx、Lighttpd等优秀的基于事件驱动的Web服务器框架,以及Tornado、Django这样的Python非阻塞Web框架,甚至使用Erlang语言编写的Yaws和Cowboy轻量级Web框架,都已经能够很好地解决C10K问题。...

    常用的web服务器软件有哪些.doc

    首先,Apache和Internet Information Server (IIS)是市场份额最大的两款Web服务器。Apache是开源的,具有高度可定制性和丰富的模块支持,适用于各种操作系统。IIS则是微软提供的闭源服务器,主要应用于Windows环境,...

    Building Web Applications with Erlang.2012.英文

    在Yaws上启动Web服务、服务静态文件(Serving Static Files)、编译、加载和运行代码以及集群化Yaws(Clustering Yaws)是构建Erlang Web应用的关键步骤。 4. 在构建Web应用时,需要考虑系统架构(System ...

    building_web_applications_with_erlang.pdf

    - **编译、加载和运行代码**: 在Web应用中,编译、加载和运行代码是常规操作,Yaws提供了相应的机制来支持这一流程。 - **集群Yaws**: 为了提高Web应用的可用性和负载均衡,Yaws支持集群部署,使多个Yaws实例能够...

    Building Web Applications with Erlang

    Yaws是一个用Erlang编写的高性能Web服务器,它特别适用于处理静态文件的分发、编译和运行Erlang代码、以及在Erlang集群中的应用。使用Yaws,开发者可以轻松地启动一个Web服务,从静态文件服务到动态内容处理,再到...

    erlang调用java

    7. **性能和限制**:虽然`Jinterface`提供了一个方便的桥梁,但跨语言调用的性能相比同语言内部调用会有下降。此外,由于`Erlang`和`Java`的并发模型不同,需要考虑线程安全和资源管理等问题。 8. **优化和实践**:...

    Erlang-or-java.rar_erlang

    标题中的“Erlang-or-java.rar_erlang”表明这是一个关于Erlang和Java之间通信的示例项目。Erlang是一种面向并发、分布式、容错的编程语言,常用于构建高可用性和高并发性的系统,而Java则是一种广泛应用的通用编程...

    Erlang-game-server开发实践.zip

    Erlang有多种库如 cowboy 和 yaws 支持WebSocket,方便实现双向通信。 ### 8. 性能优化与监控 Erlang VM(BEAM)提供了诸如实时垃圾回收和运行时性能监控等工具。开发者可以通过这些工具优化代码性能,确保游戏...

    elli:简单,健壮和高性能的Erlang Web服务器

    然而,不同的服务器在性能、功能和灵活性方面各有特点,选择哪一款取决于具体项目需求。 总的来说,elli是一个针对HTTP API设计的Erlang Web服务器,它利用Erlang的语言特性提供了高并发、高可用的解决方案。如果你...

    otp_win_64_24.0.exe

    5. 应用框架:如Mnesia数据库系统、公共接口服务器(COS)和Web服务器(Yaws或Inets)等,方便开发特定用途的应用。 使用OTP Win64 24.0,开发者可以构建高性能、高并发的系统,同时享受Erlang语言提供的强大并发...

    轻量级Web服务器选择

    - **C语言**:许多轻量级Web服务器都是用C语言编写的,因为C语言能够提供更好的性能和较低的资源消耗。 - **Erlang**:Erlang是一种适合编写并发程序的语言,因此使用Erlang编写的Web服务器在处理高并发请求时表现...

    erlang websocket 练习

    在IT行业中,Erlang是一种面向并发的编程语言,它被广泛用于构建高可靠性、分布式系统,尤其是在电信和实时计算领域。WebSocket协议则是一种在Web上实现双向通信的协议,它允许服务器和客户端进行持久连接,从而实现...

    otp_win64_21.0.zip

    10. **Web开发**: Erlang可以通过 cowboy、YAWS 等框架进行Web开发,构建高性能的HTTP服务器和API。 总的来说,Erlang OTP 21.0的Windows 64位版本是一个强大的工具,适合构建分布式、高并发和容错的系统,尤其在...

Global site tag (gtag.js) - Google Analytics