Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASSignpost: Add support for the os_signpost API, fixes #1501

Merged
merged 4 commits into from
May 9, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Source/ASRunLoopQueue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ - (void)processQueue
return;
}

ASSignpostStart(ASSignpostRunLoopQueueBatch);
ASSignpostStart(RunLoopQueueBatch, self, "%s", object_getClassName(self));

// Snatch the next batch of items.
NSInteger maxCountToProcess = MIN(internalQueueCount, self.batchSize);
Expand Down Expand Up @@ -278,7 +278,7 @@ - (void)processQueue
CFRunLoopWakeUp(_runLoop);
}

ASSignpostEnd(ASSignpostRunLoopQueueBatch);
ASSignpostEnd(RunLoopQueueBatch, self, "count: %d", (int)count);
}

- (void)enqueue:(id)object
Expand Down Expand Up @@ -440,7 +440,7 @@ - (void)processQueue
return;
}
as_activity_scope_verbose(as_activity_create("Process run loop queue batch", _rootActivity, OS_ACTIVITY_FLAG_DEFAULT));
ASSignpostStart(ASSignpostRunLoopQueueBatch);
ASSignpostStart(RunLoopQueueBatch, self, "CATransactionQueue");

// Swap buffers, clear our hash table.
_internalQueue.swap(_batchBuffer);
Expand All @@ -455,7 +455,7 @@ - (void)processQueue
}
_batchBuffer.clear();
as_log_verbose(ASDisplayLog(), "processed %lu items", (unsigned long)count);
ASSignpostEnd(ASSignpostRunLoopQueueBatch);
ASSignpostEnd(RunLoopQueueBatch, self, "count: %d", (int)count);
}

- (void)enqueue:(id<ASCATransactionQueueObserving>)object
Expand Down
3 changes: 3 additions & 0 deletions Source/Base/ASLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ AS_EXTERN os_log_t ASMainThreadDeallocationLog(void);
#define ASLockingLogEnabled 0
AS_EXTERN os_log_t ASLockingLog(void);

/// Uses the special POI category for Instruments. Used by ASSignpost.h.
AS_EXTERN os_log_t ASPointsOfInterestLog(void);

