Python Twisted:使用connectProtocol连接端点导致内存泄漏?

Python Twisted:使用connectProtocol连接端点导致内存泄漏?,python,memory-leaks,twisted,Python,Memory Leaks,Twisted,我正试图建立一个服务器。除了像普通服务器那样接受来自客户端的连接之外,我的服务器还将作为客户端连接其他服务器 我已设置协议和端点,如下所示: p = FooProtocol() client = TCP4ClientEndpoint(reactor, '127.0.0.1' , 8080) # without ClientFactory 然后,在调用reactor.run()之后,服务器将侦听/接受新的套接字连接。当建立新的套接字连接(在ConnectionMode中)时,服务器将调用conn

我正试图建立一个服务器。除了像普通服务器那样接受来自客户端的连接之外,我的服务器还将作为客户端连接其他服务器

我已设置协议和端点,如下所示:

p = FooProtocol()
client = TCP4ClientEndpoint(reactor, '127.0.0.1' , 8080) # without ClientFactory
然后,在调用reactor.run()之后,服务器将侦听/接受新的套接字连接。当建立新的套接字连接(在ConnectionMode中)时,服务器将调用
connectProtocol(client,p)
,其行为类似于下面的伪代码:

while server accept new socket:
    connectProtocol(client, p)
    # client.client.connect(foo_client_factory)    --> connecting in this way won't
    #                                                  cause memory leak
当连接到客户端时,内存逐渐消耗(显式调用
gc
不起作用)

我是否以错误的方式使用Twisted

-----更新-----

我的测试程序:服务器等待客户端连接。当从客户端建立连接时,服务器将创建50个到其他服务器的连接

代码如下:

#! /usr/bin/env python

import sys
import gc

from twisted.internet import protocol, reactor, defer, endpoints
from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol

class MyClientProtocol(protocol.Protocol):
    def connectionMade(self):
        self.transport.loseConnection()

class MyClientFactory(protocol.ClientFactory):
    def buildProtocol(self, addr):
        p = MyClientProtocol()
        return p

class ServerFactory(protocol.Factory):
    def buildProtocol(self, addr):
        p = ServerProtocol()
        return p

client_factory = MyClientFactory() # global
client_endpoint = TCP4ClientEndpoint(reactor, '127.0.0.1' , 8080) # global

times = 0

class ServerProtocol(protocol.Protocol):
    def connectionMade(self):
        global client_factory
        global client_endpoint
        global times

        for i in range(50):
            # 1)
            p = MyClientProtocol()
            connectProtocol(client_endpoint, p) # cause memleak

            # 2)
            #client_endpoint.connect(client_factory) # no memleak

        times += 1
        if times % 10 == 9:
            print 'gc'
            gc.collect() # doesn't work

        self.transport.loseConnection()

if __name__ == '__main__':
    server_factory = ServerFactory()
    serverEndpoint = endpoints.serverFromString(reactor, "tcp:8888")
    serverEndpoint.listen(server_factory)
    reactor.run()

此程序不执行任何扭曲日志初始化。这意味着它在整个运行过程中都使用“log初学者”。日志初学者在
LimitedHistoryLogoObserver
中记录它观察到的所有日志事件(最多可配置一个最大值)

日志初学者保留2**16(
\u DEFAULT\u BUFFER\u MAXIMUM
)事件,然后开始抛出旧事件,可能是为了避免在程序从未配置其他观察者的情况下消耗所有可用内存

如果您将Twisted source的
\u DEFAULT\u BUFFER\u MAXIMUM
设置为较小的值(例如10),则程序不再“泄漏”。当然,它实际上只是一个对象泄漏,而不是内存泄漏,它受到2**16限制的限制

但是,
connectProtocol
每次调用时都会创建一个新工厂。创建每个新工厂时,都会记录一条消息。应用程序代码为每条日志消息生成一个新的
记录器
。日志代码将新的
记录器
放入日志消息中。这意味着保存这些日志消息的内存开销是相当可观的(相比之下,只泄漏一小段文本,甚至泄漏一条包含几个简单对象的dict)

我想说Twisted中的代码正按预期运行。。。但也许有人没有完全考虑到这种行为的后果

当然,如果您配置了自己的日志观察器,那么“日志初学者”将从图片中删除,并且没有问题。所有严肃的程序都可以相当快地启用日志记录并避免这个问题,这似乎是合理的。然而,许多简短的一次性程序或示例程序通常不会初始化日志记录,而是依赖于打印,这使它们受制于这种行为


注意在中报告并修复了此问题,因此Twisted 17将不会有此行为。

这听起来可能是Twisted中的错误,但您在此处没有附加足够的代码来说明。你能附上一个完整的程序吗?谢谢回复!我的测试代码已经更新了。这里确实出现了漏洞。事实上,我在这两个示例中都发现了漏洞,尽管在基于connectProtocol的示例中速度要快一点。这肯定是Twisted中的一个bug,我们需要进行调查。