Transcript
Page 1: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

These are confidential sessions—please refrain from streaming, blogging, or taking pictures

Session 702

Efficient Design with XPC

Damien SorressoSenior Software Engineer

Page 2: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Agenda

• Focus on performance■ Architectural design■ Implementation

•New features• Efficient usage patterns

Page 3: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Last Time at WWDC…

Page 4: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

What Is XPC?

• Service bootstrapping and IPC• Easily factor app into services• Services deployed within app bundle

Page 5: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Why Use XPC?

• Separate address space■ Fault isolation■ Different privileges/entitlements■ Least-required privilege

• Completely managed lifecycle■ Less boilerplate

Page 6: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Bundled Services

Fully managed lifecycle

App Store-rific

Ship in app

Stateless

Page 7: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

launchd Services

Run as root

Independent of app

App Store no me gusta

Require installation

More boilerplate

Page 8: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

APIs

Page 9: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

APIs

libxpc

libdispatch

libobjc / ARC

NSXPCConnection

Page 10: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Architecture

Page 11: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Architectural Goals

Page 12: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Architectural Goals

Avoid long-running processes

Lazy initializationAdapt to resource availability

Page 13: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

XPC Events

• System events demand-launch

Page 14: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

XPC Events

• System events demand-launch■ IOKit matching

Page 15: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

XPC Events

• System events demand-launch■ IOKit matching■ BSD notifications—notify(3)

Page 16: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

XPC Events

• System events demand-launch■ IOKit matching■ BSD notifications—notify(3)■ CFDistributedNotifications

Page 17: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

XPC Events

• System events demand-launch■ IOKit matching■ BSD notifications—notify(3)■ CFDistributedNotifications

•Only available to launchd services

Page 18: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

<key>LaunchEvents</key><dict> <key>com.apple.iokit.matching</key> <dict> <key>com.mycompany.device-attach</key> <dict> <key>idProduct</key> <integer>2794</integer> <key>idVendor</key> <integer>725</integer> <key>IOProviderClass</key> <string>IOUSBDevice</string> <key>IOMatchLaunchStream</key> <true/> </dict> </dict></dict>

In the launchd.plistXPC Events

Page 19: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

<key>LaunchEvents</key><dict> <key>com.apple.iokit.matching</key> <dict> <key>com.mycompany.device-attach</key> <dict> <key>idProduct</key> <integer>2794</integer> <key>idVendor</key> <integer>725</integer> <key>IOProviderClass</key> <string>IOUSBDevice</string> <key>IOMatchLaunchStream</key> <true/> </dict> </dict></dict>

In the launchd.plistXPC Events

Page 20: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

<key>LaunchEvents</key><dict> <key>com.apple.iokit.matching</key> <dict> <key>com.mycompany.device-attach</key> <dict> <key>idProduct</key> <integer>2794</integer> <key>idVendor</key> <integer>725</integer> <key>IOProviderClass</key> <string>IOUSBDevice</string> <key>IOMatchLaunchStream</key> <true/> </dict> </dict></dict>

In the launchd.plistXPC Events

Page 21: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

<key>LaunchEvents</key><dict> <key>com.apple.iokit.matching</key> <dict> <key>com.mycompany.device-attach</key> <dict> <key>idProduct</key> <integer>2794</integer> <key>idVendor</key> <integer>725</integer> <key>IOProviderClass</key> <string>IOUSBDevice</string> <key>IOMatchLaunchStream</key> <true/> </dict> </dict></dict>

In the launchd.plistXPC Events

Page 22: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

ConsumptionXPC Events