/**
* The activity tracing system changed a lot between iOS 9 and 10.
* In iOS 10, the system was merged with logging and became much more powerful
Expand Down
5 changes: 5 additions & 0 deletions Source/Base/ASLog.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import <AsyncDisplayKit/ASLog.h>
#import <stdatomic.h>
#import <os/signpost.h>

static atomic_bool __ASLogEnabled = ATOMIC_VAR_INIT(YES);

Expand Down Expand Up @@ -50,3 +51,7 @@ os_log_t ASMainThreadDeallocationLog() {
os_log_t ASLockingLog() {
return (ASLockingLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(os_log_create("org.TextureGroup.Texture", "Locking")) : OS_LOG_DISABLED;
}

os_log_t ASPointsOfInterestLog() {
return ASCreateOnce(os_log_create("org.TextureGroup.Texture", OS_LOG_CATEGORY_POINTS_OF_INTEREST));
}
72 changes: 30 additions & 42 deletions Source/Base/ASSignpost.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,22 @@
/// The signposts we use. Signposts are grouped by color. The SystemTrace.tracetemplate file
/// should be kept up-to-date with these values.
typedef NS_ENUM(uint32_t, ASSignpostName) {
// Collection/Table (Blue)
// Collection/Table
ASSignpostDataControllerBatch = 300, // Alloc/layout nodes before collection update.
ASSignpostRangeControllerUpdate, // Ranges update pass.
ASSignpostCollectionUpdate, // Entire update process, from -endUpdates to [super perform…]

// Rendering (Green)
// Rendering
ASSignpostLayerDisplay = 325, // Client display callout.
ASSignpostRunLoopQueueBatch, // One batch of ASRunLoopQueue.

// Layout (Purple)
// Layout
ASSignpostCalculateLayout = 350, // Start of calculateLayoutThatFits to end. Max 1 per thread.

// Misc (Orange)
// Misc
ASSignpostDeallocQueueDrain = 375, // One chunk of dealloc queue work. arg0 is count.
ASSignpostCATransactionLayout, // The CA transaction commit layout phase.
ASSignpostCATransactionCommit // The CA transaction commit post-layout phase.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two have been unused for a while.

ASSignpostStatusBarOrientationChange, // From WillChangeStatusBarOrientation to animation end.
};

typedef NS_ENUM(uintptr_t, ASSignpostColor) {
ASSignpostColorBlue,
ASSignpostColorGreen,
ASSignpostColorPurple,
ASSignpostColorOrange,
ASSignpostColorRed,
ASSignpostColorDefault
};

static inline ASSignpostColor ASSignpostGetColor(ASSignpostName name, ASSignpostColor colorPref) {
if (colorPref == ASSignpostColorDefault) {
return (ASSignpostColor)((name / 25) % 4);
} else {
return colorPref;
}
}

#if defined(PROFILE) && __has_include(<sys/kdebug_signpost.h>)
#define AS_KDEBUG_ENABLE 1
#else
Expand All @@ -53,6 +34,7 @@ static inline ASSignpostColor ASSignpostGetColor(ASSignpostName name, ASSignpost
#if AS_KDEBUG_ENABLE

#import <sys/kdebug_signpost.h>
#import <os/signpost.h>

// These definitions are required to build the backward-compatible kdebug trace
// on the iOS 10 SDK. The kdebug_trace function crashes if run on iOS 9 and earlier.
Expand All @@ -68,27 +50,33 @@ static inline ASSignpostColor ASSignpostGetColor(ASSignpostName name, ASSignpost
#define APPSDBG_CODE(SubClass,code) KDBG_CODE(DBG_APPS, SubClass, code)
#endif

// Currently we'll reserve arg3.
#define ASSignpost(name, identifier, arg2, color) \
AS_AT_LEAST_IOS10 ? kdebug_signpost(name, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color)) \
: syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, name) | DBG_FUNC_NONE, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color));

#define ASSignpostStartCustom(name, identifier, arg2) \
AS_AT_LEAST_IOS10 ? kdebug_signpost_start(name, (uintptr_t)identifier, (uintptr_t)arg2, 0, 0) \
: syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, name) | DBG_FUNC_START, (uintptr_t)identifier, (uintptr_t)arg2, 0, 0);
#define ASSignpostStart(name) ASSignpostStartCustom(name, self, 0)
#define ASSignpostStart(name, identifier, format, ...) ({\
if (AS_AVAILABLE_IOS_TVOS(12, 12)) { \
unowned os_log_t log = ASPointsOfInterestLog(); \
os_signpost_id_t spid = os_signpost_id_make_with_id(log, identifier); \
os_signpost_interval_begin(log, spid, #name, format, ##__VA_ARGS__); \
} else if (AS_AVAILABLE_IOS_TVOS(10, 10)) { \
kdebug_signpost_start(ASSignpost##name, (uintptr_t)identifier, 0, 0, 0); \
} else { \
syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, ASSignpost##name) | DBG_FUNC_START, (uintptr_t)identifier, 0, 0, 0); \
} \
})

#define ASSignpostEndCustom(name, identifier, arg2, color) \
AS_AT_LEAST_IOS10 ? kdebug_signpost_end(name, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color)) \
: syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, name) | DBG_FUNC_END, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color));
#define ASSignpostEnd(name) ASSignpostEndCustom(name, self, 0, ASSignpostColorDefault)
#define ASSignpostEnd(name, identifier, format, ...) ({\
if (AS_AVAILABLE_IOS_TVOS(12, 12)) { \
unowned os_log_t log = ASPointsOfInterestLog(); \
os_signpost_id_t spid = os_signpost_id_make_with_id(log, identifier); \
os_signpost_interval_end(log, spid, #name, format, ##__VA_ARGS__); \
} else if (AS_AVAILABLE_IOS_TVOS(10, 10)) { \
kdebug_signpost_end(ASSignpost##name, (uintptr_t)identifier, 0, 0, 0); \
} else { \
syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, ASSignpost##name) | DBG_FUNC_END, (uintptr_t)identifier, 0, 0, 0); \
} \
})

#else

#define ASSignpost(name, identifier, arg2, color)
#define ASSignpostStartCustom(name, identifier, arg2)
#define ASSignpostStart(name)
#define ASSignpostEndCustom(name, identifier, arg2, color)
#define ASSignpostEnd(name)
#define ASSignpostStart(name, identifier, format, ...)
#define ASSignpostEnd(name, identifier, format, ...)

#endif
4 changes: 2 additions & 2 deletions Source/Details/ASDataController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ - (void)_allocateNodesFromElements:(NSArray<ASCollectionElement *> *)elements
return;
}

ASSignpostStart(ASSignpostDataControllerBatch);
ASSignpostStart(DataControllerBatch, self, "%@", ASObjectDescriptionMakeTiny(weakDataSource));

{
as_activity_create_for_scope("Data controller batch");
Expand Down Expand Up @@ -179,7 +179,7 @@ - (void)_allocateNodesFromElements:(NSArray<ASCollectionElement *> *)elements
});
}

ASSignpostEndCustom(ASSignpostDataControllerBatch, self, 0, (weakDataSource != nil ? ASSignpostColorDefault : ASSignpostColorRed));
ASSignpostEnd(DataControllerBatch, self, "count: %lu", (unsigned long)nodeCount);
}

/**
Expand Down
5 changes: 4 additions & 1 deletion Source/Details/ASObjectDescriptionHelpers.mm
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@
}

NSString *ASObjectDescriptionMakeTiny(__autoreleasing id object) {
return ASObjectDescriptionMake(object, nil);
static constexpr int kBufSize = 64;
char buf[kBufSize];
int len = snprintf(buf, kBufSize, "<%s: %p>", object_getClassName(object), object);
return (__bridge_transfer NSString *)CFStringCreateWithBytes(NULL, (const UInt8 *)buf, len, kCFStringEncodingASCII, false);
}

NSString *ASStringWithQuotesIfMultiword(NSString *string) {
Expand Down
5 changes: 3 additions & 2 deletions Source/Details/ASRangeController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ - (void)_updateVisibleNodeIndexPaths
auto visibleElements = [_dataSource visibleElementsForRangeController:self];
NSHashTable *newVisibleNodes = [NSHashTable hashTableWithOptions:NSHashTableObjectPointerPersonality];

ASSignpostStart(ASSignpostRangeControllerUpdate);
ASSignpostStart(RangeControllerUpdate, _dataSource, "%@", ASObjectDescriptionMakeTiny(_dataSource));

// Get the scroll direction. Default to using the previous one, if they're not scrolling.
ASScrollDirection scrollDirection = [_dataSource scrollDirectionForRangeController:self];
Expand All @@ -243,6 +243,7 @@ - (void)_updateVisibleNodeIndexPaths
[newVisibleNodes addObject:element.node];
}
[self _setVisibleNodes:newVisibleNodes];
ASSignpostEnd(RangeControllerUpdate, _dataSource, "");
return; // don't do anything for this update, but leave _rangeIsValid == NO to make sure we update it later
}

Expand Down Expand Up @@ -424,7 +425,7 @@ - (void)_updateVisibleNodeIndexPaths
NSLog(@"Range update complete; modifiedIndexPaths: %@, rangeMode: %d", [self descriptionWithIndexPaths:modifiedIndexPaths], rangeMode);
#endif

ASSignpostEnd(ASSignpostRangeControllerUpdate);
ASSignpostEnd(RangeControllerUpdate, _dataSource, "");
}

#pragma mark - Notification observers
Expand Down
6 changes: 3 additions & 3 deletions Source/Private/ASDisplayNode+AsyncDisplay.mm
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,11 @@ - (asyncdisplaykit_async_transaction_operation_block_t)_displayBlockWithAsynchro
Color the interval red if cancelled, green otherwise.
*/
#if AS_KDEBUG_ENABLE
__unsafe_unretained id ptrSelf = self;
__unsafe_unretained id ptrSelf = (id)self;
displayBlock = ^{
ASSignpostStartCustom(ASSignpostLayerDisplay, ptrSelf, 0);
ASSignpostStart(LayerDisplay, ptrSelf, "%@", ASObjectDescriptionMakeTiny(ptrSelf));
id result = displayBlock();
ASSignpostEndCustom(ASSignpostLayerDisplay, ptrSelf, 0, isCancelledBlock() ? ASSignpostColorRed : ASSignpostColorGreen);
ASSignpostEnd(LayerDisplay, ptrSelf, "(%d %d), canceled: %d", (int)bounds.size.width, (int)bounds.size.height, (int)isCancelledBlock());
return result;
};
#endif
Expand Down
26 changes: 26 additions & 0 deletions Source/Private/ASInternalHelpers.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#import <AsyncDisplayKit/ASConfigurationInternal.h>
#import <AsyncDisplayKit/ASRunLoopQueue.h>
#import <AsyncDisplayKit/ASSignpost.h>
#import <AsyncDisplayKit/ASThread.h>

