Một trong các ứng dụng python của tôi dường như bị rò rỉ bộ nhớ, đánh giá việc sử dụng bộ nhớ tăng dần. Giả thuyết của tôi là một tham chiếu tuần hoàn ở đâu đó, bất chấp những nỗ lực tốt nhất để tránh điều này. Để cô lập vấn đề tôi đang tìm cách để kiểm tra thủ công các mục không thể truy cập, một công cụ nhằm mục đích gỡ lỗi hoàn toàn.gặp khó khăn khi tìm hiểu gc.garbage của python (để truy tìm rò rỉ bộ nhớ)
Mô-đun gc có vẻ như có khả năng theo dõi cần thiết và tôi đã thử mã sau nhằm mục đích biên soạn danh sách các mục không thể truy cập được tạo thành từ cuộc gọi cuối cùng. Cuộc gọi đầu tiên chỉ đặt một trạm kiểm soát cơ sở và sẽ không xác định các mục không thể truy cập được.
def unreachable():
# first time setup
import gc
gc.set_threshold(0) # only manual sweeps
gc.set_debug(gc.DEBUG_SAVEALL) # keep unreachable items as garbage
gc.enable() # start gc if not yet running (is this necessary?)
# operation
if gc.collect() == 0:
return 'no unreachable items'
s = 'unreachable items:\n ' \
+ '\n '.join('[%d] %s' % item for item in enumerate(gc.garbage))
_deep_purge_list(gc.garbage) # remove unreachable items
return s # return unreachable items as text
nhằm phá vỡ chu kỳ và xóa đối tượng theo cách thủ công. Việc thực hiện sau xử lý một số trường hợp phổ biến nhưng không gần chặt nước. Câu hỏi đầu tiên của tôi liên quan đến điều này, xem xuống.
def _deep_purge_list(garbage):
for item in garbage:
if isinstance(item, dict):
item.clear()
if isinstance(item, list):
del item[:]
try:
item.__dict__.clear()
except:
pass
del garbage[:]
Dựa trên thử nghiệm rất hạn chế, thiết lập có vẻ hoạt động đúng. Các tài liệu tham khảo theo chu kỳ sau báo cáo một cách chính xác một lần:
class A(object):
def __init__(self):
self.ref = self
print unreachable()
# no unreachable items
A()
print unreachable()
# unreachable items:
# [0] <__main__.A object at 0xb74579ac>
# [1] {'ref': <__main__.A object at 0xb74579ac>}
print unreachable()
# no unreachable items
Tuy nhiên với một cái gì đó sau lẻ xảy ra:
print unreachable()
# no unreachable items
import numpy
print unreachable()
# unreachable items:
# [0] (<type '_ctypes.Array'>,)
# [1] {'__module__': 'numpy.ctypeslib', '__dict__': <attribute '__dict__' of 'c_long_Array_1' objects>, '__weakref__': <attribute '__weakref__' of 'c_long_Array_1' objects>, '_length_': 1, '_type_': <class 'ctypes.c_long'>, '__doc__': None}
# [2] <class 'numpy.ctypeslib.c_long_Array_1'>
# [3] <attribute '__dict__' of 'c_long_Array_1' objects>
# [4] <attribute '__weakref__' of 'c_long_Array_1' objects>
# [5] (<class 'numpy.ctypeslib.c_long_Array_1'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>)
print unreachable()
# unreachable items:
# [0] (<type '_ctypes.Array'>,)
# [1] {}
# [2] <class 'c_long_Array_1'>
# [3] (<class 'c_long_Array_1'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>)
lời gọi nhiều lần vẫn tiếp tục quay mà kết quả cuối cùng. Vấn đề không xảy ra khi không thể truy cập được lần đầu tiên sau khi nhập. Tuy nhiên, tại thời điểm này tôi không có lý do gì để tin rằng vấn đề này có tính chất cụ thể; tôi đoán là nó phơi bày một lỗ hổng trong cách tiếp cận của tôi.
Câu hỏi của tôi:
- Có cách nào tốt hơn để loại bỏ các mục trong gc.garbage? Lý tưởng nhất, là có một cách để có gc loại bỏ chúng, như nó sẽ (nên?) Đã thực hiện mà không DEBUG_SAVEALL?
- Ai đó có thể giải thích vấn đề với việc nhập khẩu khó khăn và/hoặc đề xuất các cách khắc phục sự cố không?
suy nghĩ:
Dường như mã dưới đây biểu diễn gần dự định:
def unreachable():
import gc
gc.set_threshold(0)
gc.set_debug(gc.DEBUG_LEAK)
gc.enable()
print 'collecting {{{'
gc.collect()
print '}}} done'
Tuy nhiên, để gỡ lỗi Tôi thích biểu diễn chuỗi phong phú hơn loại/id theo quy định của gc. Hơn nữa tôi muốn hiểu sai sót trong cách tiếp cận cũ của tôi, và tìm hiểu điều gì đó về mô-đun gc.
trân trọng sự giúp đỡ của bạn,
Gertjan
Cập nhật 05/06:
tôi chạy vào một tình huống mà việc thực hiện đầu tiên đã không báo cáo bất kỳ mặt hàng không thể truy cập, trừ khi người dân địa phương() được gọi ngay trước khi cho nó (loại bỏ giá trị trả lại). Không hiểu làm thế nào điều này có thể ảnh hưởng đến việc theo dõi đối tượng của gc, điều này khiến tôi bối rối hơn. Tôi không chắc chắn sẽ dễ dàng như thế nào để xây dựng một ví dụ nhỏ thể hiện vấn đề này, nhưng nếu nhu cầu đòi hỏi nó tôi có thể cho nó một shot.
Tôi chỉ đọc lướt qua, nhưng bạn có thể đã hiểu nhầm 'gc.DEBUG_SAVEALL': nó có nghĩa là gắn thêm các đối tượng được giải phóng vào' gc.garbage' (thay vì chỉ giải phóng chúng). – blueyed