xpc_set_event_stream_handler(“com.apple.iokit.matching”, q, ^(xpc_object_t event) { // Every event has the key XPC_EVENT_KEY_NAME set to a string that // is the name you gave the event in your launchd.plist. const char *name = xpc_dictionary_get_string(event, XPC_EVENT_KEY_NAME);

// IOKit events have the IORegistryEntryNumber as a payload. uint64_t id = xpc_dictionary_get_uint64(event, “IOMatchLaunchServiceID”);

// Reconstruct the node you were interested in here using the IOKit // APIs.});

Page 23: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

ConsumptionXPC Events

xpc_set_event_stream_handler(“com.apple.iokit.matching”, q, ^(xpc_object_t event) { // Every event has the key XPC_EVENT_KEY_NAME set to a string that // is the name you gave the event in your launchd.plist. const char *name = xpc_dictionary_get_string(event, XPC_EVENT_KEY_NAME);

// IOKit events have the IORegistryEntryNumber as a payload. uint64_t id = xpc_dictionary_get_uint64(event, “IOMatchLaunchServiceID”);

// Reconstruct the node you were interested in here using the IOKit // APIs.});

Page 24: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

XPC activityCentralized Task Scheduling

•Opportunistic task scheduling•Defer work until a “good time”•Minimize disruption to user experience•Maximize efficient use of battery

Page 25: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Activity Types

Type Example Interrupted when...

Maintenance

Utility

Garbage collection User begins using machine

Fetch network data Resources become scarce

Page 26: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Activity Criteria

HDD spinning

Screen asleep

A/C power

Battery level

ONOFF

100%0%

ONOFF

ONOFF

Page 27: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

launchd and XPC servicesXPC Activity

• Persist across launches• System state change launches on-demand•Activity picks up where it left off

Page 28: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_INTERVAL, 5 * 60);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, 10 * 60);

// Activity handler runs on background queue.xpc_activity_register(“com.mycompany.myapp.myactivity”, criteria, ^(xpc_activity_t activity) { id data = createDataFromPeriodicRefresh();

// Continue the activity asynchronously to update the UI. xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_CONTINUE); dispatch_async(dispatch_get_main_queue(), ^{ updateViewWithData(data); xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE); });});

XPC Activity

Page 29: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_INTERVAL, 5 * 60);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, 10 * 60);

// Activity handler runs on background queue.xpc_activity_register(“com.mycompany.myapp.myactivity”, criteria, ^(xpc_activity_t activity) { id data = createDataFromPeriodicRefresh();

// Continue the activity asynchronously to update the UI. xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_CONTINUE); dispatch_async(dispatch_get_main_queue(), ^{ updateViewWithData(data); xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE); });});

XPC Activity

Page 30: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_INTERVAL, 5 * 60);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, 10 * 60);

// Activity handler runs on background queue.xpc_activity_register(“com.mycompany.myapp.myactivity”, criteria, ^(xpc_activity_t activity) { id data = createDataFromPeriodicRefresh();

// Continue the activity asynchronously to update the UI. xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_CONTINUE); dispatch_async(dispatch_get_main_queue(), ^{ updateViewWithData(data); xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE); });});

XPC Activity

Page 31: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_INTERVAL, 5 * 60);xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, 10 * 60);

// Activity handler runs on background queue.xpc_activity_register(“com.mycompany.myapp.myactivity”, criteria, ^(xpc_activity_t activity) { id data = createDataFromPeriodicRefresh();

// Continue the activity asynchronously to update the UI. xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_CONTINUE); dispatch_async(dispatch_get_main_queue(), ^{ updateViewWithData(data); xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE); });});

XPC Activity

Page 32: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Runtime

Page 33: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Service Lifecycle

Page 34: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Service Lifecycle

Page 35: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Service Lifecycle

Page 36: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Service Lifecycle

• Service launches on-demand• System stops service as needed

■ App quits■ Memory pressure■ Idle/lack of use

Page 37: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Sudden terminationXPC Runtime

• Sudden termination management•Disabled when request is live• Enabled when reply is sent

Page 38: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Importance Boosting

• Bundled services■ Background priority by default■ UI app requests boost priority

•Minimize disruption of user experience

Page 39: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Boost Lifetime

Page 40: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Boost Lifetime

Page 41: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Boost Lifetime

Page 42: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Importance Boosting

• launchd services can opt in• ProcessType plist key