static NSNumber *allowsGroupOpacityFromUIKitOrNil;
Expand Down Expand Up @@ -43,6 +44,28 @@ BOOL ASDefaultAllowsEdgeAntialiasing()
return edgeAntialiasing;
}

#if AS_KDEBUG_ENABLE
void _ASInitializeSignpostObservers(void)
{
#if !TARGET_OS_TV
// Orientation changes.
[NSNotificationCenter.defaultCenter addObserverForName:UIApplicationWillChangeStatusBarOrientationNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
UIInterfaceOrientation orientation = (UIInterfaceOrientation)[note.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
ASSignpostStart(StatusBarOrientationChange, (id)nil, "from %s", UIInterfaceOrientationIsPortrait(orientation) ? "portrait" : "landscape");
[CATransaction begin];
}];
[NSNotificationCenter.defaultCenter addObserverForName:UIApplicationDidChangeStatusBarOrientationNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
// When profiling, go ahead and commit the transaction early so that it happens as part of our interval.
UIInterfaceOrientation orientation = (UIInterfaceOrientation)[note.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
[CATransaction setCompletionBlock:^{
ASSignpostEnd(StatusBarOrientationChange, (id)nil, "to %s", UIInterfaceOrientationIsPortrait(orientation) ? "portrait" : "landscape");
}];
[CATransaction commit];
}];
#endif
}
#endif

void ASInitializeFrameworkMainThread(void)
{
static dispatch_once_t onceToken;
Expand All @@ -57,6 +80,9 @@ void ASInitializeFrameworkMainThread(void)
allowsEdgeAntialiasingFromUIKitOrNil = @(layer.allowsEdgeAntialiasing);
}
ASNotifyInitialized();
#if AS_KDEBUG_ENABLE
_ASInitializeSignpostObservers();
#endif
});
}

Expand Down