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