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.WebSocketHandler
documentation, wyjaśniono mi, kiedy obiekt jest "zamknięty", ale nie wiem, kiedy pamięć zostanie zwolniona.
Aby uniknąć tych cykli odniesienia, byłoby 'weakref' opcję? Lub nie ma nic do robienia z niego odrobinę? –
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 . –