Add gluecode for systrace

Summary: @​public

Add gluecode to allow use to systrace as the backend of RCTProfile

Reviewed By: @jspahrsummers

Differential Revision: D2439181
This commit is contained in:
Tadeu Zagallo 2015-09-23 11:59:44 -07:00 committed by facebook-github-bot-6
parent dcf245a9a2
commit 98378cab18
2 changed files with 159 additions and 41 deletions

View File

@ -125,6 +125,34 @@ RCT_EXTERN void RCTProfileUnhookModules(RCTBridge *);
*/ */
RCT_EXTERN void RCTProfileSendResult(RCTBridge *bridge, NSString *route, NSData *profielData); RCT_EXTERN void RCTProfileSendResult(RCTBridge *bridge, NSString *route, NSData *profielData);
/**
* Systrace gluecode
*
* allow to use systrace to back RCTProfile
*/
typedef struct {
const char *key;
int key_len;
const char *value;
int value_len;
} systrace_arg_t;
typedef struct {
void (*start)(uint64_t enabledTags, char *buffer, size_t bufferSize);
void (*stop)(void);
void (*begin_section)(uint64_t tag, const char *name, size_t numArgs, systrace_arg_t *args);
void (*end_section)(uint64_t tag, size_t numArgs, systrace_arg_t *args);
void (*begin_async_section)(uint64_t tag, const char *name, int cookie, size_t numArgs, systrace_arg_t *args);
void (*end_async_section)(uint64_t tag, const char *name, int cookie, size_t numArgs, systrace_arg_t *args);
void (*instant_section)(uint64_t tag, const char *name, char scope);
} RCTProfileCallbacks;
RCT_EXTERN void RCTProfileRegisterCallbacks(RCTProfileCallbacks *);
#else #else
#define RCTProfileBeginFlowEvent() #define RCTProfileBeginFlowEvent()

View File

