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

最快的http hello world服务器调优指南 (C20Khttp短链接请求/S每桌面CPU)

阅读更多
erl的虚拟机有2种方式 plain版本的和smp版本的。 smp版本由于锁的开销相比要比plain版本的慢很多。 而32位机器由于内存访问比64位的少,也会快出很多。所有我选择在32位的linux系统下调优这个httpd服务器。 这个服务器就是实现个简单的功能,在browser下返回hello world。 以下我们会先编译我们的优化版本的虚拟机,然后再分别测试R13B02的标准版本的和我们优化版的性能:

root@nd-desktop:/build_opt_plain# uname -a
Linux nd-desktop 2.6.31-14-generic #3 SMP Sun Nov 1 23:03:10 CST 2009 i686 GNU/Linux

#准备开发环境
root@nd-desktop:/# apt-get build-dep erlang

#下载otp R13B02-1源码包
root@nd-desktop:/# wget http://www.erlang.org/download/otp_src_R13B02-1.tar.gz

#解开patch包
root@nd-desktop:/# tar xzvf build_opt_plain.tgz

#解开源码包
root@nd-desktop:/# tar xzf otp_src_R13B02-1.tar.gz

#打补丁
root@nd-desktop:/# cd otp_src_R13B02-1
root@nd-desktop:/otp_src_R13B02-1# patch -p1 <../build_opt_plain/otp_src_R13B02-1_patch_by_yufeng
patching file erts/emulator/beam/erl_binary.h
patching file erts/emulator/beam/erl_process.c
patching file erts/emulator/beam/sys.h
patching file erts/emulator/drivers/common/inet_drv.c
patching file erts/preloaded/src/Makefile
patching file erts/preloaded/src/prim_inet.erl
patching file lib/asn1/src/Makefile
patching file lib/hipe/Makefile
patching file lib/parsetools/src/Makefile
root@nd-desktop:/otp_src_R13B02-1# ../build_opt_plain/build.plain
。。。
如果编译都没有任何错误的话, 就大功告成了。

好 现在我们开始性能比较:

#先加大文件句柄数
root@nd-desktop:/otp_src_R13B02-1# cd ../build_opt_plain
root@nd-desktop:/build_opt_plain# ulimit -n 99999

#标准发布版本
root@nd-desktop:/build_opt_plain# erlc ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1 erl +K true +h 99999  +P 99999 -smp enable +S 2:1 -s ehttpd
Erlang R13B03 (erts-5.7.4) [source] [smp:2:1] [rq:2] [async-threads:0] [hipe] [kernel-poll:true]

ehttpd ready with 2 schedulers on port 8888
Eshell V5.7.4  (abort with ^G)
1>

