2015-06-12 8 views
5

Pracuję nad aplikacją, która musi obsługiwać połączenia klient-serwer. W tym celu korzystam z modułu tornado, który pozwala mi tworzyć WebSockets. Zamierzam być zawsze w akcji, przynajmniej po stronie serwera. Dlatego bardzo martwię się wydajnością i wykorzystaniem pamięci każdego z obiektów utworzonych na tych połączeniach. Zacząłem robić testy, aby wykryć, kiedy te obiekty zostały usunięte przez bibliotekę. Weźmy przykładowy kod i nadpisałeś metodę __del__()python - Kiedy WebSocketHandler i TornadoWebSocketClient są całkowicie usunięte?

server.py

#! /usr/bin/env python 
import tornado.httpserver 
import tornado.websocket 
import tornado.ioloop 
import tornado.web 
import gc, sys 
import resource 

class WSHandler(tornado.websocket.WebSocketHandler): 
    def open(self): 
     print 'new connection' 
     self.write_message("h") 

    def check_origin(self, origin): 
     return True 

    def on_message(self, message): 
     print "Message: " + message 

    def on_close(self): 
     print 'Closed' 
     print 'GC count: ' + str(len(gc.get_referrers(self))) 

    def __del__(self): 
     print "DELETED" 

application = tornado.web.Application([ 
    (r'/s', WSHandler), 
]) 


if __name__ == "__main__": 
    http_server = tornado.httpserver.HTTPServer(application) 
    http_server.listen(8888) 
    tornado.ioloop.IOLoop.instance().start() 

client.py

#! /usr/bin/env python 
from ws4py.client.tornadoclient import TornadoWebSocketClient 
from tornado import ioloop 

class MainClient(TornadoWebSocketClient): 
    def opened(self): 
     print "Connected" 

    def received_message(self, message): 
     print "Message" 

     #I close the connection 
     self.close() 

    def closed(self, code, reason=None): 
     print "Closed" 
     ioloop.IOLoop.instance().stop() 

    def __del__(self): 
     print "DELETED" 

if __name__ == "__main__": 
    ws = MainClient('ws://localhost:8888/s', protocols=['http-only', 'chat']) 
    ws.connect() 

    ioloop.IOLoop.instance().start() 

Gdy klient otrzymuje wiadomość, że zamyka połączenie. Miałem nadzieję, że oba obiekty zostały wyeliminowane, ponieważ połączenie zostało zamknięte, dlatego należy wywołać metodę __del__(), ale tak się nie stało.

wyjście Serwer: wyjście

new connection 
Closed 
GC count: 6 

klient:

Connected 
Message 
Closed 

Jak widać nie wydrukować DELETED zdanie, że spodziewałem się ze sposobu __del__().

--edited--

Również dodaniu linii, który drukuje się numer odniesienia, które ma GC tego przedmiotu w czasie zamykania połączenia. Dowodzi to, że rzeczywiście istnieją cykle referencyjne.

-----

oczywiście zajęcia, że ​​będę używać będzie bardziej skomplikowane niż te, ale pomagają mi zrozumieć zachowanie obu obiektów, co jest, co naprawdę starają się wiedzieć: kiedy Czy są one usunięte? Czy uwalnia pamięć po jej usunięciu? lub w inny sposób stawać się jakoś? lub ¿jak jawnie usunąć obiekt?

Przeczytałem tornado.websocket.WebSocketHandlerdocumentation, wyjaśniono mi, kiedy obiekt jest "zamknięty", ale nie wiem, kiedy pamięć zostanie zwolniona.

Odpowiedz

3

Kod WebSocket zawiera obecnie kilka cykli referencyjnych, co oznacza, że ​​obiekty nie są czyszczone aż do następnego pełnego GC. Co gorsza, metody mogą faktycznie uniemożliwić usunięcie obiektu (w pythonie 3.3 i starszym: https://docs.python.org/3.3/library/gc.html#gc.garbage), więc trudno jest stwierdzić, kiedy rzeczy faktycznie są usuwane. Zamiast tego musisz po prostu załadować test systemu i sprawdzić, czy jego ślad pamięciowy rośnie z czasem.

(Patches zerwać cykle odniesienia po zamknięciu połączenia byłoby mile widziane)

+0

Aby uniknąć tych cykli odniesienia, byłoby 'weakref' opcję? Lub nie ma nic do robienia z niego odrobinę? –

+1

Nie jestem pewien, czy 'weakref' pomaga z cyklami w bieżącym GC (cykl zawierający słabe referencje jest nadal cyklem).W tym przypadku mamy już jakiś wyraźny kod czyszczenia (gdzie zamykamy IOStream i usuwamy handler z IOLoop), więc musimy po prostu upewnić się, że wszelkie atrybuty, które mogą powodować cykl (i nie są już potrzebne) są ustawione na Brak . –

Powiązane problemy