tracemalloc
— Trace memory allocations¶
Нове в версії 3.4.
Вихідний код: Lib/tracemalloc.py
Модуль tracemalloc — це інструмент налагодження для відстеження блоків пам’яті, виділених Python. Він надає таку інформацію:
Зворотне відстеження місця розміщення об’єкта
Статистика виділених блоків пам’яті на ім’я файлу та номер рядка: загальний розмір, кількість і середній розмір виділених блоків пам’яті
Обчисліть різницю між двома знімками, щоб виявити витоки пам’яті
Для відстеження більшості блоків пам’яті, виділених Python, модуль слід запускати якомога раніше, встановивши змінну середовища PYTHONTRACEMALLOC
на 1
або використовуючи -X
tracemalloc
параметр командного рядка. Функцію tracemalloc.start()
можна викликати під час виконання, щоб розпочати відстеження розподілу пам’яті Python.
За замовчуванням трасування виділеного блоку пам’яті зберігає лише останній кадр (1 кадр). Щоб зберегти 25 кадрів під час запуску: установіть для змінної середовища PYTHONTRACEMALLOC
значення 25
або скористайтеся параметром командного рядка -X
tracemalloc=25
.
Приклади¶
Покажіть 10 найкращих¶
Відобразити 10 файлів, які виділяють найбільше пам’яті:
import tracemalloc
tracemalloc.start()
# ... run your application ...
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print("[ Top 10 ]")
for stat in top_stats[:10]:
print(stat)
Приклад результату набору тестів Python:
[ Top 10 ]
<frozen importlib._bootstrap>:716: size=4855 KiB, count=39328, average=126 B
<frozen importlib._bootstrap>:284: size=521 KiB, count=3199, average=167 B
/usr/lib/python3.4/collections/__init__.py:368: size=244 KiB, count=2315, average=108 B
/usr/lib/python3.4/unittest/case.py:381: size=185 KiB, count=779, average=243 B
/usr/lib/python3.4/unittest/case.py:402: size=154 KiB, count=378, average=416 B
/usr/lib/python3.4/abc.py:133: size=88.7 KiB, count=347, average=262 B
<frozen importlib._bootstrap>:1446: size=70.4 KiB, count=911, average=79 B
<frozen importlib._bootstrap>:1454: size=52.0 KiB, count=25, average=2131 B
<string>:5: size=49.7 KiB, count=148, average=344 B
/usr/lib/python3.4/sysconfig.py:411: size=48.0 KiB, count=1, average=48.0 KiB
Ми бачимо, що Python завантажив дані 4855 KiB
(байт-код і константи) з модулів і що модуль collections
виділив 244 KiB
для створення типів namedtuple
.
Перегляньте Snapshot.statistics()
для отримання додаткових параметрів.
Обчислити відмінності¶
Зробіть два знімки та покажіть відмінності:
import tracemalloc
tracemalloc.start()
# ... start your application ...
snapshot1 = tracemalloc.take_snapshot()
# ... call the function leaking memory ...
snapshot2 = tracemalloc.take_snapshot()
top_stats = snapshot2.compare_to(snapshot1, 'lineno')
print("[ Top 10 differences ]")
for stat in top_stats[:10]:
print(stat)
Приклад результату до/після виконання деяких тестів набору тестів Python:
[ Top 10 differences ]
<frozen importlib._bootstrap>:716: size=8173 KiB (+4428 KiB), count=71332 (+39369), average=117 B
/usr/lib/python3.4/linecache.py:127: size=940 KiB (+940 KiB), count=8106 (+8106), average=119 B
/usr/lib/python3.4/unittest/case.py:571: size=298 KiB (+298 KiB), count=589 (+589), average=519 B
<frozen importlib._bootstrap>:284: size=1005 KiB (+166 KiB), count=7423 (+1526), average=139 B
/usr/lib/python3.4/mimetypes.py:217: size=112 KiB (+112 KiB), count=1334 (+1334), average=86 B
/usr/lib/python3.4/http/server.py:848: size=96.0 KiB (+96.0 KiB), count=1 (+1), average=96.0 KiB
/usr/lib/python3.4/inspect.py:1465: size=83.5 KiB (+83.5 KiB), count=109 (+109), average=784 B
/usr/lib/python3.4/unittest/mock.py:491: size=77.7 KiB (+77.7 KiB), count=143 (+143), average=557 B
/usr/lib/python3.4/urllib/parse.py:476: size=71.8 KiB (+71.8 KiB), count=969 (+969), average=76 B
/usr/lib/python3.4/contextlib.py:38: size=67.2 KiB (+67.2 KiB), count=126 (+126), average=546 B
Ми бачимо, що Python завантажив 8173 KiB
даних модуля (байт-код і константи), і що це на 4428 KiB
більше, ніж було завантажено до тестів, коли було зроблено попередній знімок. Подібним чином модуль linecache
кешував 940 КіБ
вихідного коду Python для форматування відстеження, усе це з попереднього знімка.
Якщо в системі мало вільної пам’яті, знімки можна записати на диск за допомогою методу Snapshot.dump()
для аналізу знімка в автономному режимі. Потім скористайтеся методом Snapshot.load()
, перезавантажте знімок.
Отримати відстеження блоку пам’яті¶
Код для відображення зворотного відстеження найбільшого блоку пам’яті:
import tracemalloc
# Store 25 frames
tracemalloc.start(25)
# ... run your application ...
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('traceback')
# pick the biggest memory block
stat = top_stats[0]
print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024))
for line in stat.traceback.format():
print(line)
Приклад результату набору тестів Python (зворотне відстеження обмежено 25 кадрами):
903 memory blocks: 870.1 KiB
File "<frozen importlib._bootstrap>", line 716
File "<frozen importlib._bootstrap>", line 1036
File "<frozen importlib._bootstrap>", line 934
File "<frozen importlib._bootstrap>", line 1068
File "<frozen importlib._bootstrap>", line 619
File "<frozen importlib._bootstrap>", line 1581
File "<frozen importlib._bootstrap>", line 1614
File "/usr/lib/python3.4/doctest.py", line 101
import pdb
File "<frozen importlib._bootstrap>", line 284
File "<frozen importlib._bootstrap>", line 938
File "<frozen importlib._bootstrap>", line 1068
File "<frozen importlib._bootstrap>", line 619
File "<frozen importlib._bootstrap>", line 1581
File "<frozen importlib._bootstrap>", line 1614
File "/usr/lib/python3.4/test/support/__init__.py", line 1728
import doctest
File "/usr/lib/python3.4/test/test_pickletools.py", line 21
support.run_doctest(pickletools)
File "/usr/lib/python3.4/test/regrtest.py", line 1276
test_runner()
File "/usr/lib/python3.4/test/regrtest.py", line 976
display_failure=not verbose)
File "/usr/lib/python3.4/test/regrtest.py", line 761
match_tests=ns.match_tests)
File "/usr/lib/python3.4/test/regrtest.py", line 1563
main()
File "/usr/lib/python3.4/test/__main__.py", line 3
regrtest.main_in_temp_cwd()
File "/usr/lib/python3.4/runpy.py", line 73
exec(code, run_globals)
File "/usr/lib/python3.4/runpy.py", line 160
"__main__", fname, loader, pkg_name)
Ми бачимо, що найбільше пам’яті було виділено в модулі importlib
для завантаження даних (байт-код і константи) з модулів: 870.1 KiB
. Трасування – це місце, де importlib
завантажував дані останнім часом: у рядку import pdb
модуля doctest
. Трасування може змінитися, якщо завантажується новий модуль.
Досить топ¶
Код для відображення 10 рядків, які виділяють найбільшу кількість пам’яті, з гарним виведенням, ігноруючи файли <frozen importlib._bootstrap>
і <unknown>
:
import linecache
import os
import tracemalloc
def display_top(snapshot, key_type='lineno', limit=10):
snapshot = snapshot.filter_traces((
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "<unknown>"),
))
top_stats = snapshot.statistics(key_type)
print("Top %s lines" % limit)
for index, stat in enumerate(top_stats[:limit], 1):
frame = stat.traceback[0]
print("#%s: %s:%s: %.1f KiB"
% (index, frame.filename, frame.lineno, stat.size / 1024))
line = linecache.getline(frame.filename, frame.lineno).strip()
if line:
print(' %s' % line)
other = top_stats[limit:]
if other:
size = sum(stat.size for stat in other)
print("%s other: %.1f KiB" % (len(other), size / 1024))
total = sum(stat.size for stat in top_stats)
print("Total allocated size: %.1f KiB" % (total / 1024))
tracemalloc.start()
# ... run your application ...
snapshot = tracemalloc.take_snapshot()
display_top(snapshot)
Приклад результату набору тестів Python:
Top 10 lines
#1: Lib/base64.py:414: 419.8 KiB
_b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
#2: Lib/base64.py:306: 419.8 KiB
_a85chars2 = [(a + b) for a in _a85chars for b in _a85chars]
#3: collections/__init__.py:368: 293.6 KiB
exec(class_definition, namespace)
#4: Lib/abc.py:133: 115.2 KiB
cls = super().__new__(mcls, name, bases, namespace)
#5: unittest/case.py:574: 103.1 KiB
testMethod()
#6: Lib/linecache.py:127: 95.4 KiB
lines = fp.readlines()
#7: urllib/parse.py:476: 71.8 KiB
for a in _hexdig for b in _hexdig}
#8: <string>:5: 62.0 KiB
#9: Lib/_weakrefset.py:37: 60.0 KiB
self.data = set()
#10: Lib/base64.py:142: 59.8 KiB
_b32tab2 = [a + b for a in _b32tab for b in _b32tab]
6220 other: 3602.8 KiB
Total allocated size: 5303.1 KiB
Перегляньте Snapshot.statistics()
для отримання додаткових параметрів.
API¶
Функції¶
-
tracemalloc.
get_object_traceback
(obj)¶ Отримати зворотне відстеження, де було виділено об’єкт Python obj. Повертає екземпляр
Traceback
абоNone
, якщо модульtracemalloc
не відстежує виділення пам’яті або не відстежує виділення об’єкта.Дивіться також функції
gc.get_referrers()
іsys.getsizeof()
.
-
tracemalloc.
get_traceback_limit
()¶ Отримайте максимальну кількість кадрів, що зберігаються в зворотній трасі.
Модуль
tracemalloc
має відстежувати виділення пам’яті, щоб отримати обмеження, інакше виникає виняткова ситуація.Обмеження встановлюється функцією
start()
.
-
tracemalloc.
get_traced_memory
()¶ Отримайте поточний розмір і максимальний розмір блоків пам’яті, які відстежуються модулем
tracemalloc
, як кортеж:(current: int, peak: int)
.
-
tracemalloc.
get_tracemalloc_memory
()¶ Отримати дані про використання пам’яті в байтах модуля
tracemalloc
, який використовується для зберігання слідів блоків пам’яті. Повертаєint
.
-
tracemalloc.
is_tracing
()¶ True
, якщо модульtracemalloc
відстежує виділення пам’яті Python,False
інакше.
-
tracemalloc.
start
(nframe: int=1)¶ Почніть відстежувати виділення пам’яті Python: установіть перехоплювачі на розподільниках пам’яті Python. Зібрані зворотні трасування трасувань будуть обмежені кадрами nframe. За замовчуванням трасування блоку пам’яті зберігає лише останній кадр: обмеження становить
1
. nframe має бути більше або дорівнювати1
.Зберігання більш ніж 1 кадру корисне лише для обчислення статистики, згрупованої за
'traceback'
або для обчислення сукупної статистики: перегляньте методиSnapshot.compare_to()
іSnapshot.statistics()
.Зберігання більшої кількості кадрів збільшує навантаження на пам’ять і ЦП модуля
tracemalloc
. Використовуйте функціюget_tracemalloc_memory()
, щоб виміряти, скільки пам’яті використовується модулемtracemalloc
.Змінну середовища
PYTHONTRACEMALLOC
(PYTHONTRACEMALLOC=NFRAME
) і параметр командного рядка-X
tracemalloc=NFRAME
можна використовувати для запуску трасування під час запуску.Дивіться також функції
stop()
,is_tracing()
іget_traceback_limit()
.
-
tracemalloc.
stop
()¶ Зупиніть відстеження розподілу пам’яті Python: видаліть перехоплювачі розподільників пам’яті Python. Також очищає всі раніше зібрані сліди блоків пам’яті, виділених Python.
Викличте функцію
take_snapshot()
, щоб зробити знімок слідів перед їх очищенням.Дивіться також функції
start()
,is_tracing()
іclear_traces()
.
-
tracemalloc.
take_snapshot
()¶ Зробіть знімок слідів блоків пам’яті, виділених Python. Повернути новий екземпляр
Snapshot
.Знімок не включає блоки пам’яті, виділені до того, як модуль
tracemalloc
почав відстежувати виділення пам’яті.Відстеження трасування обмежено кадрами
get_traceback_limit()
. Щоб зберегти більше кадрів, використовуйте параметр nframe функціїstart()
.Модуль
tracemalloc
повинен відстежувати виділення пам’яті, щоб зробити знімок, дивіться функціюstart()
.Дивіться також функцію
get_object_traceback()
.
DomainFilter¶
-
class
tracemalloc.
DomainFilter
(inclusive: bool, domain: int)¶ Фільтрувати сліди блоків пам’яті за їх адресним простором (доменом).
Нове в версії 3.6.
-
inclusive
¶ Якщо inclusive має значення
True
(include), збігаються блоки пам’яті, виділені в адресному просторіdomain
.Якщо inclusive має значення
False
(виключити), збігаються блоки пам’яті, не виділені в адресному просторіdomain
.
-
domain
¶ Адресний простір блоку пам’яті (
int
). Властивість лише для читання.
-
фільтр¶
-
class
tracemalloc.
Filter
(inclusive: bool, filename_pattern: str, lineno: int=None, all_frames: bool=False, domain: int=None)¶ Фільтрувати сліди блоків пам’яті.
Перегляньте функцію
fnmatch.fnmatch()
, щоб дізнатися про синтаксис шаблон_назви_файлу. Розширення файлу'.pyc'
замінено на'.py'
.приклади:
Filter(True, subprocess.__file__)
містить лише сліди модуляsubprocess
Filter(False, tracemalloc.__file__)
виключає сліди модуляtracemalloc
Filter(False, "<unknown>")
виключає порожні відстеження
Змінено в версії 3.5: Розширення файлу
'.pyo'
більше не замінюється на'.py'
.Змінено в версії 3.6: Додано атрибут
domain
.-
domain
¶ Адресний простір блоку пам’яті (
int
абоNone
).tracemalloc використовує домен
0
для відстеження розподілу пам’яті, зробленого Python. Розширення C можуть використовувати інші домени для відстеження інших ресурсів.
-
inclusive
¶ Якщо inclusive має значення
True
(include), збігаються лише блоки пам’яті, виділені у файлі з іменем, яке відповідаєfilename_pattern
у номері рядкаlineno
.Якщо inclusive має значення
False
(виключити), ігнорувати блоки пам’яті, виділені у файлі з іменем, яке відповідаєfilename_pattern
у номері рядкаlineno
.
-
lineno
¶ Номер рядка (
int
) фільтра. Якщо lineno має значенняNone
, фільтр відповідає будь-якому номеру рядка.
-
filename_pattern
¶ Шаблон імені файлу фільтра (
str
). Властивість лише для читання.
-
all_frames
¶ Якщо all_frames має значення
True
, перевіряються всі кадри зворотного відстеження. Якщо all_frames має значенняFalse
, перевіряється лише останній кадр.Цей атрибут не діє, якщо обмеження зворотного відстеження дорівнює
1
. Перегляньте функціюget_traceback_limit()
і атрибутSnapshot.traceback_limit
.
рамка¶
знімок¶
-
class
tracemalloc.
Snapshot
¶ Знімок слідів блоків пам’яті, виділених Python.
Функція
take_snapshot()
створює екземпляр знімка.-
compare_to
(old_snapshot: Snapshot, key_type: str, cumulative: bool=False)¶ Обчисліть різницю за старим знімком. Отримати статистику як відсортований список екземплярів
StatisticDiff
, згрупованих за key_type.Перегляньте метод
Snapshot.statistics()
для параметрів key_type і cumulative.Результат сортується від найбільшого до найменшого за: абсолютним значенням
StatisticDiff.size_diff
,StatisticDiff.size
, абсолютним значеннямStatisticDiff.count_diff
,Statistic .count
, а потімStatisticDiff.traceback
.
-
filter_traces
(filters)¶ Створіть новий екземпляр
Snapshot
із відфільтрованою послідовністюtraces
, filters — це список екземплярівDomainFilter
іFilter
. Якщо filters є порожнім списком, поверніть новий екземплярSnapshot
із копією трасувань.Усі включені фільтри застосовуються одразу, трасування ігнорується, якщо жодні включені фільтри не відповідають йому. Трасування ігнорується, якщо йому відповідає хоча б один ексклюзивний фільтр.
Змінено в версії 3.6: Екземпляри
DomainFilter
тепер також приймаються в filters.
-
statistics
(key_type: str, cumulative: bool=False)¶ Отримати статистику як відсортований список екземплярів
Statistic
, згрупованих за key_type:key_type
опис
'ім'я файлу'
ім’я файлу
''лінено'
ім’я файлу та номер рядка
'відстеження''
простежити
Якщо cumulative має значення
True
, кумулювати розмір і кількість блоків пам’яті всіх кадрів зворотного відстеження трасування, а не лише останнього кадру. Кумулятивний режим можна використовувати лише з key_type, що дорівнює'filename'
і'lineno'
.Результат сортується від найбільшого до найменшого за:
Statistic.size
,Statistic.count
, а потім заStatistic.traceback
.
-
traceback_limit
¶ Максимальна кількість кадрів, що зберігаються у зворотній трасуванні
traces
: результатуget_traceback_limit()
під час створення знімка.
-
статистика¶
-
class
tracemalloc.
Statistic
¶ Статистика виділення пам’яті.
Snapshot.statistics()
повертає список екземплярівStatistic
.Дивіться також клас
StatisticDiff
.-
count
¶ Кількість блоків пам’яті (
int
).
-
size
¶ Загальний розмір блоків пам’яті в байтах (
int
).
-
StatisticDiff¶
-
class
tracemalloc.
StatisticDiff
¶ Різниця в статистиці виділення пам’яті між старим і новим екземплярами
Snapshot
.Snapshot.compare_to()
повертає список екземплярівStatisticDiff
. Дивіться також класStatistic
.-
count
¶ Кількість блоків пам’яті в новому знімку (
int
):0
, якщо блоки пам’яті було звільнено в новому знімку.
-
count_diff
¶ Різниця кількості блоків пам’яті між старим і новим знімками (
int
):0
, якщо блоки пам’яті були виділені в новому знімку.
-
size
¶ Загальний розмір блоків пам’яті в байтах у новому знімку (
int
):0
, якщо блоки пам’яті було звільнено в новому знімку.
-
size_diff
¶ Різниця загального розміру блоків пам’яті в байтах між старим і новим знімками (
int
):0
, якщо блоки пам’яті були виділені в новому знімку.
-
Слід¶
-
class
tracemalloc.
Trace
¶ Трасування блоку пам’яті.
Атрибут
Snapshot.traces
— це послідовність екземплярівTrace
.Змінено в версії 3.6: Додано атрибут
domain
.-
domain
¶ Адресний простір блоку пам’яті (
int
). Властивість лише для читання.tracemalloc використовує домен
0
для відстеження розподілу пам’яті, зробленого Python. Розширення C можуть використовувати інші домени для відстеження інших ресурсів.
-
size
¶ Розмір блоку пам’яті в байтах (
int
).
-
Простежити¶
-
class
tracemalloc.
Traceback
¶ Послідовність екземплярів
Frame
, відсортованих від найстарішого кадру до останнього.Трасування містить принаймні
1
кадр. Якщо модулюtracemalloc
не вдалося отримати кадр, використовується ім’я файлу"<unknown>"
під номером рядка0
.When a snapshot is taken, tracebacks of traces are limited to
get_traceback_limit()
frames. See thetake_snapshot()
function.Атрибут
Trace.traceback
є екземпляром екземпляраTraceback
.Змінено в версії 3.7: Кадри тепер сортуються від найстаріших до найновіших, а не від останніх до найстаріших.
-
format
(limit=None, most_recent_first=False)¶ Format the traceback as a list of lines with newlines. Use the
linecache
module to retrieve lines from the source code. If limit is set, format the limit most recent frames if limit is positive. Otherwise, format theabs(limit)
oldest frames. If most_recent_first isTrue
, the order of the formatted frames is reversed, returning the most recent frame first instead of last.Подібно до функції
traceback.format_tb()
, за винятком того, щоformat()
не містить символів нового рядка.Приклад:
print("Traceback (most recent call first):") for line in traceback: print(line)
Вихід:
Traceback (most recent call first): File "test.py", line 9 obj = Object() File "test.py", line 12 tb = tracemalloc.get_object_traceback(f())
-