@ -35,11 +35,11 @@ NSString *const RCTProfilePrefix = @"rct_profile_";
#pragma mark - Variables #pragma mark - Variables
NSDictionary *RCTProfileInfo; static BOOL RCTProfileProfiling;
NSUInteger RCTProfileEventID = 0; static NSDictionary *RCTProfileInfo;
NSMutableDictionary *RCTProfileOngoingEvents; static NSMutableDictionary *RCTProfileOngoingEvents;
NSTimeInterval RCTProfileStartTime; static NSTimeInterval RCTProfileStartTime;
NSRecursiveLock *_RCTProfileLock; static NSUInteger RCTProfileEventID = 0;
#pragma mark - Macros #pragma mark - Macros
@ -56,12 +56,55 @@ if (!RCTProfileIsProfiling()) { \
} }
#define RCTProfileLock(...) \ #define RCTProfileLock(...) \
[_RCTProfileLock lock]; \ [_RCTProfileLock() lock]; \
__VA_ARGS__ \ __VA_ARGS__ \
[_RCTProfileLock unlock] [_RCTProfileLock() unlock]
#pragma mark - systrace glue code
static RCTProfileCallbacks *callbacks;
static char *systrace_buffer;
static systrace_arg_t *RCTProfileSystraceArgsFromNSDictionary(NSDictionary *args)
{
if (args.count == 0) {
return NULL;
}
systrace_arg_t *systrace_args = malloc(sizeof(systrace_arg_t) * args.count);
__block size_t i = 0;
[args enumerateKeysAndObjectsUsingBlock:^(id key, id value, __unused BOOL *stop) {
const char *keyc = [key description].UTF8String;
systrace_args[i].key = keyc;
systrace_args[i].key_len = (int)strlen(keyc);
const char *valuec = RCTJSONStringify(value, nil).UTF8String;
systrace_args[i].value = valuec;
systrace_args[i].value_len = (int)strlen(valuec);
i++;
}];
return systrace_args;
}
void RCTProfileRegisterCallbacks(RCTProfileCallbacks *cb)
{
callbacks = cb;
}
#pragma mark - Private Helpers #pragma mark - Private Helpers
static NSLock *_RCTProfileLock()
{
static dispatch_once_t token;
static NSLock *lock;
dispatch_once(&token, ^{
lock = [NSLock new];
lock.name = @"RCTProfileLock";
});
return lock;
}
static NSNumber *RCTProfileTimestamp(NSTimeInterval timestamp) static NSNumber *RCTProfileTimestamp(NSTimeInterval timestamp)
{ {
return @((timestamp - RCTProfileStartTime) * 1e6); return @((timestamp - RCTProfileStartTime) * 1e6);
@ -215,20 +258,19 @@ void RCTProfileUnhookModules(RCTBridge *bridge)
BOOL RCTProfileIsProfiling(void) BOOL RCTProfileIsProfiling(void)
{ {
RCTProfileLock( return RCTProfileProfiling;
BOOL profiling = RCTProfileInfo != nil;
);
return profiling;
} }
void RCTProfileInit(RCTBridge *bridge) void RCTProfileInit(RCTBridge *bridge)
{ {
RCTProfileHookModules(bridge); RCTProfileHookModules(bridge);
RCTProfileProfiling = YES;
static dispatch_once_t onceToken; if (callbacks != NULL) {
dispatch_once(&onceToken, ^{ size_t buffer_size = 1 << 22;
_RCTProfileLock = [NSRecursiveLock new]; systrace_buffer = calloc(1, buffer_size);
}); callbacks->start(~((uint64_t)0), systrace_buffer, buffer_size);
} else {
RCTProfileLock( RCTProfileLock(
RCTProfileStartTime = CACurrentMediaTime(); RCTProfileStartTime = CACurrentMediaTime();
RCTProfileOngoingEvents = [NSMutableDictionary new]; RCTProfileOngoingEvents = [NSMutableDictionary new];
@ -237,6 +279,7 @@ void RCTProfileInit(RCTBridge *bridge)
RCTProfileSamples: [NSMutableArray new], RCTProfileSamples: [NSMutableArray new],
}; };
); );
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidStartProfiling [[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidStartProfiling
object:nil]; object:nil];
@ -247,6 +290,17 @@ NSString *RCTProfileEnd(RCTBridge *bridge)
[[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidEndProfiling [[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidEndProfiling
object:nil]; object:nil];
RCTProfileProfiling = NO;
RCTProfileLock(
RCTProfileUnhookModules(bridge);
);
if (callbacks != NULL) {
callbacks->stop();
return @(systrace_buffer);
} else {
RCTProfileLock( RCTProfileLock(
NSString *log = RCTJSONStringify(RCTProfileInfo, NULL); NSString *log = RCTJSONStringify(RCTProfileInfo, NULL);
RCTProfileEventID = 0; RCTProfileEventID = 0;
@ -254,10 +308,9 @@ NSString *RCTProfileEnd(RCTBridge *bridge)
RCTProfileOngoingEvents = nil; RCTProfileOngoingEvents = nil;
); );
RCTProfileUnhookModules(bridge);
return log; return log;
} }
}
static NSMutableArray *RCTProfileGetThreadEvents(void) static NSMutableArray *RCTProfileGetThreadEvents(void)
{ {
@ -273,6 +326,12 @@ static NSMutableArray *RCTProfileGetThreadEvents(void)
void RCTProfileBeginEvent(uint64_t tag, NSString *name, NSDictionary *args) void RCTProfileBeginEvent(uint64_t tag, NSString *name, NSDictionary *args)
{ {
CHECK(); CHECK();
if (callbacks != NULL) {
callbacks->begin_section(tag, name.UTF8String, args.count, RCTProfileSystraceArgsFromNSDictionary(args));
return;
}
NSMutableArray *events = RCTProfileGetThreadEvents(); NSMutableArray *events = RCTProfileGetThreadEvents();
[events addObject:@[ [events addObject:@[
RCTProfileTimestamp(CACurrentMediaTime()), RCTProfileTimestamp(CACurrentMediaTime()),
@ -283,12 +342,17 @@ void RCTProfileBeginEvent(uint64_t tag, NSString *name, NSDictionary *args)
} }
void RCTProfileEndEvent( void RCTProfileEndEvent(
__unused uint64_t tag, uint64_t tag,
NSString *category, NSString *category,
NSDictionary *args NSDictionary *args
) { ) {
CHECK(); CHECK();
if (callbacks != NULL) {
callbacks->end_section(tag, args.count, RCTProfileSystraceArgsFromNSDictionary(args));
return;
}
NSMutableArray *events = RCTProfileGetThreadEvents(); NSMutableArray *events = RCTProfileGetThreadEvents();
NSArray *event = events.lastObject; NSArray *event = events.lastObject;
[events removeLastObject]; [events removeLastObject];
@ -312,7 +376,7 @@ void RCTProfileEndEvent(
} }
int RCTProfileBeginAsyncEvent( int RCTProfileBeginAsyncEvent(
__unused uint64_t tag, uint64_t tag,
NSString *name, NSString *name,
NSDictionary *args NSDictionary *args
) { ) {
@ -320,6 +384,9 @@ int RCTProfileBeginAsyncEvent(
static int eventID = 0; static int eventID = 0;
if (callbacks != NULL) {
callbacks->begin_async_section(tag, name.UTF8String, eventID, args.count, RCTProfileSystraceArgsFromNSDictionary(args));
} else {
RCTProfileLock( RCTProfileLock(
RCTProfileOngoingEvents[@(eventID)] = @[ RCTProfileOngoingEvents[@(eventID)] = @[
RCTProfileTimestamp(CACurrentMediaTime()), RCTProfileTimestamp(CACurrentMediaTime()),
@ -327,18 +394,25 @@ int RCTProfileBeginAsyncEvent(
RCTNullIfNil(args), RCTNullIfNil(args),
]; ];
); );
}
return eventID++; return eventID++;
} }
void RCTProfileEndAsyncEvent( void RCTProfileEndAsyncEvent(
__unused uint64_t tag, uint64_t tag,
NSString *category, NSString *category,
int cookie, int cookie,
__unused NSString *name, NSString *name,
NSDictionary *args NSDictionary *args
) { ) {
CHECK(); CHECK();
if (callbacks != NULL) {
callbacks->end_async_section(tag, name.UTF8String, cookie, args.count, RCTProfileSystraceArgsFromNSDictionary(args));
return;
}
RCTProfileLock( RCTProfileLock(
NSArray *event = RCTProfileOngoingEvents[@(cookie)]; NSArray *event = RCTProfileOngoingEvents[@(cookie)];
if (event) { if (event) {
@ -358,12 +432,17 @@ void RCTProfileEndAsyncEvent(
} }
void RCTProfileImmediateEvent( void RCTProfileImmediateEvent(
__unused uint64_t tag, uint64_t tag,
NSString *name, NSString *name,
char scope char scope
) { ) {
CHECK(); CHECK();
if (callbacks != NULL) {
callbacks->instant_section(tag, name.UTF8String, scope);
return;
}
RCTProfileLock( RCTProfileLock(
RCTProfileAddEvent(RCTProfileTraceEvents, RCTProfileAddEvent(RCTProfileTraceEvents,
@"name": name, @"name": name,
@ -380,6 +459,12 @@ NSNumber *_RCTProfileBeginFlowEvent(void)
static NSUInteger flowID = 0; static NSUInteger flowID = 0;
CHECK(@0); CHECK(@0);
if (callbacks != NULL) {
// flow events not supported yet
return @0;
}
RCTProfileAddEvent(RCTProfileTraceEvents, RCTProfileAddEvent(RCTProfileTraceEvents,
@"name": @"flow", @"name": @"flow",
@"id": @(++flowID), @"id": @(++flowID),
@ -394,6 +479,11 @@ NSNumber *_RCTProfileBeginFlowEvent(void)
void _RCTProfileEndFlowEvent(NSNumber *flowID) void _RCTProfileEndFlowEvent(NSNumber *flowID)
{ {
CHECK(); CHECK();
if (callbacks != NULL) {
return;
}
RCTProfileAddEvent(RCTProfileTraceEvents, RCTProfileAddEvent(RCTProfileTraceEvents,
@"name": @"flow", @"name": @"flow",
@"id": flowID, @"id": flowID,