100
© 2019 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. #WWDC19 Daniel Delwood, Software Radiologist Kacper Harasim, Software Engineer Developing a Great Profiling Experience Telling your story with Custom Instruments

Developing a Great Profiling Experience

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Developing a Great Profiling Experience

© 2019 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

#WWDC19

Daniel Delwood, Software Radiologist Kacper Harasim, Software Engineer

•Developing a Great Profiling Experience •Telling your story with Custom Instruments

Page 2: Developing a Great Profiling Experience
Page 3: Developing a Great Profiling Experience
Page 4: Developing a Great Profiling Experience

/**

@protocol MTLCommandBuffer

@abstract A serial list of commands for the device to execute.

public protocol MTLCommandBuffer : NSObjectProtocol { var device: MTLDevice { get } var commandQueue: MTLCommandQueue { get } var retainedReferences: Bool { get } var label: String? { get set }

func enqueue() func commit()

func addScheduledHandler(_ block: @escaping MTLCommandBufferHandler) func present(_ drawable: MTLDrawable) func present(_ drawable: MTLDrawable, atTime presentationTime: CFTimeInterval) func waitUntilScheduled() func addCompletedHandler(_ block: @escaping MTLCommandBufferHandler) ...

Page 5: Developing a Great Profiling Experience
Page 6: Developing a Great Profiling Experience
Page 7: Developing a Great Profiling Experience

Goals

Page 8: Developing a Great Profiling Experience

Goals

Transparency → Trust

Page 9: Developing a Great Profiling Experience

Goals

Transparency → Trust

Explain cost, determine responsibility

Page 10: Developing a Great Profiling Experience

Goals

Transparency → Trust

Explain cost, determine responsibility

Opportunity to tell your story

Page 11: Developing a Great Profiling Experience

Tracing

Schemas/Modeling

Visualization

Page 12: Developing a Great Profiling Experience

•Tracing: Adding os_signpost to your code •Modeling: Adding structure to temporal data •Visualization: Telling your story with an instrument

Page 13: Developing a Great Profiling Experience

•Tracing: Adding os_signpost to your code •Modeling: Adding structure to temporal data •Visualization: Telling your story with an instrument

Page 14: Developing a Great Profiling Experience

os_signpost

Low-cost tracing primitive

Points (.event) or intervals (.begin/.end)

os_signpost_interval_begin(logHandle, spid, name, ...) os_signpost_interval_end(logHandle, spid, name, ...) os_signpost_event_emit(logHandle, spid, name, ...)

C

os_signpost(type, log: logHandle, name: name, signpostID: spid, format, args...)

Page 15: Developing a Great Profiling Experience

os_signpost

Low-cost tracing primitive

Points (.event) or intervals (.begin/.end)

os_signpost_interval_begin(logHandle, spid, name, ...) os_signpost_interval_end(logHandle, spid, name, ...) os_signpost_event_emit(logHandle, spid, name, ...)

C

os_signpost(type, log: logHandle, name: name, signpostID: spid, format, args...)

Page 16: Developing a Great Profiling Experience

os_signpost

OSLog-based • Subsystem • Category

Structure: Subsystem → Category → Name

Page 17: Developing a Great Profiling Experience

Tracing Merits

Page 18: Developing a Great Profiling Experience

Tracing Merits

Temporal • Implicitly records mach_continuous_time • Inherently support overlapping intervals with signpostID

Page 19: Developing a Great Profiling Experience

Tracing Merits

Temporal • Implicitly records mach_continuous_time • Inherently support overlapping intervals with signpostID

Low cost • Format strings are __TEXT constants, cheap • Not #DEBUG-only — leave them in

Page 20: Developing a Great Profiling Experience

Signpost Schema

os_signpost(type, log: logHandle, name: name, signpostID: spid, format, args...)

* .dynamicStackTracing only

Available Columns

Explicit event-type, subsystem, category, name, identifier, format-string, message

Implicit time, thread, process, scope, backtrace*

Page 21: Developing a Great Profiling Experience

Modes of os_signpost

Page 22: Developing a Great Profiling Experience

Modes of os_signpost

Enabled (default) • Low-cost, logged to ring buffer

Page 23: Developing a Great Profiling Experience

Modes of os_signpost

Enabled (default) • Low-cost, logged to ring buffer

Streaming • Higher cost when Instruments, log stream --signpost displaying live

Page 24: Developing a Great Profiling Experience

Modes of os_signpost

Enabled (default) • Low-cost, logged to ring buffer

Streaming • Higher cost when Instruments, log stream --signpost displaying live

Dynamic • OSLog.Category.dynamicTracing, .dynamicStackTracing

• Instruments enables only when recording

Page 25: Developing a Great Profiling Experience

Tracing Cost Order of magnitude approximations

NSLog

os_signpost (default)

os_signpost (.dynamic)

os_signpost (.dynamicStacks)

Release Build Recording Streaming

Smaller is better (logarithmic scale)

16ns 256ns 4µs 64µs32µs1µs64ns

Page 26: Developing a Great Profiling Experience

Tracing Cost Order of magnitude approximations

NSLog

os_signpost (default)

os_signpost (.dynamic)

os_signpost (.dynamicStacks)

Release Build Recording Streaming

Smaller is better (logarithmic scale)

16ns 256ns 4µs 64µs32µs1µs64ns

Page 27: Developing a Great Profiling Experience

Tracing Cost Order of magnitude approximations

NSLog

os_signpost (default)

os_signpost (.dynamic)

os_signpost (.dynamicStacks)

Release Build Recording Streaming

Smaller is better (logarithmic scale)

16ns 256ns 4µs 64µs32µs1µs64ns

Page 28: Developing a Great Profiling Experience

Tracing Cost Order of magnitude approximations

NSLog

os_signpost (default)

os_signpost (.dynamic)

os_signpost (.dynamicStacks)

Release Build Recording Streaming

Smaller is better (logarithmic scale)

16ns 256ns 4µs 64µs32µs1µs64ns

Page 29: Developing a Great Profiling Experience

Minimizing Overhead

Page 30: Developing a Great Profiling Experience

Minimizing Overhead

Record in deferred/last few seconds mode

Page 31: Developing a Great Profiling Experience

Minimizing Overhead

Record in deferred/last few seconds mode

Use .dynamicTracing categories

let normalLog = OSLog(subsystem: "com.org.MyFramework", category: "CompressorPhases") let highRateLog = OSLog(subsystem: "com.org.MyFramework", category: .dynamicTracing) let needStacksLog = OSLog(subsystem: "com.org.MyFramework", category: .dynamicStackTracing)

Page 32: Developing a Great Profiling Experience

Staying Under the Radar Back-of-the-envelope math

Page 33: Developing a Great Profiling Experience

Staying Under the Radar Back-of-the-envelope math

< 1% CPU(enabled, not streaming)

Page 34: Developing a Great Profiling Experience

Staying Under the Radar Back-of-the-envelope math

< 1% CPU(enabled, not streaming)

~500nssignpost*x

Page 35: Developing a Great Profiling Experience

Staying Under the Radar Back-of-the-envelope math

< 1% CPU(enabled, not streaming)

~500nssignpost*x

➞ <~20,000 signpostsx

second

Page 36: Developing a Great Profiling Experience

Staying Under the Radar Back-of-the-envelope math

< 1% CPU(enabled, not streaming)

~500nssignpost*x

➞ <~20,000 signpostsx

second@120 fps= ~83 intervals

frame

Page 37: Developing a Great Profiling Experience

Tailored to Your Audience

Page 38: Developing a Great Profiling Experience

Tailored to Your Audience

Signposts use shared system resources • Cost will vary by device hardware, software load • As always — use what you need

Page 39: Developing a Great Profiling Experience

Tailored to Your Audience

Signposts use shared system resources • Cost will vary by device hardware, software load • As always — use what you need

One or more OSLog handles per audience • Tools for clients • Tools for contributors

Page 40: Developing a Great Profiling Experience

Tracing Best Practices

Page 41: Developing a Great Profiling Experience

1. Always end intervals! defer { } when possible to avoid missing returns

Tracing Best Practices

do { let uniqueID = OSSignpostID(myHandle) os_signpost(.begin, log: myHandle, name: "Calculations", signpostID: uniqueID) let result = try expensiveProcessing(payloadData) /* additional result processing */ os_signpost(.end, log: myHandle, name: "Calculations", signpostID: uniqueID) } catch { /* handle error */ }

