Этот доклад будет максимально прикладным. Насколько MetricKit
хорош? Какие данные действительно помогут оптимизировать работу приложения? Как подружить MetricKit с другими метриками?
В приложении Vivid используется MetricKit и мы уже решили эти вопросы и многие другие.
5. 5
MXMetricManager
let metrikManager = MXMetricManager.shared
metrikManager.add(self)
open func add(_ subscriber: MXMetricManagerSubscriber)
open func remove(_ subscriber: MXMetricManagerSubscriber)
@available(iOS 13.0, *)
open var pastPayloads: [MXMetricPayload] { get }
open var pastDiagnosticPayloads: [MXDiagnosticPayload] { get }
@available(iOS 14.0, *)
What’s New in MetricKit
10. 10
@available(iOS 14.0, *)
Нормальный выход
Вытеснено другим приложением в foreground
Переходы между стейтами занимают больше 20 секунд
MXMetricPayload 🤩
cumulativeBadAccessExitCount
cumulativeIllegalInstructionExitCount
cumulativeAbnormalExitCount
cumulativeCPUResourceLimitExitCount
cumulativeMemoryResourceLimitExitCount
cumulativePressureExitCount
cumulativeSuspendedWithLockedFileExitCount
cumulativeAppWatchdogExitCount
cumulativeBackgroundTaskAssertionTimeoutExitCount
cumulativeNormalExitCount
Crashes
Segmentation fault
Illegal instruction
Asserts and uncaught exceptions
Understanding Crashes and Crash Logs
Why is my app getting killed
MXBackgroundExitData
Рассмотрим вместе с MXDiagnosticPayload
15. 15
MXCPUExceptionDiagnostic
CPU Exception, or a "high CPU usage termination"
80% CPU over a period of one minute (on background execution)
Why is my app getting killed
Solving CPU Usage Crashes with Xcode's Energy Organizer
cumulativeCPUResourceLimitExitCount
Чтобы избежать этого exception'а:
move work into BGProcessingTask
MXBackgroundExitData
16. 16
MXDiskWriteExceptionDiagnostic
"diskIOMetrics": {
cumulativeLogicalWrites = "1300 kB"
}
Генерируется, если количество записей > 1 ГБ в день
"callStackTree" : {
"callStacks" : [
{
"callStackRootFrames" : [
{
…
"sampleCount" : 20
"diagnosticMetaData" : {
…
"regionFormat" : "GB",
"writesCaused" : "2,000 byte"
…
}
A disk write exception occurs when the app writes an excessive amount of data to the disk.
diskIOMetrics MXDiskIOMetric
cumulativeLogicalWrites "1300kB"
18. 18
MXHangDiagnostic
Eliminate animation hitches with XCTest
Все данные unsymbolicated - можно использовать утилиту ATOS
cd ~/Library/Developer/Xcode/Archives/2022-01-26/Vivid 26.01.2022, 20.43.xcarchive/dSYMs/Vivid.app.dSYM/Contents/Resources/DWARF/
atos -arch arm64 -o myApp 0x4329526096
Identify trends with the Power and Performance API
An object representing a diagnostic report for an app that is too busy
to handle user input responsively
applicationResponsivenessMetrics MXAppResponsivenessMetric
histogrammedAppHangTime (buckets)
23. reality.code
23
struct PerformanceMeasure {
var callTime: TimeInterval
let type: PerformanceMeasureType
let concreteName: String?
var stopTime: TimeInterval?
}
struct TelegrafEvent {
let name: String
let time: TimeInterval
let tags: [String: String]
let metricType: TelegrafMetricType
}
let time = measure.stopTime - measure.callTime
Date().timeIntervalSince1970
vivid
24. 24
App launch metric
func measureAppStartUpTime() -> (Double, Double) {
var kinfo = kinfo_proc()
var size = MemoryLayout<kinfo_proc>.stride
var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
sysctl(&mib, u_int(mib.count), &kinfo, &size, nil, 0)
let startTime = kinfo.kp_proc.p_starttime
var time = timeval(tv_sec: 0, tv_usec: 0)
gettimeofday(&time, nil)
let currentTimeMilliseconds = (Double(Int64(time.tv_sec) * 1_000) + Double(time.tv_usec) / 1_000.0) / 1_000.0
let processTimeMilliseconds = (Double(Int64(startTime.tv_sec) * 1_000) + Double(startTime.tv_usec) / 1_000.0) /
1_000.0
return (processTimeMilliseconds, currentTimeMilliseconds)
}
vivid
28. 28
struct PerformanceNewMeasure {
var callTime: TimeInterval
let type: PerformanceMeasureType
let concreteName: String?
var stopTime: TimeInterval?
}
struct TelegrafEvent {
let name: String
let time: TimeInterval
let tags: [String: String]
let metricType: TelegrafMetricType
}
let time = measure.stopTime - measure.callTime
Date().timeIntervalSince1970
Date().timeIntervalSince1970
event.time.multiply(1_000)
Ответ
Date().timeIntervalSince1970
vivid reality.code
32. План
32
1 MetricKit - основные сущности и как с ними работать
2 Примеры и истории из нашей практики
3 Итоги
✅
✅
33. 33
💚 MetricKit легко добавить
💚 MetricKit можно использовать вместе с остальными метриками, но есть 2 нюанса:
- Нужно учитывать, в каком они формате (их 3 - бакеты, количество и длительность)
- Следить за единицами измерения
💚 Удобно использовать метрики в связке с Pro
fi
ler и с Organizer - они позволяют смотреть в моменте
и регресс, а MetricKit позволяет смотреть в динамике от сборки к сборке
💚 Сопоставление MXMetricPayload vs MXDiagnosticPayload
❌ MXDiagnostic не доступен без dSYMs - не получится в реальном времени отслеживать данные
❌ Не все метрики кажутся полезными
❌ Perf tests
Итоги
34. MetricKit
What’s New in MetricKit
Improving Your App's Performance
Understanding Crashes and Crash Logs
Why is my app getting killed
Solving CPU Usage Crashes with Xcode's Energy Organizer
Eliminate animation hitches with XCTest
Identify trends with the Power and Performance API
Telegraf
VictoriaMetrics
Grafana
https://stackoverflow.com/questions/64378095/metrickit-mxdiagnostic-symbolication
https://swiftrocks.com/debug-cpu-exceptions-xcode-energy-reports
https://medium.com/naukri-engineering/overview-of-dsym-crashlytics-in-ios-dfd72eae8b58
iOS Performance Engineer Android Performance Engineer
https://jobs.vivid.money/jobs/Careers/33579000004386184/iOS-developer-Performance-team-?source=CareerSite
https://jobs.vivid.money/jobs/Careers/33579000004386170/Android-developer-Performance-team-?source=CareerSite