#在另外的一台机器上发动ab测试
[root@localhost src]# ab -c 60 -n 100000 http://192.168.235.147:8888/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.235.147 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software:       
Server Hostname:        192.168.235.147
Server Port:            8888

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      60
Time taken for tests:   8.925945 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Total transferred:      5100051 bytes
HTML transferred:       1200012 bytes
Requests per second:    11203.29 [#/sec] (mean)
Time per request:       5.356 [ms] (mean)
Time per request:       0.089 [ms] (mean, across all concurrent requests)
Transfer rate:          557.92 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1  65.7      0    3001
Processing:     0    3   1.5      4       7
Waiting:        0    2   1.8      4       6
Total:          0    4  65.8      4    3007
WARNING: The median and mean for the waiting time are not within a normal deviation
        These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      4
  80%      4
  90%      5
  95%      5
  98%      5
  99%      5
100%   3007 (longest request)

标准smp版本1个CPU的结果是: 11203.29 [#/sec] (mean)

#启用hipe的标准版本
root@nd-desktop:/build_opt_plain# erlc +native +"{hipe, [o3]}" ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1 erl +K true +h 99999  +P 99999 -smp enable +S 2:1 -s ehttpd
Erlang R13B03 (erts-5.7.4) [source] [smp:2:1] [rq:2] [async-threads:0] [hipe] [kernel-poll:true]

ehttpd ready with 2 schedulers on port 8888
Eshell V5.7.4  (abort with ^G)
1>

标准smp hipe版本1个CPU结果是: 12390.32 [#/sec] (mean)


#我们的优化版本
root@nd-desktop:/build_opt_plain#  ../otp_src_R13B02-1/bin/erlc  ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1   ../otp_src_R13B02-1/bin/erl +K true +h 99999  +P 99999   -s ehttpd
Erlang R13B02 (erts-5.7.3) [source] [rq:1] [hipe] [kernel-poll:true]

ehttpd ready with 1 schedulers on port 8888
Eshell V5.7.3  (abort with ^G)
1>

优化版本单个cpu: 19662.37 [#/sec] (mean)


#启用hipe的优化版本
root@nd-desktop:/build_opt_plain#  ../otp_src_R13B02-1/bin/erlc +native +"{hipe, [o3]}"  ehttpd.erl
root@nd-desktop:/build_opt_plain# taskset -c 1   ../otp_src_R13B02-1/bin/erl +K true +h 99999  +P 99999   -s ehttpd
Erlang R13B02 (erts-5.7.3) [source] [rq:1] [hipe] [kernel-poll:true]

ehttpd ready with 1 schedulers on port 8888
Eshell V5.7.3  (abort with ^G)
1>

优化版本启用hipe单个cpu:20090.83 [#/sec] (mean)

附上我们的最小的高性能的http echo 服务器:

root@nd-desktop:/build_opt_plain# cat ehttpd.erl
-module(ehttpd).
-compile(export_all).


start() ->
    start(8888).
start(Port) ->
    N = erlang:system_info(schedulers),
    listen(Port, N),
    io:format("ehttpd ready with ~b schedulers on port ~b~n", [N, Port]),

    register(?MODULE, self()),
    receive Any -> io:format("~p~n", [Any]) end.  %% to stop: ehttpd!stop.

listen(Port, N) ->
    Opts = [{active, false},
            binary,
            {backlog, 256},
            {packet, http_bin},
            {raw,6,9,<<1:32/native>>}, %defer accept
            %%{delay_send,true},
            %%{nodelay,true},
            {reuseaddr, true}],

    {ok, S} = gen_tcp:listen(Port, Opts),
    Spawn = fun(I) ->    
                    register(list_to_atom("acceptor_" ++ integer_to_list(I)),
                             spawn_opt(?MODULE, accept, [S, I], [link, {scheduler, I}]))
            end,
    lists:foreach(Spawn, lists:seq(1, N)).

accept(S, I) ->
    case gen_tcp:accept(S) of
        {ok, Socket} -> spawn_opt(?MODULE, loop, [Socket], [{scheduler, I}]);
        Error    -> erlang:error(Error)
    end,
    accept(S, I).

loop(S) ->
    case gen_tcp:recv(S, 0) of
        {ok, http_eoh} ->
            Response = <<"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nhello world!">>,
            gen_tcp:send(S, Response),
            gen_tcp:close(S),
            ok;

        {ok, _Data} ->
            loop(S);

        Error ->
            Error
    end.


这个服务器是最小的,单是在多处理器和单cpu上都有非常好的性能。

root@nd-desktop:/build_opt_plain# cat /proc/cpuinfo
model name      : Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz

注:这个http服务器基本上是在c的程序跑,erlang的代码执行的很少, 所以hipe的提升效果不是很明显。对于复杂的业务,应该是有很大的帮助的。

附件里是用到的脚本和补丁。


我们可以得出结论:
hipe启用要比不启用快。
优化版本的和标准版本的 20090:11203, 性能提高了将近80% 还是非常可观的。


分享到:
评论
21 楼 mryufeng 2010-01-14  
rain2005 写道
spawn_opt(?MODULE, loop, [Socket], [{scheduler, I}]); 


原来spawn option有scheduler, I这个选项,学习了一把,这样SMP下锁的开销基本上没有了哦。同时erlang支持多个accept process

今天把老大的文章看个遍,呵呵,貌似最近不怎么写文章了哦。


这个选项是未公开的 otp team还没有最终想好这个功能如何体现 不过你可以先用着 这个cpu绑定对提高性能很有帮助, 前提是你规划好了...
20 楼 rain2005 2010-01-14  
spawn_opt(?MODULE, loop, [Socket], [{scheduler, I}]); 


原来spawn option有scheduler, I这个选项,学习了一把,这样SMP下锁的开销基本上没有了哦。同时erlang支持多个accept process

今天把老大的文章看个遍,呵呵,貌似最近不怎么写文章了哦。
19 楼 mryufeng 2009-11-22  
linkerlin 写道
老大,最近有折腾lua么?

lua有空的时候都在看呀 百看不厌呀
18 楼 linkerlin 2009-11-21  
老大,最近有折腾lua么?
17 楼 whrllm 2009-11-10  
我确认过了,我重新装过一次没有patch的时候可以正常运行,但是patch后,运行erl就一堆得错误
16 楼 mryufeng 2009-11-10  
你先确认patch前你的make过程没有问题 我在64位上没有问题的。
15 楼 whrllm 2009-11-10  
老大,写一个全的patch好么?好象在64位的机器上跑不起来呀。出了好多的错误,期待呀//
14 楼 joshzhu 2009-11-08  
mryufeng补充:以上例子要在R13版本才能跑
13 楼 mryufeng 2009-11-06  
joel的hotwheel程序是个优化的典型 可以看到很多技术点。。。
12 楼 mryufeng 2009-11-05  
设计是1方面 性能挖掘是一方面 同样的代码logic 会差很多的.
11 楼 大忙人 2009-11-05  
不错不错。
不过,我觉得这类还是通过设计来解决比较好一些。毕竟这种做法不具有扩展性。
10 楼 mryufeng 2009-11-05  
我用这个vm hotwheel比赛突破4W 奖励下我哦 $1K。。。
9 楼 mryufeng 2009-11-05  
right
8 楼 whrllm 2009-11-05  
是不是在./configure 那不带任何参数就可以了?
7 楼 whrllm 2009-11-05  
老大 把编smp的版本的脚本也发出来嘛//
6 楼 mryufeng 2009-11-05  
我编译的是 单cpu版本的 hipe是和版本相关的 你要想用smp, 得重新编译个。 smp和plain版本的完全不兼容。
5 楼 whrllm 2009-11-05  
还有个问题,就是我为什么使用erl -smp -enable无效,怎么才能在hipe的情况下 使用smp啊?谢谢
4 楼 whrllm 2009-11-05  
老大 请教个问题,我按照这些步骤编译了,而且过程没有出错,
但是我用 m(lists),并没有看到debug_info,native,"{hipe, [o3]}"] 这个显示,是不是没有成功啊?

PS:不好意思,刚不小心发错文章了
3 楼 joshzhu 2009-11-04  
这个结果相当NB,相当有说服力~~~
2 楼 whrllm 2009-11-04  
等了一个晚上,出来了,哈哈,老大太帅了////

相关推荐

    khttp:Kotlin HTTP请求库。 类似于Python请求

    khttp是一款针对Kotlin开发的HTTP请求库,其设计灵感来源于Python的requests库,旨在提供一个简洁、易用且功能强大的API,使得开发者在Kotlin环境中处理网络请求变得更加简便。这款库的核心目标是通过优雅的Kotlin...

    KHttp,kotlin-dsl包装okhttp3.zip

    【KHttp:Kotlin DSL封装OkHttp3】 KHttp是一个基于Kotlin语言的DSL(领域特定语言)封装库,它简化了对OkHttp3的使用,使得在Android或Kotlin应用中进行网络请求变得更加简洁、易读。OkHttp是Square公司开发的一个...

    Android-KotlinHTTP请求库与Pythonrequests类似

    在Android开发中,使用Kotlin进行网络请求是常见的任务,而`khttp`库就是为此目的设计的一个轻量级工具。这个库模仿了Python中广受欢迎的`requests`库,为开发者提供了简单易用的API来执行HTTP请求。在本文中,我们...

    Android-KHttp利用KotlinDSL封装OKHttp3

    在Android开发中,高效、可靠的网络请求库是不可或缺的一部分,OKHttp因其优秀的性能和易用性,被广泛应用。而Kotlin DSL(Domain Specific Language)的引入,为代码编写提供了更加简洁和可读的语法。本篇文章将...

    khttp:HTTPS服务器和(可能在将来)反向代理

    - **高度可定制**:khttp 可能支持自定义请求处理器和中间件,允许开发者根据需要调整服务器的行为,如处理特定类型的请求、添加身份验证机制等。 - **SSL/TLS 支持**:由于其 HTTPS 功能,khttp 应该内置了处理 ...

    khttp-2.7.5

    khttp-2.7.5.jar

    okhttp3.8.0-jdk1.6.zip

    3. **透明GZIP压缩**:OkHttp自动检测服务器是否支持GZIP压缩,并在必要时进行数据压缩,降低了传输数据的大小,提高了网络效率。 4. **同步和异步API**:OkHttp提供了简单易用的同步和异步API,方便开发者根据需求...

    kcgi:CC ++的最小CGI和FastCGI库

    - **高效**:通过缓存和复用CGI请求处理程序,`kcgi`能有效地处理大量并发请求。 - **安全**:`kcgi`提供了安全机制,如防止缓冲区溢出和输入验证,确保应用的安全性。 - **易用**:API设计简洁,便于理解和使用...

    Android快速开发框架

    BaseHttpListActivity,几行代码搞定http请求列表 加载和缓存;BaseView,自定义View竟然如此简单;万能的Entry, V&gt;,两个变量的Model/JavaBean再也不用写了;100多个常用style,一行搞定View属性,一键统一配置UI..

    KmmRssReader

    4. **Networking**: 为了获取RSS源,项目可能会使用Kotlin的`khttp`库或者更现代的`Ktor`网络库来执行HTTP请求。Ktor提供了一套完整的异步网络API,适合构建服务器和客户端应用。 5. **UI**: 对于Android,UI可能由...

Global site tag (gtag.js) - Google Analytics