do { let uniqueID = OSSignpostID(myHandle) os_signpost(.begin, log: myHandle, name: "Calculations", signpostID: uniqueID) let result = try expensiveProcessing(payloadData) /* additional result processing */ os_signpost(.end, log: myHandle, name: "Calculations", signpostID: uniqueID) } catch { /* handle error */ }

Page 42: Developing a Great Profiling Experience

1. Always end intervals! defer { } when possible to avoid missing returns

Tracing Best Practices

do { let uniqueID = OSSignpostID(myHandle) os_signpost(.begin, log: myHandle, name: "Calculations", signpostID: uniqueID) let result = try expensiveProcessing(payloadData) /* additional result processing */ os_signpost(.end, log: myHandle, name: "Calculations", signpostID: uniqueID) } catch { /* handle error */ }

Page 43: Developing a Great Profiling Experience

Tracing Best Practices

1. Always end intervals! defer { } when possible to avoid missing returns

do { let uniqueID = OSSignpostID(myHandle) os_signpost(.begin, log: myHandle, name: "Calculations", signpostID: uniqueID) defer { os_signpost(.end, log: myHandle, name: "Calculations", signpostID: uniqueID) } let result = try expensiveProcessing(payloadData) /* additional result processing */ } catch { /* handle error */ }

Page 44: Developing a Great Profiling Experience

