<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>