python - WebSocketHandler 和 TornadoWebSocketClient 何时完全删除?
python - When are WebSocketHandler and TornadoWebSocketClient completely deleted?
我正在开发一个必须支持客户端-服务器连接的应用程序。为此,我使用了允许我创建 WebSocket 的 tornado 模块。我打算始终处于运行状态,至少在服务器端。所以我非常担心在这些连接上创建的每个对象的性能和内存使用情况。
我已经开始进行测试以检测这些对象实际上何时被库消除了。
以示例代码为例,我重写了方法 __del__()
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
如您所见,它没有打印出我期望从 __del__()
方法中得到的 DELETED
句子。
--已编辑--
我还添加了打印引用数的行,该引用数在关闭连接时具有该对象的 GC。这证明确实存在引用循环
-----
显然,我将使用的 类 会比那些更复杂,但可以帮助我理解这两个对象的行为,这是我真正想知道的:它们何时被删除?删除它们时会释放内存吗?或者以其他方式成为某种方式?或 ¿如何显式删除对象?
我看了tornado.websocket.WebSocketHandler
documentation,它解释了我什么时候对象是"closed",但我不知道什么时候释放内存。
WebSocket 代码目前包含一些循环引用,这意味着直到下一次完整 GC 才会清理对象。更糟糕的是,__del__
方法实际上可以阻止对象的删除(在 python 3.3 和更早的版本中:https://docs.python.org/3.3/library/gc.html#gc.garbage),所以很难判断什么时候真正被删除了。相反,您只需要对系统进行负载测试,看看它的内存占用量是否会随着时间的推移而增加。
(欢迎在连接关闭后打断引用循环的补丁)
我正在开发一个必须支持客户端-服务器连接的应用程序。为此,我使用了允许我创建 WebSocket 的 tornado 模块。我打算始终处于运行状态,至少在服务器端。所以我非常担心在这些连接上创建的每个对象的性能和内存使用情况。
我已经开始进行测试以检测这些对象实际上何时被库消除了。
以示例代码为例,我重写了方法 __del__()
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
如您所见,它没有打印出我期望从 __del__()
方法中得到的 DELETED
句子。
--已编辑--
我还添加了打印引用数的行,该引用数在关闭连接时具有该对象的 GC。这证明确实存在引用循环
-----
显然,我将使用的 类 会比那些更复杂,但可以帮助我理解这两个对象的行为,这是我真正想知道的:它们何时被删除?删除它们时会释放内存吗?或者以其他方式成为某种方式?或 ¿如何显式删除对象?
我看了tornado.websocket.WebSocketHandler
documentation,它解释了我什么时候对象是"closed",但我不知道什么时候释放内存。
WebSocket 代码目前包含一些循环引用,这意味着直到下一次完整 GC 才会清理对象。更糟糕的是,__del__
方法实际上可以阻止对象的删除(在 python 3.3 和更早的版本中:https://docs.python.org/3.3/library/gc.html#gc.garbage),所以很难判断什么时候真正被删除了。相反,您只需要对系统进行负载测试,看看它的内存占用量是否会随着时间的推移而增加。
(欢迎在连接关闭后打断引用循环的补丁)