代码之家  ›  专栏  ›  技术社区  ›  thr

无堆叠的python网络性能会随着时间的推移而下降?

  •  8
  • thr  · 技术社区  · 16 年前

    所以我在玩弄无堆叠的巨蟒,写一个 非常简单 webserver教自己使用微线程/微线程编程。但现在我的问题是,当我运行类似 ab -n 100000 -c 50 http://192.168.0.192/ (100k请求,50并发)在Apache工作台上,我得到了类似于6K req/s的请求,第二次运行它时,我得到了5.5K、第三次5K、第四次4.5K等,一直到100req/s或其他东西。

    不过,当我重新启动python脚本时,问题就消失了。

    现在我的问题是为什么?我忘记删除微线程了吗?我检查了stackless.getruncount()(它总是返回1,出于某种原因),所以看起来不会有死掉的微线程挂在身边?我尝试对所有完成的微线程调用.kill(),但没有帮助。我就是想不出这个。

    import socket
    import select
    import stackless
    import time
    
    class socket_wrapper(object):
        def __init__(self, sock, sockets):
            super(socket_wrapper, self).__init__()
            self.sock = sock
            self.fileno = sock.fileno
            self.sockets_list = sockets
            self.channel = stackless.channel()
            self.writable = False
            self.error = False
    
        def remove(self):
            self.sock.close()
            self.sockets_list.remove(self)
    
        def send(self, data):
            self.sock.send(data)
    
        def push(self, bytes):
            self.channel.send(self.sock.recv(bytes))
    
    def stackless_accept(accept, handler, recv_size=1024, timeout=0):
        sockets = [accept]
    
        while True:
            read, write, error = select.select(sockets, sockets, sockets, timeout)
    
            for sock in read:
                if sock is accept:
                    # Accept socket and create wrapper
                    sock = socket_wrapper(sock.accept()[0], sockets)
    
                    # Create tasklett for this connection
                    tasklet = stackless.tasklet(handler)
                    tasklet.setup(sock)
    
                    # Store socket
                    sockets.append(sock)
    
                else:
                    # Send data to handler
                    sock.push(recv_size)
    
            # Tag all writable sockets
            for sock in write:
                if sock is not accept:
                    sock.writable = True
    
            # Tag all faulty sockets
            for sock in error:
                if sock is not accept:
                    sock.error = True
                else:
                    pass # should do something here if the main socket is faulty
    
            timeout = 0 if socket else 1
            stackless.schedule() 
    
    def simple_handler(tsock):
        data = ""
    
        while data[-4:] != "\r\n\r\n":
            data += tsock.channel.receive()
    
        while not tsock.writable and not tsock.error:
            stackless.schedule()
    
        if not tsock.error:
            tsock.send("HTTP/1.1 200 OK\r\nContent-length: 8\r\n\r\nHi there")
            tsock.remove()
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(("192.168.0.192", 8000))
    sock.listen(5)
    
    stackless.tasklet(stackless_accept)(sock, simple_handler)
    stackless.run()
    
    1 回复  |  直到 12 年前
        1
  •  14
  •   S.Lott    16 年前

    两件事。

    首先,请使类名以大写字母开头。它更传统,更容易阅读。

    更重要的是,在 stackless_accept 你积累的函数 list 属于 Sock 对象,命名为 sockets . 这个名单似乎在不断增长。是的,你有一个 remove ,但它不是 总是 已调用。如果套接字出错,那么它似乎将永远留在集合中。