Профилирование
Профилирование процессора
Существует два основных подхода к профилированию кода Julia:
Через @profile
Где профилирование включено для данного вызова с помощью макроса @profile.
julia> using Profile
julia> @profile foo()
julia> Profile.print()
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
╎147 @Base/client.jl:506; _start()
╎ 147 @Base/client.jl:318; exec_options(opts::Base.JLOptions)
...
Вызванное во время выполнения
Задачи, которые уже выполняются, также могут быть профилированы в течение определённого периода времени в любой момент по запросу пользователя.
Для запуска профилирования:
- MacOS & FreeBSD (платформы на основе BSD): Используйте
ctrl-tили передайте сигналSIGINFOпроцессу julia, например% kill -INFO $julia_pid. - Linux: Передайте сигнал
SIGUSR1процессу julia, например% kill -USR1 $julia_pid. - Windows: В настоящее время не поддерживается.
Сначала отображается один стек вызовов в момент броска сигнала, затем собирается профиль длительностью 1 секунда, а затем отчёт о профиле в следующей точке перехода к другому заданию, которая может быть в момент завершения задачи для кода без точек перехода, например, в жёстких циклах.
julia> foo()
##== the user sends a trigger while foo is running ==##
load: 2.53 cmd: julia 88903 running 6.16u 0.97s
======================================================================================
Information request received. A stacktrace will print followed by a 1.0 second profile
======================================================================================
signal (29): Information request: 29
__psynch_cvwait at /usr/lib/system/libsystem_kernel.dylib (unknown line)
_pthread_cond_wait at /usr/lib/system/libsystem_pthread.dylib (unknown line)
...
======================================================================
Profile collected. A report will print if the Profile module is loaded
======================================================================
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
Thread 1 Task 0x000000011687c010 Total snapshots: 572. Utilization: 100%
╎147 @Base/client.jl:506; _start()
╎ 147 @Base/client.jl:318; exec_options(opts::Base.JLOptions)
...
Thread 2 Task 0x0000000116960010 Total snapshots: 572. Utilization: 0%
╎572 @Base/task.jl:587; task_done_hook(t::Task)
╎ 572 @Base/task.jl:879; wait()
...
Настройка
Длительность профилирования можно настроить с помощью Profile.set_peek_duration
Отчёт о профиле разбивается по потокам и задачам. Передайте функцию без аргументов в Profile.peek_report[] чтобы переопределить это. Например, Profile.peek_report[] = () -> Profile.print() для удаления группировки. Это также может быть переопределено внешним потребителем данных профиля.
Справочник
Profile.@profileМакрос
@profile
@profile <expression> выполняет ваше выражение, периодически делая дампы стека вызовов. Они добавляются к внутреннему буферу дампов стека.
Методы в Profile не экспортируются и должны вызываться, например, как Profile.print().
Profile.clearФункция
clear()
Очистить любые существующие дампы стека из внутреннего буфера.
Profile.printФункция
print([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)
Выводит результаты профилирования в io (по умолчанию, stdout). Если вы не предоставите вектор data, будет использован внутренний буфер накопленных дампов стека.
Ключевые аргументы могут быть любым сочетанием:
format– Определяет, выводятся ли дампы стека с (по умолчанию,:tree) или без (:flat) отступом, указывающим структуру дерева.C– Еслиtrue, дампы стека из кода C и Fortran отображаются (обычно они исключаются).combine– Еслиtrue(по умолчанию), указатели инструкций, соответствующие одной строке кода, объединяются.maxdepth– Ограничивает глубину, превышающуюmaxdepthв формате:tree.sortedby– Управляет порядком в формате:flat.:filefuncline(по умолчанию) сортирует по строке исходного кода,:countсортирует по количеству собранных выборок, а:overheadсортирует по количеству выборок, выпавших на каждую функцию.groupby– Управляет группировкой по задачам и потокам или без группировки. Варианты::none(по умолчанию),:thread,:task,[:thread, :task], или[:task, :thread], где последние два обеспечивают вложенную группировку.noisefloor– Ограничивает кадры, которые превышают эвристическое пороговое значение шума выборки (применяется только к формату:tree). Рекомендуемое значение для попытки установить — 2.0 (по умолчанию 0). Этот параметр скрывает выборки, для которыхn <= noisefloor * √N, гдеn— количество выборок в этой строке, аN— количество выборок для вызываемого объекта.mincount– Ограничивает вывод только теми строками, у которых есть по крайней мереmincountвхождений.recur– Управляет обработкой рекурсии в формате:tree.:off(по умолчанию) выводит дерево в обычном виде.:flatвместо этого сжимает любую рекурсию (по ip), показывая приблизительный эффект преобразования любой саморекурсии в итератор.:flatcделает то же самое, но также включает сжатие кадров C (может давать странные результаты вблизиjl_apply).threads::Union{Int,AbstractVector{Int}}– Укажите, с каких потоков включать снимки в отчёте. Обратите внимание, что это не контролирует, на каких потоках собираются выборки (которые также могут быть собраны на другой машине).tasks::Union{Int,AbstractVector{Int}}– Укажите, с каких задач включать снимки в отчёте. Обратите внимание, что это не контролирует, в каких задачах собираются выборки.
print([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)
Выводит результаты профилирования в io. Этот вариант используется для проверки результатов, экспортированных предыдущим вызовом retrieve. Передайте вектор data дампов стека и словарь lidict информации о строках.
См. Profile.print([io], data) для объяснения допустимых ключевых аргументов.
Profile.initФункция
init(; n::Integer, delay::Real)
Настройте интервал delay между дампами стека (в секундах) и количество n указателей инструкций, которые могут храниться на поток. Каждый указатель инструкции соответствует одной строке кода; дампы стека, как правило, содержат длинный список указателей инструкций. Обратите внимание, что 6 пространств для указателей инструкций на дамп стека используются для хранения метаданных и двух NULL-маркеров конца.
Текущие настройки можно получить, вызвав эту функцию без аргументов, и каждый параметр можно установить независимо, используя ключевые слова или в порядке (n, delay).
Начиная с Julia 1.8, эта функция выделяет место для n указателей инструкций на каждом профилируемом потоке. Ранее это было n в общей сложности.
Profile.fetchФункция
fetch(;include_meta = true) -> data
Возвращает копию буфера дампов стека профиля. Обратите внимание, что значения в data имеют смысл только на этой машине в текущем сеансе, потому что зависят от точных адресов памяти, используемых при JIT-компиляции. Эта функция предназначена в основном для внутреннего использования; retrieve может быть лучшим выбором для большинства пользователей. По умолчанию метаданные, такие как threadid и taskid, включены. Установите include_meta в false для удаления метаданных.
Profile.retrieveФункция
retrieve(; kwargs...) -> data, lidict
«Экспортирует» результаты профилирования в переносимом формате, возвращая набор всех дампов стека (data) и словарь, сопоставляющий (специфичные для сеанса) указатели инструкций в data с LineInfo значениями, которые хранят имя файла, имя функции и номер строки. Эта функция позволяет сохранять результаты профилирования для дальнейшего анализа.
Profile.callersФункция
callers(funcname, [data, lidict], [filename=<filename>], [linerange=<start:stop>]) -> Vector{Tuple{count, lineinfo}}
Учитывая предыдущую сессию профилирования, определите, кто вызвал определённую функцию. Предоставление имени файла (и, необязательно, диапазона номеров строк, в котором определяется функция) позволяет различать перегруженные методы. Возвращаемое значение — вектор, содержащий количество вызовов и информацию о строках вызывающего объекта. Необязательно можно предоставить дампы стека data , полученные из retrieve; в противном случае используется текущий внутренний буфер профиля.
Profile.clear_malloc_dataФункция
clear_malloc_data()
Очищает любые сохранённые данные о распределении памяти при выполнении julia с --track-allocation. Выполните команду(ы), которые вы хотите протестировать (чтобы принудительно выполнить JIT-компиляцию), а затем вызовите clear_malloc_data. Затем снова выполните свою команду(ы), выйдите из Julia и изучите полученные файлы *.mem.
Profile.get_peek_durationФункция
get_peek_duration()
Получить длительность в секундах «просмотра» профиля, который запускается через SIGINFO или SIGUSR1, в зависимости от платформы.
Profile.set_peek_durationФункция
set_peek_duration(t::Float64)
Установить длительность в секундах «просмотра» профиля, который запускается через SIGINFO или SIGUSR1, в зависимости от платформы.
Профилирование памяти
Profile.Allocs.@profileМакрос
Profile.Allocs.@profile [sample_rate=0.0001] expr
Профилировать распределения, которые происходят во время expr, возвращая как результат, так и структуру AllocResults.
Частота 1.0 будет записывать всё; 0.0 — ничего.
julia> Profile.Allocs.@profile sample_rate=0.01 peakflops()
1.03733270279065e11
julia> results = Profile.Allocs.fetch()
julia> last(sort(results.allocs, by=x->x.size))
Profile.Allocs.Alloc(Vector{Any}, Base.StackTraces.StackFrame[_new_array_ at array.c:127, ...], 5576)
Текущая реализация профайлера распределения не захватывает типы для всех распределений. Распределения, для которых профайлер не смог захватить тип, представлены как имеющие тип Profile.Allocs.UnknownType.
Вы можете узнать больше о недостающих типах и планах по улучшению этого по адресу: https://github.com/JuliaLang/julia/issues/43688.
Профайлер распределения был добавлен в Julia 1.8.
Методы в Profile.Allocs не экспортируются и должны вызываться, например, как Profile.Allocs.fetch().
Profile.Allocs.clearФункция
Profile.Allocs.clear()
Очистить ранее профилированную информацию о распределении из памяти.
Profile.Allocs.fetchФункция
Profile.Allocs.fetch()
Получить записанные распределения и декодировать их в объекты Julia, которые можно проанализировать.
Profile.Allocs.startФункция
Profile.Allocs.start(sample_rate::Real)
Начните запись распределения с заданной частотой дискретизации. Частота дискретизации 1,0 запишет все; 0,0 — ничего.
Profile.Allocs.stopФункция
Profile.Allocs.stop()
Остановить запись распределения.
© 2009–2022 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v1.8/stdlib/Profile/