2009-02-16 10 views
8

तो मैं स्टैकलेस पायथन के साथ चारों ओर घूम रहा हूं, लिखना बहुत आसान वेबसर्वर खुद को माइक्रोथ्रेड/टास्कलेट के साथ प्रोग्रामिंग सिखाने के लिए। लेकिन अब मेरी समस्या के लिए, जब मैं अपाचे बैंच में ab -n 100000 -c 50 http://192.168.0.192/ (100k अनुरोध, 50 concurrency) जैसे कुछ चलाता हूं तो मुझे 6k req/s की तरह कुछ मिलता है, दूसरी बार जब मैं इसे चलाता हूं तो मुझे 5.5k, तीसरा समय 5k, चौथा समय, 4.5 मिलता है के, आदि सभी तरह से 100req/एस या कुछ करने के लिए।स्टैकलेस पायथन नेटवर्क प्रदर्शन समय के साथ घट रहा है?

समस्या जब मैं पाइथन लिपि को पुनरारंभ करता हूं तो समस्या दूर हो जाती है।

अब मेरा प्रश्न है क्यों? क्या मैं टास्कलेट को मिटाना भूल रहा हूं? मैंने 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 समारोह में आप एक Sock की list वस्तुओं, sockets नामित जमा। यह सूची अंतहीन रूप से बढ़ती प्रतीत होती है। हां, आपके पास remove है, लेकिन यह हमेशा नहीं है। यदि सॉकेट को कोई त्रुटि मिलती है, तो ऐसा प्रतीत होता है कि इसे हमेशा संग्रह में छोड़ा जाएगा।

संबंधित मुद्दे