Tracing Best Practices

2. Log data once in earliest trace point available

os_signpost(.begin, log: myHandle, name: "DecodingPhase", "Request %u: decoding %lu bytes", requestNumber, raw.size)

os_signpost(.end, log: myHandle, name: "DecodingPhase", "Request %u: %lu -> %lu bytes", requestNumber, raw.size, decoded.size)

os_signpost(.end, log: myHandle, name: "DecodingPhase", "Decoded size: %lu bytes", decoded.size)

// deserialization work

Page 45: Developing a Great Profiling Experience

2. Log data once in earliest trace point available

os_signpost(.end, log: myHandle, name: "DecodingPhase", signpostID: spid "Decoded size: %lu bytes", decoded.size)

Tracing Best Practices

let spid = OSSignpostID(myHandle) os_signpost(.begin, log: myHandle, name: "DecodingPhase", signpostID: spid "Request %u: decoding %lu bytes", requestNumber, raw.size)

Page 46: Developing a Great Profiling Experience

Tracing Best Practices

3. Avoid expensive argument evaluation

os_signpost(.event, log: myLoggingHandle, name: "ReceivedPayload", "Details: %@", myObject.expensiveJSONDecodedProperty.description)

Page 47: Developing a Great Profiling Experience

Tracing Best Practices

3. Avoid expensive argument evaluation

os_signpost(.event, log: myLoggingHandle, name: "ReceivedPayload", "Details: %@", myObject.expensiveJSONDecodedProperty.description)

if myLoggingHandle.signpostsEnabled { let decoded = myObject.expensiveJSONDecodedProperty os_signpost(.event, log: myLoggingHandle, name: "ReceivedPayload", "Details: %@", decoded.description) }

Page 48: Developing a Great Profiling Experience

Tracing Best Practices

4. Only trace what you need, consider guard preconditions

