Я работаю с большими файлами, имеющими несколько миллионов записей каждый (около 2 ГБ распакованных, несколько сотен мегабайт gzip).Вероятная утечка памяти в контуре генератора с помощью islice
Я перебираю записи с islice
, что позволяет мне получить небольшую порцию (для отладки и разработки) или все, когда я хочу протестировать код. Я заметил абсурдно большое использование памяти для моего кода, и поэтому я пытаюсь найти утечку памяти в своем коде.
Ниже представлен вывод memory_profiler на парном чтении (где я открываю два файла и записываю их в архив), ТОЛЬКО 10 ** 5 значений (значение по умолчанию становится перезаписанным).
Line # Mem usage Increment Line Contents
================================================
137 27.488 MiB 0.000 MiB @profile
138 def paired_read(read1, read2, nbrofitems = 10**8):
139 """ Procedure for reading both sequences and stitching them together """
140 27.488 MiB 0.000 MiB seqFreqs = Counter()
141 27.488 MiB 0.000 MiB linker_str = "~"
142 #for rec1, rec2 in izip(read1, read2):
143 3013.402 MiB 2985.914 MiB for rec1, rec2 in islice(izip(read1, read2), nbrofitems):
144 3013.398 MiB -0.004 MiB rec1 = rec1[9:] # Trim the primer variable sequence
145 3013.398 MiB 0.000 MiB rec2 = rec2[:150].reverse_complement() # Trim the low quality half of the 3' read AND take rev complement
146 #aaSeq = Seq.translate(rec1 + rec2)
147
148 global nseqs
149 3013.398 MiB 0.000 MiB nseqs += 1
150
151 3013.402 MiB 0.004 MiB if filter_seq(rec1, direction=5) and filter_seq(rec2, direction=3):
152 3013.395 MiB -0.008 MiB aakey = str(Seq.translate(rec1)) + linker_str + str(Seq.translate(rec2))
153 3013.395 MiB 0.000 MiB seqFreqs.update({ aakey : 1 })
154
155 3013.402 MiB 0.008 MiB print "========================================"
156 3013.402 MiB 0.000 MiB print "# of total sequences: %d" % nseqs
157 3013.402 MiB 0.000 MiB print "# of filtered sequences: %d" % sum(seqFreqs.values())
158 3013.461 MiB 0.059 MiB print "# of repeated occurances: %d" % (sum(seqFreqs.values()) - len(list(seqFreqs)))
159 3013.461 MiB 0.000 MiB print "# of low-score sequences (<20): %d" % lowQSeq
160 3013.461 MiB 0.000 MiB print "# of sequences with stop codon: %d" % starSeqs
161 3013.461 MiB 0.000 MiB print "========================================"
162 3013.504 MiB 0.043 MiB pprint(seqFreqs.most_common(100), width = 240)
Код, в общем, делает некоторую фильтрацию записей и отслеживает, сколько раз строка происходит в файле (архивные пару строк в данном конкретном случае).
100 000 строк из 150 символов с целыми значениями в счетчике должны располагаться на вершинах 100 МБ, которые я проверил, используя следующую функцию: @AaronHall.
Учитывая вывод memory_profiler, я подозреваю, что islice не отпускает предыдущие объекты в течение итерации. Поиск в Google приземлился на this bug report, однако он отмечен как разрешенный для Python 2.7, который я сейчас запускаю.
Любые мнения?
EDIT: Я попытался пропустить islice
как на комментарий ниже, и использовать цикл как
for rec in list(next(read1) for _ in xrange(10**5)):
, который не делает никаких существенных различий. Это относится к одному файлу, чтобы избежать izip
, который также поступает от itertools
.
Вторая проблема, связанная с поиском и устранением неисправностей, заключалась в том, чтобы проверить, читает и расширяет ли файл gzip.open()
файл и поэтому вызывает здесь проблему. Однако запуск сценария в распакованных файлах не имеет значения.
Попробуйте использовать версию [pure Python] (https://docs.python.org/3/library/itertools.html#itertools.islice) для проверки гипотезы утечки. Или просто отпустите 'islice' и используйте счетчик с' if'. –
@SergeiLebedev, как вы это понимаете? is 'islice' не чистый питон? – posdef
Нет, весь модуль 'itertools' реализован в C, [включая] (https://hg.python.org/cpython/file/2.7/Modules/itertoolsmodule.c#l1123) функцию' islice'. –