Ответ 1
Вместо использования флагов мы можем теперь использовать программно вставленные указатели, которые фиксируются в инструменте "Достопримечательности".
В iOS 13 и macOS 10.15 мы можем использовать os_signpost
. Это показано в видео WWDC 2019 Начало работы с инструментами.
-
Импортируйте единую структуру ведения журнала:
import os.log
-
Создайте
OSLog
для достопримечательностей:private let pointsOfInterest = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: .pointsOfInterest)
-
Если вы хотите начать диапазон точек интереса, вы можете.
.begin
точку интереса:let id = OSSignpostID(log: pointsOfInterest) os_signpost(.begin, log: pointsOfInterest, name: "Download", signpostID: id, "Download %d", index)
-
Если вы хотите, чтобы закончить точки диапазона интереса, вы можете
.end
его:os_signpost(.end, log: pointsOfInterest, name: "Download", signpostID: id, "Download %d", index)
-
Если вы не заинтересованы в определенном интервале времени, а предпочитаете один указатель, вы можете просто опубликовать
.event
:os_signpost(.event, log: pointsOfInterest, name: "Done", "All done")
Таким образом, последовательность операций загрузки и анализа (каждая очередь ограничена двумя параллельными операциями в очереди) приводит к следующему в инструментах:
Обратите внимание, что значения name
(в одном наборе я использовал имя Download
а в другом - Parse
) красиво разделены на разные дорожки в инструменте Points of Interest. И поскольку я использовал необязательные строки формата, я на самом деле могу видеть сообщения, в которых я могу четко соотнести каждую операцию загрузки и анализа с конкретной задачей в моем приложении.
Выше я использовал необязательные параметры OSSignpostID
потому что у меня было несколько перекрывающихся диапазонов, и я хотел избежать путаницы, связывающей конкретный .end
с соответствующим .begin
. Если вы либо не используете диапазоны точек интереса, либо у вас нет перекрывающихся диапазонов, вам не нужно использовать этот необязательный параметр. Например, вы можете просто сделать:
os_signpost(.begin, log: pointsOfInterest, name: "SomeTask")
asynchronousMethod {
os_signpost(.end, log: pointsOfInterest, name: "SomeTask")
}
В любом случае, теперь, когда у вас есть инструмент "Достопримечательности", заполненный информацией, вы можете удвоить -click в диапазоне, чтобы выбрать его, или в три раза -click, чтобы также установить свой диапазон проверки.
В iOS 10 и macOS 10.12 мы использовали kdebug_signpost
. Это проиллюстрировано на трассе видеосистемы WWDC 2016 в глубине.
Для тех процессов, которые занимают определенное количество времени, мы можем использовать kdebug_signpost_start
и kdebug_signpost_end
. Например:
kdebug_signpost_start(SignPostCode.download.rawValue, UInt(index), 0, 0, SignPostColor.orange.rawValue)
performDownload {
kdebug_signpost_end(SignPostCode.download.rawValue, UInt(index), 0, 0, SignPostColor.orange.rawValue)
}
Чтобы отметить один момент времени, мы можем просто использовать kdebug_signpost
:
kdebug_signpost(SignPostCode.done.rawValue, 0, 0, 0, SignPostColor.red.rawValue)
Первый параметр - это просто некоторый уникальный числовой код, который соответствует "кодовому имени указателя", которое мы будем использовать в инструментах. Вы можете использовать любые значения (от 0 до 16383), но я использую то, что обозначает тип задачи:
enum SignPostCode: UInt32 { // some custom constants that I'll reference in Instruments
case download = 0
case parse = 1
case done = 2
}
Остальные параметры могут быть любыми значениями UInt
вы хотите, но в моем примере я буду использовать второй параметр в качестве уникального идентификатора для сопоставления повторяющихся start
и end
вызовов, и я буду использовать последний параметр для цветовой кодировки моих регионов в инструментах:
enum SignPostColor: UInt { // standard color scheme for signposts in Instruments
case blue = 0
case green = 1
case purple = 2
case orange = 3
case red = 4
}
Сделав это, вы можете затем профилировать приложение в разделе "Инструменты", нажать кнопку "+" в правой части панели инструментов и добавить "Точки интереса". Сконфигурировав "Имена кодов указателей", чтобы они соответствовали числовым значениям, которые я передал в качестве первого параметра моим указателям, Инструменты фактически переведут эти коды для меня. После того, как я профилировал приложение, и теперь у меня есть четко обозначенные пункты интереса:
В этом снимке я профилировал семь операций загрузки (оранжевым цветом) и семь операций синтаксического анализа (зеленым цветом), ограничив их до двух одновременно. И когда они были сделаны, я разместил единый указатель "сделано" (красный). Но детали этого демонстрационного приложения не являются критическими, а скорее всего лишь иллюстрируют, как единичные указатели и начальные/конечные указатели отображаются в "точках интереса" инструментов.
Основная проблема заключается в том, что теперь у меня есть четкое соответствие между событиями в моем коде и тем, что я вижу в инструментах. И я могу control -click на записи в списке диапазонов указателей и сказать инструментам "Установить фильтр времени", если я хочу, чтобы, когда я возвращаюсь к другим своим инструментам (распределению или профайлеру времени или как угодно), диапазон проверки отфильтрован до соответствующих точек интереса в моем приложении.
Обратите внимание, что выше Swift. В Objective-C API kdebug_signpost
похож, но вы должны включить:
#import <sys/kdebug_signpost.h>
Очевидно, что и то, как вы определяете свои перечисления для ваших кодов, тоже изменится.
Обратите внимание, этот API kdebug_signpost
был представлен в iOS 10/macOS 10.12. Заголовки говорят нам, что более ранние версии ОС могли использовать syscall
:
В предыдущих версиях операционной системы приложения могли использовать:
syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, <your event code>) | DBG_FUNC_<type>, arg1, arg2, arg3, arg4);
для записи событий, которые будут отображаться с помощью инструментов.
syscall(2)
теперь устарела, и этот интерфейс заменяет вышеуказанный вызов.
Примечание. Если вам syscall
использовать syscall
в более ранней версии ОС, вам придется импортировать <sys/kdebug.h>
:
#import <sys/kdebug.h>
Кроме того, я не смог найти объявление SYS_kdebug_trace
ни в одном из заголовков, но наткнулся на ссылку в Интернете, в которой говорилось, что это значение равно 180
, что я проверял эмпирически:
#ifndef SYS_kdebug_trace
#define SYS_kdebug_trace 180
#endif