<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:΢ÈíÑźÚ
}
--></style></head>
<body class='hmmessage'><div dir='ltr'><div>A simple TCP echo server using epoll reactor:</div><div>this server process take 60% cpu on 4000 request/s.</div><div><br></div><div>If use <span style="font-size: 12pt; ">self.transport.getHandle().send instead of </span><span style="font-size: 12pt; ">self.transport.write,</span></div><div>it take 30% cpu on 4000 request/s.</div><div><br></div><div>Why transport.write take more user cpu?</div><div><span style="font-size: 12pt; ">Why twisted performance so poor?</span></div><div><span style="font-size: 12pt; ">(echosvr.c using libevent only take 12% cpu on 4000 request/s)</span></div><div><br></div><div>tsvr.py</div><div>-----------------------------------------------------------</div><div>import sys, time, random, socket, traceback</div><div>from twisted.internet import epollreactor</div><div>epollreactor.install()</div><div>from twisted.internet import defer, reactor, task</div><div>from twisted.internet.protocol import Protocol, Factory</div><div>from protocol import TCPServerProtocol</div><div><br></div><div>def main():</div><div>        tcpprotocol = TCPServerProtocol</div><div>        factory = Factory()</div><div>        factory.protocol = tcpprotocol</div><div>        reactor.listenTCP(9976, factory)</div><div>        reactor.run()</div><div><br></div><div>if __name__ == '__main__':</div><div>        main()</div><div><br></div><div><div>protocol.py</div><div><span style="font-size: 12pt; ">--------------------------------------------------------- </span></div><div>import socket</div><div>import datetime</div><div>import traceback</div><div>from twisted.protocols.basic import LineReceiver</div><div>from twisted.internet import protocol</div><div><br></div><div>class TCPServerProtocol(LineReceiver):</div><div>        req_count = 0</div><div>        req_time = datetime.datetime.now()</div><div><br></div><div>        def lineReceived(self, data):</div><div>                TCPServerProtocol.req_count+=1</div><div>                if TCPServerProtocol.req_count%10000==0:</div><div>                        ct = datetime.datetime.now()</div><div>                        dt = ct-TCPServerProtocol.req_time</div><div>                        pps = 10000/(dt.seconds+dt.microseconds/1000000.0)</div><div>                        TCPServerProtocol.req_time=ct</div><div>                        print('RPS='+str(pps))</div><div>                try:</div><div>                        #self.transport.write(data)</div><div>                        self.transport.getHandle().send(data)</div><div>                except:</div><div>                        traceback.print_exc()</div></div><div><br></div><div><div>tcli.py </div><div>-----------------------------------------------------------------</div><div>import sys</div><div>import socket</div><div>import traceback</div><div>import time</div><div>import datetime</div><div><br></div><div>host = 'localhost'</div><div>port = 9976</div><div>loopcount = 300</div><div>sockcount = 5000</div><div>RPS = 4000</div><div><br></div><div>ss=[]</div><div>for x in xrange(sockcount):</div><div>        ss.append(socket.socket(socket.AF_INET, socket.SOCK_STREAM))</div><div>        ss[x].connect((host, port))</div><div>        ss[x].settimeout(120)</div><div><br></div><div>for x in xrange(10000000):</div><div>        st = datetime.datetime.now()</div><div>        for y in xrange(loopcount):</div><div>                try:</div><div>                        if ss[x%sockcount]!=None:</div><div>                                ss[x%sockcount].sendall('1234567890\r\n')</div><div>                                ss[x%sockcount].recv(1024)</div><div>                except:</div><div>                        print y</div><div>                        sys.exit()</div><div>        time.sleep(0.1)</div><div>        dt = (datetime.datetime.now()-st)</div><div>        plc = loopcount/(dt.seconds+dt.microseconds/1000000.0)</div><div>        print loopcount/(dt.seconds+dt.microseconds/1000000.0)</div><div>        #auto adjust RPS</div><div>        if plc<RPS:</div><div>                if RPS-plc>50:</div><div>                        loopcount+=10</div><div>        else:</div><div>                if plc-RPS>50:</div><div>                        loopcount-=10</div></div><div><br></div><div><div>echosvr.c </div><div>----------------------------------------------------------------------</div><div>#include <stdio.h></div><div>#include <stdlib.h></div><div>#include <errno.h></div><div>#include <assert.h></div><div><br></div><div>#include <event2/event.h></div><div>#include <event2/bufferevent.h></div><div><br></div><div>#define LISTEN_PORT 9976</div><div>#define LISTEN_BACKLOG 32</div><div><br></div><div>#ifdef FD_SETSIZE</div><div>#undef FD_SETSIZE</div><div>#endif</div><div>#define FD_SETSIZE 65536</div><div><br></div><div>void do_accept(evutil_socket_t listener, short event, void *arg);</div><div>void read_cb(struct bufferevent *bev, void *arg);</div><div>void error_cb(struct bufferevent *bev, short event, void *arg);</div><div>void write_cb(struct bufferevent *bev, void *arg);</div><div><br></div><div>int main(int argc, char *argv[])</div><div>{</div><div>    int ret;</div><div>    evutil_socket_t listener;</div><div>    listener = socket(AF_INET, SOCK_STREAM, 0);</div><div>    assert(listener > 0);</div><div>    evutil_make_listen_socket_reuseable(listener);</div><div><br></div><div>    struct sockaddr_in sin;</div><div>    sin.sin_family = AF_INET;</div><div>    sin.sin_addr.s_addr = 0;</div><div>    sin.sin_port = htons(LISTEN_PORT);</div><div><br></div><div>    if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0) {</div><div>        perror("bind");</div><div>        return 1;</div><div>    }</div><div><br></div><div>    if (listen(listener, LISTEN_BACKLOG) < 0) {</div><div>        perror("listen");</div><div>        return 1;</div><div>    }</div><div><br></div><div>    printf ("Listening...\n");</div><div><br></div><div>    evutil_make_socket_nonblocking(listener);</div><div><br></div><div>    struct event_base *base = event_base_new();</div><div>    assert(base != NULL);</div><div>    struct event *listen_event;</div><div>    listen_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);</div><div>    event_add(listen_event, NULL);</div><div>    event_base_dispatch(base);</div><div><br></div><div>    printf("The End.");</div><div>    return 0;</div><div>}</div><div><br></div><div>void do_accept(evutil_socket_t listener, short event, void *arg)</div><div>{</div><div>    struct event_base *base = (struct event_base *)arg;</div><div>    evutil_socket_t fd;</div><div>    struct sockaddr_in sin;</div><div>    socklen_t slen;</div><div>    fd = accept(listener, (struct sockaddr *)&sin, &slen);</div><div>    if (fd < 0) {</div><div>        perror("accept");</div><div>        return;</div><div>    }</div><div>    if (fd > FD_SETSIZE) {</div><div>        perror("fd > FD_SETSIZE\n");</div><div>        return;</div><div>    }</div><div><br></div><div>    printf("ACCEPT: fd = %u\n", fd);</div><div><br></div><div>    struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);</div><div>    bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);</div><div>    bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);</div><div>}</div><div><br></div><div>void read_cb(struct bufferevent *bev, void *arg)</div><div>{</div><div>#define MAX_LINE    256</div><div>    char line[MAX_LINE+1];</div><div>    int n;</div><div>    evutil_socket_t fd = bufferevent_getfd(bev);</div><div><br></div><div>    while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) {</div><div>        line[n] = '\0';</div><div>        //printf("fd=%u, read line: %s\n", fd, line);</div><div><br></div><div>        bufferevent_write(bev, line, n);</div><div>    }</div><div>}</div><div><br></div><div>void write_cb(struct bufferevent *bev, void *arg) {}</div><div><br></div><div>void error_cb(struct bufferevent *bev, short event, void *arg)</div><div>{</div><div>    evutil_socket_t fd = bufferevent_getfd(bev);</div><div>    printf("fd = %u, ", fd);</div><div>    if (event & BEV_EVENT_TIMEOUT) {</div><div>        printf("Timed out\n"); //if bufferevent_set_timeouts() called</div><div>    }</div><div>    else if (event & BEV_EVENT_EOF) {</div><div>        printf("connection closed\n");</div><div>    }</div><div>    else if (event & BEV_EVENT_ERROR) {</div><div>        printf("some other error\n");</div><div>    }</div><div>    bufferevent_free(bev);</div><div>}</div></div>                                        </div></body>
</html>