Page 43: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Value Contention Behavior Use when…

Adaptive

Background

Interactive

Standard

Contend with apps when doing work on their behalf

app uses XPC to communicate with launchd job

Never contend with apps app has no dependency on launchd job’s work

Always contend with apps the sun explodes

Default valueSimilar behavior as previous releases you just want to purty-up your plist

ProcessType Values

Page 44: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Persisting a Boost

// Transfers boost from ‘message’ to ‘reply’.xpc_object_t reply = xpc_dictionary_create_reply(message);

// Set up work using information in ‘message’ and do it// asynchronously.setup_work_context_with_message(message);dispatch_async(queue, ^{ // After work is done, populate ‘reply‘ with result. xpc_connection_send_message(conn, reply);

// Boost drops after runtime has sent ‘reply’. });

Page 45: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Persisting a Boost

// Transfers boost from ‘message’ to ‘reply’.xpc_object_t reply = xpc_dictionary_create_reply(message);

// Set up work using information in ‘message’ and do it// asynchronously.setup_work_context_with_message(message);dispatch_async(queue, ^{ // After work is done, populate ‘reply‘ with result. xpc_connection_send_message(conn, reply);

// Boost drops after runtime has sent ‘reply’. });

Page 46: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Persisting a Boost

// Transfers boost from ‘message’ to ‘reply’.xpc_object_t reply = xpc_dictionary_create_reply(message);

// Set up work using information in ‘message’ and do it// asynchronously.setup_work_context_with_message(message);dispatch_async(queue, ^{ // After work is done, populate ‘reply‘ with result. xpc_connection_send_message(conn, reply);

// Boost drops after runtime has sent ‘reply’. });

Page 47: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

With anonymous connectionsMultiple Replies

Page 48: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

With anonymous connectionsMultiple Replies

xpc_connection_t ac = xpc_connection_create(NULL, NULL);

Page 49: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Sending Connections

xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);xpc_dictionary_set_connection(message, “backchannel”, ac);xpc_connection_send_message(connection, message);

Page 50: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Sending Connections

xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);xpc_dictionary_set_connection(message, “backchannel”, ac);xpc_connection_send_message(connection, message);

Page 51: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

With anonymous connectionsMultiple Replies

xpc_connection_set_event_handler(backchannel, ^(xpc_object_t conn) { __block size_t seqno = 0; // Accept remote connection. xpc_connection_set_event_handler(conn, ^(xpc_object_t message) { // Receive the reply. bool done = do_stuff_with_message(message, ++seqno); if (done) { xpc_connection_cancel(conn); } });

xpc_connection_resume(conn);});

xpc_connection_resume(backchannel);

Page 52: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

With anonymous connectionsMultiple Replies

xpc_connection_set_event_handler(backchannel, ^(xpc_object_t conn) { __block size_t seqno = 0; // Accept remote connection. xpc_connection_set_event_handler(conn, ^(xpc_object_t message) { // Receive the reply. bool done = do_stuff_with_message(message, ++seqno); if (done) { xpc_connection_cancel(conn); } });

xpc_connection_resume(conn);});

xpc_connection_resume(backchannel);

Page 53: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Server sideMultiple Replies

