2009-02-16 51 views
8

所以我用堆棧python,寫一個非常簡單的網絡服務器,教自己用microthreads/tasklets編程。但現在對我的問題,當我在Apache板凳上運行諸如ab -n 100000 -c 50 http://192.168.0.192/(100k請求,50個併發)時,我得到類似6k的請求/秒,第二次運行它我得到5.5k,第三次5k,第四次,4.5 k等一路下降到100req/s什麼的。Stackless python網絡性能隨着時間的推移而降低?

但是,當我重新啓動python腳本時,問題就消失了。

現在我的問題是爲什麼?我忘了刪除小工具嗎?我已經檢查了stackless.getrunco​​unt()(並且由於某種原因它總是返回1),所以它看起來好像沒有任何死的tasklets在附近?我試過在完成的所有tasklet上調用.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() 

回答

14

兩件事。

首先,請使類名以大寫字母開頭。這是更傳統和更容易閱讀。

更重要的是,在stackless_accept函數中,您累積了list個對象,其名稱爲sockets。這份名單似乎無限增長。是的,你有一個remove,但它不是總是調用。如果套接字出現錯誤,那麼看起來它將永遠留在集合中。

相關問題