2009-02-16 2 views
8

그래서 stackless python을 가지고 놀고 있는데, 매우 간단한 웹 서버를 사용하여 microthreads/tasklet 프로그래밍을 가르칩니다. 하지만 지금 내 문제에, 내가 아파치 벤치에서 ab -n 100000 -c 50 http://192.168.0.192/ (100k 요청, 50 동시성)과 같은 것을 실행하면 6k req/s와 비슷한 결과를 얻는다. 두 번째로 나는 5.5k, 세 번째 시간은 5k, 네 번째는 4.5를 얻는다. k, 등등까지 100req/s 또는 뭔가.시간이 지남에 따라 스택없는 파이썬 네트워크 성능이 저하됩니까?

파이썬 스크립트를 다시 시작하면 문제가 해결됩니다.

내 질문이 여기에 있습니다. 내가 tasklets을 삭제하는 것을 잊고 있습니까? 나는 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() 

답변

14

두 가지.

먼저 클래스 이름을 대문자로 시작하도록하십시오. 더 일반적이며 읽기 쉽습니다.

더 중요한 것은 stackless_accept 함수에 sockets이라는 의 Sock 개체가 누적됩니다. 이 목록은 끝없이 성장하는 것으로 보입니다. 예, 당신은 remove이지만, 은 항상이 아닙니다. 소켓에 오류가 발생하면 컬렉션에 영원히 남아있는 것으로 보입니다.

관련 문제