gc的性能问题
在优化日志落盘的任务里,为了避免消费日志队列过慢导致爆队列,其中一个优化是快速消费队列并全部缓存到 deque 里,再慢慢落盘
但测试时发现,虽然理论上 deque
的 append
是 O(1) 的,但实际表现是 append 时不时会变慢(体现为消费队列并 append
变慢导致队列爆掉),且随着 deque
变大,对应的延迟会变高
这个问题表现类似 is there a way to circumvent python list append becoming progressively slower,所以猜测可能也是 gc
导致的,禁用 gc
后确实不会变慢了,但随后发现引入了内存泄露,即虽然 deque
里缓存的元素被消费完了,但进程内存用量不会下降
由于 gc
只被用于回收有循环引用的对象,所以猜测是项目里的某些对象有循环引用,定位到了如下代码:
class Foo:
@property
def bar(self):
try:
return self._bar
except AttributeError:
self._bar = self.c_bar.contents
return self._bar
其中 c_bar
是一个 ctypes.POINTER
,在命中 AttributeError
时的逻辑会使 self._bar
引用 self.c_bar
,产生循环引用,改掉这里后内存泄露消失