[Twisted-Python] transport.write performance.

zipxing zipxing at hotmail.com
Tue Jul 30 02:54:10 MDT 2013


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);} 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://twistedmatrix.com/pipermail/twisted-python/attachments/20130730/70353e04/attachment-0001.html>


More information about the Twisted-Python mailing list