func needsDecompression(data: Data) -> Bool { os_signpost(.begin, log: myHandle, name: "Validation") defer { os_signpost(.end, log: myHandle, name: "Validation") } guard data.count > Int(vm_page_size) else { return false // not worth the trouble for such a small payload } // more expensive validation logic }a

os_signpost(.begin, log: myHandle, name: "Validation") defer { os_signpost(.end, log: myHandle, name: "Validation") } guard data.count > Int(vm_page_size) else { return false // not worth the trouble for such a small payload }

Page 49: Developing a Great Profiling Experience

Tracing Best Practices

4. Only trace what you need, consider guard preconditions

func needsDecompression(data: Data) -> Bool { os_signpost(.begin, log: myHandle, name: "Validation") defer { os_signpost(.end, log: myHandle, name: "Validation") } guard data.count > Int(vm_page_size) else { return false // not worth the trouble for such a small payload } // more expensive validation logic }a

os_signpost(.begin, log: myHandle, name: "Validation") defer { os_signpost(.end, log: myHandle, name: "Validation") }

guard data.count > Int(vm_page_size) else { return false // not worth the trouble for such a small payload }

Page 50: Developing a Great Profiling Experience

Tracing Is Basis for Tools

Tracing

Schemas/Modeling

Visualization

Page 51: Developing a Great Profiling Experience

Avoid tracing frequently changing implementation details

No need to worry about inlining

Tools depend on stability of handles, signpost names, and format strings

Keeping Trace Points Stable

Page 52: Developing a Great Profiling Experience

Avoid tracing frequently changing implementation details

No need to worry about inlining

Tools depend on stability of handles, signpost names, and format strings

Keeping Trace Points Stable

let logHandle = OSLog(subsystem: "com.org.MyFramework", category: "Instrumented Activity") os_signpost(.begin, log: logHandle, name: "ManagerLifecycle", signpostID: .exclusive, "[%@] Activated with delegate: %p", self.managerUUID, self.delegate)

Page 53: Developing a Great Profiling Experience

•Tracing: Adding os_signpost to your code •Modeling: Adding structure to temporal data •Visualization: Telling your story with an instrument

Page 54: Developing a Great Profiling Experience

Instruments Architecture

Data stream os-signpost your-schema InstrumentModeler

Creating Custom Instruments WWDC 2018

Page 55: Developing a Great Profiling Experience

Instruments Architecture

Data stream os-signpost your-schema InstrumentModeler

os_signpost(.begin, log: log, name: "Inflate", "(%@) Compressed: %d", tag, size) […] os_signpost(.end, log: log, name: "Inflate", "Expanded: %d", final)

Tracing

Page 56: Developing a Great Profiling Experience

Instruments Architecture

Data stream os-signpost your-schema InstrumentModeler

Modeling

start duration thread client-tag expanded compressed ratio

0:00:001.324 342ms Thread 0x4016 Textures 14.11 MiB 4.32 MiB 3.27:1

Page 57: Developing a Great Profiling Experience

Instruments Architecture

Data stream os-signpost your-schema InstrumentModeler

Visualization

Decompressed: 4.32 MiB -> 14.11 MiB (342ms)Compression

Textures

Audio

Page 58: Developing a Great Profiling Experience

Getting Data into Instruments

All data is time-ordered • Point or Interval schemas

CLIPS Modelers • Generated and custom

Page 59: Developing a Great Profiling Experience

Getting Started

1. Built-in os_signpost instrument • Use instrument inspector to see raw data

Page 60: Developing a Great Profiling Experience

Getting Started

1. Built-in os_signpost instrument • Use instrument inspector to see raw data

2. New Target → Instruments Package • Define schema - Automatic modeler: <os-signpost-{point|interval}-schema>

• Define an Instrument to require/display - <instrument> must <create-table>

Page 61: Developing a Great Profiling Experience

Kacper Harasim, Software Engineer

•Demo •From os_signpost to Instruments

Page 62: Developing a Great Profiling Experience
Page 63: Developing a Great Profiling Experience
Page 64: Developing a Great Profiling Experience

Custom schema, custom modeler

When you need more: data fusion, inference

Allows you to embed more complex logic

Draw more customized graphs

<point-schema>, <interval-schema>, <modeler>

Modeling in Custom Instruments Friday, 3:20

Page 65: Developing a Great Profiling Experience

•Tracing: Adding os_signpost to your code •Modeling: Adding structure to temporal data •Visualization: Telling your story with an instrument

Page 66: Developing a Great Profiling Experience

Data ≠ Story

Page 67: Developing a Great Profiling Experience
Page 68: Developing a Great Profiling Experience
Page 69: Developing a Great Profiling Experience

Compelling Stories Have Plots

Make problems apparent

Graphs are the first summary

Display in terms of familiar concepts, metrics

Page 70: Developing a Great Profiling Experience

Summarizing Points

Thread 1

Thread 2

Time

Page 71: Developing a Great Profiling Experience

Summarizing Points

Thread 1

Thread 2

Time

24

1 2 1 1

5

1

Events

<histogram>

10 ms buckets

Page 72: Developing a Great Profiling Experience

Summarizing Points

Thread 1

Thread 2

Time

24

1 2 1 1

5

1

Events

<histogram>

10 ms buckets

Page 73: Developing a Great Profiling Experience

Thread 1

Thread 2

Time

Summarizing Points

Page 74: Developing a Great Profiling Experience

Thread 1

Thread 2

Time

Summarizing Points

Critical

Count2

41 2 1 1

5

1

<plot> + <histogram>

Page 75: Developing a Great Profiling Experience

Tabular Summaries

Define which metrics are important • <aggregation>: <count>, <min>, <max>, <average>, <std-dev> • Titles, order convey importance

Page 76: Developing a Great Profiling Experience

Even More Detail

<narrative>: natural language, expressive types

(set-column-narrative narrative "Interrupted for %duration% while %core% serviced an interrupt handler." ?duration ?core)

Page 77: Developing a Great Profiling Experience

Displaying Intervals

Qualified, multiple plots • <plot>, <plot-template> • <qualified-by>, <instance-by>

Page 78: Developing a Great Profiling Experience

Displaying Intervals

Hierarchies • <engineering-type-track>, <augmentation> • <hierarchy>, <add-graph>

NEW

Page 79: Developing a Great Profiling Experience

Summarizing Intervals

Interval Interval

Time

Thread 1

Page 80: Developing a Great Profiling Experience

Summarizing Intervals

8ms

42ms

8msDuration

<histogram>

19ms

10 ms buckets

Interval Interval

Time

Thread 1

Page 81: Developing a Great Profiling Experience

Summarizing Intervals

8ms

42ms

8msDuration

<histogram>

19ms

10 ms buckets

Interval Interval

Time

Thread 1

Page 82: Developing a Great Profiling Experience

Summarizing Intervals

8ms

42ms

8msDuration

<histogram>

19ms

10 ms buckets

Interval Interval

Time

Thread 1

Don't graph time/duration on the Y-axis

Page 83: Developing a Great Profiling Experience

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

Page 84: Developing a Great Profiling Experience

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

Page 85: Developing a Great Profiling Experience

start duration utilization severity

0:00:030.000 10ms 2.0 Low

0:00:040.000 10ms 2.7 Moderate

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

0.8 0.8 2.0 2.7 2.2 2.2 2.1 2.3 3.0 1.9 1.8 1.8 0.8

Quantized Utilization

Average

Page 86: Developing a Great Profiling Experience

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

Page 87: Developing a Great Profiling Experience

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

Transactions3 2

4 3 36 4 3 3 2

42

Quantized Activity

start duration unique-intervals severity

0:00:060.000 10ms 3 Low

0:00:070.000 10ms 6 High

Page 88: Developing a Great Profiling Experience

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

Page 89: Developing a Great Profiling Experience

Summarizing IntervalsInterval

Interval

Interval

Interval

Interval

Interval

Interval

Time

Thread 1

Thread 2

Thread 3

Worker Thread

Main Thread

Contention 2 3+ 2 3+

Overlap Plot

start duration description severity

0:00:031.401 9.32ms 2 Moderate

0:00:040.721 11.41ms 3+ High

Page 90: Developing a Great Profiling Experience

Data stream os-signpost mymodule-interval DetailsGenerated modeler

Modeler Outputs

Page 91: Developing a Great Profiling Experience

Modeler Outputs

Data stream os-signpost mymodule-interval Details

mymodule-utilization Graph

mymodule-conclusions Narrative

Custom modeler

Tick timer tick [10ms]

syscallBuilt-in modeler

Page 92: Developing a Great Profiling Experience

Kacper Harasim, Software Engineer

•Demo •Crafting your story

Page 93: Developing a Great Profiling Experience

Complete Profiling Experience

Users start with a template

Utilize tools bundled with Instruments

Presented graphs should quickly draw users to problems

Detail views should lead user to root cause

Page 94: Developing a Great Profiling Experience

Instruments 11 — HierarchiesNEW

Page 95: Developing a Great Profiling Experience

Instruments 11 — Custom Track ScopesNEW

Page 96: Developing a Great Profiling Experience

Instruments 11 — Custom Track ScopesNEW

Page 97: Developing a Great Profiling Experience

Instruments 11 — Custom Track ScopesNEW

Page 98: Developing a Great Profiling Experience

Summary

Opportunity to tell your story, educate, and catch easy mistakes

When something goes wrong, tools provide an answer

Increase confidence and trust in your library

Page 99: Developing a Great Profiling Experience

More Informationdeveloper.apple.com/wwdc19/414

Modeling in Custom Instruments Friday, 3:20

Creating Custom Instruments WWDC18

Measuring Performance Using Logging WWDC18

Page 100: Developing a Great Profiling Experience