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 Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python