2015-06-12 4 views
5

Я работаю над приложением, которое должно поддерживать соединения клиент-сервер. Для этого я использую модуль торнадо, который позволяет мне создавать WebSockets. Я намерен всегда работать, по крайней мере, на стороне сервера. Поэтому меня очень беспокоит производительность и использование памяти каждого из объектов, созданных в этих соединениях. Я начал выполнять тесты, чтобы определить, когда эти объекты будут уничтожены библиотекой. Возьмем пример кода, и я переписал метод __del__()python - Когда полностью удалены WebSocketHandler и TornadoWebSocketClient?

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() 

Когда клиент получает сообщение, он закрывает соединение. Я надеялся, что оба объекта были устранены, потому что соединение было закрыто, поэтому вызовите метод __del__(), но этого не произошло. Выход сервера

: выход

new connection 
Closed 
GC count: 6 

клиента:

Connected 
Message 
Closed 

Как вы можете видеть, что это не напечатать DELETED фразы, что я ожидал от метода __del__().

--edited--

Также я добавил строку, которая выводит количество ссылок, которое имеет GC этого объекта в момент закрытия соединения. Это доказывает, что существуют действительно циклы ссылок.

-----

Очевидно, что классы, которые я буду использовать будет более сложным, чем те, но помочь мне понять поведение обоих объектов, что является то, что я на самом деле стремятся знать: когда они удалены? Это освобождает память при удалении их? или каким-то иным образом? или ¿как удалить объект явно?

Я читал tornado.websocket.WebSocketHandlerdocumentation, он объясняет мне, когда объект «закрыт», но я не знаю, когда будет выпущена память.

ответ

3

Код WebSocket в настоящее время содержит некоторые ссылочные циклы, что означает, что объекты не очищаются до следующего полного GC. Хуже того, методы __del__ могут фактически предотвратить удаление объекта (в python 3.3 и старше: https://docs.python.org/3.3/library/gc.html#gc.garbage), поэтому трудно сказать, когда вещи фактически удаляются. Вместо этого вам нужно просто загрузить тестовую систему и посмотреть, увеличивается ли ее объем памяти с течением времени.

(Патчи к разбивают опорные циклы после того, как соединение закрыты будут приветствоваться)

+0

Чтобы избежать этих опорных циклов, будет 'weakref' варианта? Или нечего делать? –

+1

Я не уверен, что «weakref» помогает с циклами в текущем GC (цикл, включающий слабые ссылки, по-прежнему является циклом).В этом случае у нас уже есть явный код очистки (где мы закрываем IOStream и удаляем обработчик из IOLoop), поэтому нам просто нужно убедиться, что любые атрибуты, которые могут вызвать цикл (и больше не нужны), установлены на None , –