xpc_connection_t backchannel = xpc_dictionary_create_connection(message, “backchannel”);xpc_connection_set_event_handler(backchannel, ^(xpc_object_t event) { // This is only used for sending. xpc_connection_cancel(backchannel);});xpc_connection_resume(backchannel);

Page 54: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Server sideMultiple Replies

xpc_connection_t backchannel = xpc_dictionary_create_connection(message, “backchannel”);xpc_connection_set_event_handler(backchannel, ^(xpc_object_t event) { // This is only used for sending. xpc_connection_cancel(backchannel);});xpc_connection_resume(backchannel);

Page 55: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Server sideMultiple Replies

xpc_connection_set_event_handler(conn, ^(xpc_object_t message) { // Boost dropped when last block is done and ‘message’ is // released. dispatch_apply(5, queue, ^{ // Do stuff with ‘message’ and populate ‘replyi’. do_stuff_and_populate(message, replyi); xpc_object_t replyi = xpc_dictionary_create(NULL, NULL, 0); xpc_connection_send_message(backchannel, replyi); });});

Page 56: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Server sideMultiple Replies

xpc_connection_set_event_handler(conn, ^(xpc_object_t message) { // Boost dropped when last block is done and ‘message’ is // released. dispatch_apply(5, queue, ^{ // Do stuff with ‘message’ and populate ‘replyi’. do_stuff_and_populate(message, replyi); xpc_object_t replyi = xpc_dictionary_create(NULL, NULL, 0); xpc_connection_send_message(backchannel, replyi); });});

Page 57: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Big Data

• Runtime recognizes large data objects•Object is sent with minimal copies• Copy-less fast path available

Page 58: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

How it worksBig Data

•Deals with VM object backing data• Shares copy-on-write• Page-granular

Page 59: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

Safely Sharing Memory

Page 60: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

Safely Sharing Memory

P0

0x0

0x1000

Page 61: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

Safely Sharing Memory

P0 P1

0x0

0x1000

malloc(3)ed

Random Data

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

0x100 - 0x200

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

0x100 - 0x200

Page 62: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

Safely Sharing Memory

P0 P1

0x0

0x1000

malloc(3)ed

Random Data

0100101010010101001010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101110101010101010001010101001010010101001010100101010101010000101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010010010101001010100101010101010101001011101010101010100010101010010010000101001001010100101010010101010101010100101110101010101010001010101001001000010100100101010010101001010101010101010010111010101010101000101010100100100001010

0x100 - 0x200

Page 63: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Minimizing copiesBig Data

• Create dispatch data object•DISPATCH_DATA_DESTRUCTOR_MUNMAP•Wrap dispatch data in XPC data

Page 64: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Sending Big Data

// Points to large mmap(2)ed region of memory.void *buff;// Size of region pointed to by ‘buff’.size_t sz;

dispatch_data_t ddata = dispatch_data_create(buff, sz, DISPATCH_TARGET_QUEUE_DEFAULT, DISPATCH_DATA_DESTRUCTOR_MUNMAP);

// ‘buff’ is now owned by ‘ddata’.xpc_object_t xdata = xpc_data_create_with_dispatch_data(ddata);

// Send ‘xdata’ in a message.// Look Ma! No copies!

Page 65: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Sending Big Data

// Points to large mmap(2)ed region of memory.void *buff;// Size of region pointed to by ‘buff’.size_t sz;

dispatch_data_t ddata = dispatch_data_create(buff, sz, DISPATCH_TARGET_QUEUE_DEFAULT, DISPATCH_DATA_DESTRUCTOR_MUNMAP);

// ‘buff’ is now owned by ‘ddata’.xpc_object_t xdata = xpc_data_create_with_dispatch_data(ddata);

// Send ‘xdata’ in a message.// Look Ma! No copies!

Page 66: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Sending Big Data

// Points to large mmap(2)ed region of memory.void *buff;// Size of region pointed to by ‘buff’.size_t sz;

dispatch_data_t ddata = dispatch_data_create(buff, sz, DISPATCH_TARGET_QUEUE_DEFAULT, DISPATCH_DATA_DESTRUCTOR_MUNMAP);

// ‘buff’ is now owned by ‘ddata’.xpc_object_t xdata = xpc_data_create_with_dispatch_data(ddata);

// Send ‘xdata’ in a message.// Look Ma! No copies!

Page 67: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Using NSXPCConnectionBig Data

•Dispatch data toll-free bridged with NSData•Not subclasses•Not no-copy•Any of the following

■ Mapped■ NSDataDeallocatorVM■ NSDataDeallocatorMunmap

Page 68: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Receive Fast Path

•Message-receive much faster• Substantially reduced allocations and copies•Drain messages more quickly

Page 69: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Eligible messagesReceive Fast Path

•No out-of-line types■ File descriptors■ Shared memory

Page 70: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Forcing the slow pathReceive Fast Path

• Some actions force full unpack■ Copying■ xpc_dictionary_apply(3)

• xpc_dictionary_get_value(3)•Accessing nested containers•Modifying dictionary

Page 71: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Timeouts

Page 72: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Timeouts

• XPC APIs have no support for timeouts•Unneeded in most cases

Page 73: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Timeouts

• Local-machine and network IPC different• Kernel is not unreliable medium• Server should always be responsive

Page 74: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Masking bugsTimeouts

• Can confuse behavior expectations■ Operation may have timed out■ Server may have a bug

• Expressed to client identically

Page 75: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Server-Side Timeout

• If service does network operations■ Have it manage timeout■ Return ETIMEDOUT (or similar) to client

• Lack of response indicates server bug

Page 76: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

When they are neededTimeouts

•Hard deadline for response•When transit time makes a difference

■ “Real time”■ Derived from desired throughput rate■ fps, Hz, etc.

•Not arbitrary

Page 77: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Debugging Tips

Page 78: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Debugging

• Xcode enhancements■ Transparent breakpoints■ Debugging services just works■ Copy Files destination

• imptrace(1) for debugging boosts

Page 79: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Debugging

• Connection-invalid indicates configuration error•Make sure service target…

■ is dependency of app target■ is in Copy Files build phase

•Make sure CFBundleIdentifier matches service name

Page 80: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

API Misuse

• XPC API is defensive•Aborts on detectable corruption/misuse

■ Retain count underflow■ Obvious API misuse■ xpc_abort(3)

• Issues illegal instruction—SIGILL

Page 81: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

API Misuse

• Look in Application-Specific Information•Under lldb

■ xpc_debugger_api_misuse_info(3)■ Returns (const char *)

Page 82: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Crash Report

Exception Type: EXC_BAD_INSTRUCTION (SIGILL)Exception Codes: 0x0000000000000001, 0x0000000000000000

Application Specific Information:API MISUSE: Over-release of an object

Page 83: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Crash Report

Exception Type: EXC_BAD_INSTRUCTION (SIGILL)Exception Codes: 0x0000000000000001, 0x0000000000000000

Application Specific Information:API MISUSE: Over-release of an object

Page 84: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

lldb

Program received signal EXC_BAD_INSTRUCTION, Illegal instruction/operand.0x000000010012b25e in _xpc_api_misuse ()(lldb) p (char *)xpc_debugger_api_misuse_info()$1 = 0x7fff5fbff908 "XPC API Misuse: Over-release of object."(lldb)

Page 85: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

lldb

Program received signal EXC_BAD_INSTRUCTION, Illegal instruction/operand.0x000000010012b25e in _xpc_api_misuse ()(lldb) p (char *)xpc_debugger_api_misuse_info()$1 = 0x7fff5fbff908 "XPC API Misuse: Over-release of object."(lldb)

Page 86: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

libxpc Assertions

•Might see messages in system logassertion failed: 13A476z: libxpc.dylib + 2794 [0B05C709-16BA-3C31-ACC6-1234774ED777]: 0x11

• Indicates unexpected but non-fatal error• File a bug

Page 87: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

More Information

Paul DanboldCore OS Technology [email protected]

Documentationxpc(3)/usr/include/xpcDaemons and Services Programming Guide

Apple Developer Forumsdevforums.apple.com

Page 88: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Related Sessions

Building Efficient OS X Apps Nob HillTuesday 4:30PM

Debugging with Xcode Pacific HeightsWednesday 2:00PM

Page 89: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps

Labs

CoreOS Lab Open Hours CoreOS Labs A/BFriday 2:00PM

XPC and GCD Lab CoreOS Lab BTuesday 3:15PM

Page 90: Efficient Design with XPC - Apple Inc....app uses XPC to communicate with launchd job Never contend with apps app has no dependency on launchd job’s work Always contend with apps