对C, Erlang, Java and the Go 编程语言的Hello world web服务进行了测试 .
* C, 使用高性能的web server-nginx,以及一个 hello world 的nginx模块
* Erlang/OTP
* Java, 使用MINA 2.0框架.
* Go, http://golang.org/
1. 测试环境
1.1 Hardware/OS
2 Linux boxes in a gigabit ethernet LAN, 1 server and 1 test client
Linux Centos 5.2 64bit
Intel(R) Xeon(R) CPU E5410 @ 2.33GHz (L2 cache: 6M), Quad-Core * 2
8G memory
SCSI disk (standalone disk, no other access)
1.2 软件版本
nginx, nginx-0.7.63.tar.gz
Erlang, otp_src_R13B02-1.tar.gz
Java, jdk-6u17-linux-x64.bin, mina-2.0.0-RC1.tar.gz
Go, hg clone -r release https://go.googlecode.com/hg/ $GOROOT (Nov 12, 2009)
1.3 源代码及配置
Linux, run sysctl -p
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
kernel.panic = 1
net.ipv4.tcp_rmem = 8192 873800 8738000
net.ipv4.tcp_wmem = 4096 655360 6553600
net.ipv4.ip_local_port_range = 1024 65000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# ulimit -n
150000
C: ngnix hello world module, copy the code ngx_http_hello_module.c from http://timyang.net/web/nginx-module/
in nginx.conf, set “worker_processes 1; worker_connections 10240″ for 1 cpu test, set “worker_processes 4; worker_connections 2048″ for multi-core cpu test. Turn off all access or debug log in nginx.conf, as follows
worker_processes 1;
worker_rlimit_nofile 10240;
events {
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 0;
server {
listen 8080;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /hello {
ngx_hello_module;
hello 1234;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
$ taskset -c 1 ./nginx or $ taskset -c 1-7 ./nginx
Erlang hello world server
The source code is available at yufeng’s blog, see http://blog.yufeng.info/archives/105
Just copy the code after “cat ehttpd.erl”, and compile it.
$ erlc ehttpd.erl
$ taskset -c 1 erl +K true +h 99999 +P 99999 -smp enable +S 2:1 -s ehttpd
$ taskset -c 1-7 erl +K true -s ehttpd
We use taskset to limit erlang vm to use only 1 CPU/core or use all CPU cores. The 2nd line is run in single CPU mode, and the 3rd line is run in multi-core CPU mode.
Java source code, save the 2 class as HttpServer.java and HttpProtocolHandler.java, and do necessary import.
public class HttpServer {
public static void main(String[] args) throws Exception {
SocketAcceptor acceptor = new NioSocketAcceptor(4);
acceptor.setReuseAddress( true );
int port = 8080;
String hostname = null;
if (args.length > 1) {
hostname = args[0];
port = Integer.parseInt(args[1]);
}
// Bind
acceptor.setHandler(new HttpProtocolHandler());
if (hostname != null)
acceptor.bind(new InetSocketAddress(hostname, port));
else
acceptor.bind(new InetSocketAddress(port));
System.out.println("Listening on port " + port);
Thread.currentThread().join();
}
}
public class HttpProtocolHandler extends IoHandlerAdapter {
public void sessionCreated(IoSession session) {
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
session.setAttribute(SslFilter.USE_NOTIFICATION);
}
public void sessionClosed(IoSession session) throws Exception {}
public void sessionOpened(IoSession session) throws Exception {}
public void sessionIdle(IoSession session, IdleStatus status) {}
public void exceptionCaught(IoSession session, Throwable cause) {
session.close(true);
}
static IoBuffer RESULT = null;
public static String HTTP_200 = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\n" +
"hello world\r\n";
static {
RESULT = IoBuffer.allocate(32).setAutoExpand(true);
RESULT.put(HTTP_200.getBytes());
RESULT.flip();
}
public void messageReceived(IoSession session, Object message)
throws Exception {
if (message instanceof IoBuffer) {
IoBuffer buf = (IoBuffer) message;
int c = buf.get();
if (c == 'G' || c == 'g') {
session.write(RESULT.duplicate());
}
session.close(false);
}
}
}
$ taskset -c 1-7 \
java -Xmx1024m -Xms1024m -XX:+UseConcMarkSweepGC -classpath . test.HttpServer 192.168.10.1 8080
We use taskset to limit java only use cpu1-7, and not use cpu0, because we want cpu0 dedicate for system call.
Go language, source code
package main
import (
"http";
"io";
)
func HelloServer(c *http.Conn, req *http.Request) {
io.WriteString(c, "hello, world!\n");
}
func main() {
runtime.GOMAXPROCS(8); // 8 cores
http.Handle("/", http.HandlerFunc(HelloServer));
err := http.ListenAndServe(":8080", nil);
if err != nil {
panic("ListenAndServe: ", err.String())
}
}
$ 6g httpd2.go
$ 6l httpd2.6
$ taskset -c 1-7 ./6.out
1.4 Performance test client
ApacheBench client, for 30, 100, 1,000, 5,000 concurrent threads
ab -c 30 -n 1000000 http://192.168.10.1:8080/
ab -c 100 -n 1000000 http://192.168.10.1:8080/
ab -c 1000 -n 1000000 http://192.168.10.1:8080/
ab -c 5000 -n 1000000 http://192.168.10.1:8080/
2. 测试结果
2.1 request per second
|
30 (threads) |
100 |
1000 |
5000 |
Nginx html(1C) |
21,301 |
21,331 |
17,803 |
11,901 |
Nginx module(1C) |
25,809 |
25,735 |
17,562 |
12,412 |
Nginx module(Multi-core) |
25,057 |
24,507 |
18,110 |
11,681 |
Erlang(1C) |
11,585 |
12,367 |
12,185 |
10,200 |
Erlang(Multi-Core) |
15,101 |
20,255 |
18,687 |
11,613 |
Java, Mina2 |
30,631 |
26,846 |
18,134 |
11,945 |
Go |
14,080 |
14,748 |
13,292 |
7,754 |
![c_erlang_java_go c_erlang_java_go](http://timyang.net/blog/wp-content/uploads/2009/11/c_erlang_java_go.png)
2.2 latency, 99% requests within(ms)
|
30 |
100 |
1,000 |
5,000 |
Nginx html(1C) |
1 |
4 |
69 |
504 |
Nginx module(1C) |
1 |
4 |
73 |
502 |
Nginx module(Multi-core) |
1 |
6 |
70 |
501 |
Erlang(1C) |
3 |
8 |
3,023 |
1,874 |
Erlang(Multi-Core) |
2 |
7 |
73 |
495 |
Java, Mina2 |
3 |
5 |
67 |
501 |
Go |
26 |
33 |
3,006 |
9,059 |
3. Notes
* On large concurrent connections, C, Erlang, Java no big difference on their performance, all are about 18k/s (1,000 threads) .
* Java runs better on small connections, but the code in this test doesn’t parse the HTTP request header.
* Although Mr. Yu Feng (the Erlang guru in China) mentioned that Erlang performance better on single CPU(prevent context switch), but the result tells that Erlang has big latency(> 1S) under 1,000 or 5,000 connections.
* Go language is very close to Erlang, but still not good under heavy load (5,000 threads)
查看原文:http://timyang.net/programming/c-erlang-java-performance/
17 楼 witeman 2011-02-27 15:02
原因请参考:
"Eventually I came to believe that Erlang’s I/O library is very slow and that that might be the reason for its sub-optimal performance in the benchmarks above."
http://muharem.wordpress.com/2007/07/31/erlang-vs-stackless-python-a-first-benchmark/
16 楼 witeman 2011-02-27 14:55
在5000Threads的时候,Erlang(1Core)应该比Go要多,而且,和其他的区别不大,可是,怎么图标上看上去和别的对比起来是少了一半左右的?
15 楼 Stero 2010-01-21 03:50
高并发的情况下,ab本身就是瓶颈。用更好的机器跑ab,用两台机器一起跑ab。用10G网卡来连接网络。
14 楼 fsword 2009-12-10 14:16
你测试性能都在本机进行?
13 楼 olive009 2009-11-22 17:44
12 楼 rain2005 2009-11-19 12:51
11 楼 CharlesCui 2009-11-19 11:51
说到点子上了,语言这东西学来学去没意义,知道了算法,会一种高效的语言,之后设计出来的东东对客户来说足够足够了.
作为一个老板更不会关心你用什么语言.
跟买车一样,买的时候挑来挑去,总在比较,没意义.合适就好!
10 楼 sleets 2009-11-19 11:00
9 楼 gqf2008 2009-11-19 09:24
8 楼 linux1689 2009-11-19 08:39
Erlang支持高并发,但是是有是有条件的。
7 楼 redsea 2009-11-19 08:20
6 楼 redsea 2009-11-19 08:18
5 楼 skzr.org 2009-11-19 07:31
同意,我一直觉得java的server还是很不错的选择!应付大多数应用应该足够了
4 楼 gakaki 2009-11-18 23:06
3 楼 gakaki 2009-11-18 23:06
除非直接写汇编然后汇编上写语言 java和.net是用了虚拟机
2 楼 wangxinpier 2009-11-18 19:15
1 楼 Arden 2009-11-18 17:14