【问题标题】:python - When are WebSocketHandler and TornadoWebSocketClient completely deleted?python - WebSocketHandler 和 TornadoWebSocketClient 何时完全删除?
【发布时间】:2015-06-12 15:11:04
【问题描述】:

我正在开发一个必须支持客户端-服务器连接的应用程序。为了做到这一点,我正在使用允许我创建 WebSockets 的龙卷风模块。我打算一直在运行,至少在服务器端。所以我非常担心在这些连接上创建的每个对象的性能和内存使用情况。 我已经开始进行测试以检测这些对象何时被库消除。 以示例代码为例,我重写了方法__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.WebSocketHandlerdocumentation,它解释了我何时“关闭”对象,但我不知道何时释放内存。

【问题讨论】:

    标签: python object websocket tornado


    【解决方案1】:

    WebSocket 代码当前包含一些引用循环,这意味着直到下一次完整 GC 才会清理对象。更糟糕的是,__del__ 方法实际上可以防止删除对象(在 python 3.3 和更早版本中:https://docs.python.org/3.3/library/gc.html#gc.garbage),因此很难判断什么时候实际删除了对象。相反,您只需对系统进行负载测试,看看它的内存占用是否会随着时间的推移而增加。

    (欢迎在连接关闭后打断引用循环的补丁)

    【讨论】:

    • 为了避免这些参考周期,weakref 是一个选项吗?还是和它无关?
    • 我不确定weakref 是否有助于当前 GC 中的循环(包括弱引用的循环仍然是一个循环)。在这种情况下,我们已经有一些明确的清理代码(我们关闭 IOStream 并从 IOLoop 中删除处理程序),因此我们只需确保将任何可能导致循环(并且不再需要)的属性设置为 None .
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 2018-10-22
    • 2020-11-01
    • 2017-07-20
    相关资源
    最近更新 更多