2015-04-20 11:55:05 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import "RCTProfile.h"
|
|
|
|
|
|
|
|
#import <mach/mach.h>
|
|
|
|
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
|
2015-05-25 12:19:53 +00:00
|
|
|
#import "RCTAssert.h"
|
2015-04-21 12:26:51 +00:00
|
|
|
#import "RCTDefines.h"
|
2015-04-20 11:55:05 +00:00
|
|
|
#import "RCTUtils.h"
|
|
|
|
|
2015-06-02 13:15:53 +00:00
|
|
|
NSString *const RCTProfileDidStartProfiling = @"RCTProfileDidStartProfiling";
|
|
|
|
NSString *const RCTProfileDidEndProfiling = @"RCTProfileDidEndProfiling";
|
|
|
|
|
2015-04-21 12:26:51 +00:00
|
|
|
#if RCT_DEV
|
2015-04-20 13:33:52 +00:00
|
|
|
|
2015-04-20 11:55:05 +00:00
|
|
|
#pragma mark - Prototypes
|
|
|
|
|
|
|
|
NSNumber *RCTProfileTimestamp(NSTimeInterval);
|
|
|
|
NSString *RCTProfileMemory(vm_size_t);
|
|
|
|
NSDictionary *RCTProfileGetMemoryUsage(void);
|
|
|
|
|
|
|
|
#pragma mark - Constants
|
|
|
|
|
|
|
|
NSString const *RCTProfileTraceEvents = @"traceEvents";
|
|
|
|
NSString const *RCTProfileSamples = @"samples";
|
|
|
|
|
|
|
|
#pragma mark - Variables
|
|
|
|
|
|
|
|
NSDictionary *RCTProfileInfo;
|
|
|
|
NSUInteger RCTProfileEventID = 0;
|
|
|
|
NSMutableDictionary *RCTProfileOngoingEvents;
|
|
|
|
NSTimeInterval RCTProfileStartTime;
|
2015-04-22 14:03:55 +00:00
|
|
|
NSLock *_RCTProfileLock;
|
2015-04-20 11:55:05 +00:00
|
|
|
|
|
|
|
#pragma mark - Macros
|
|
|
|
|
|
|
|
#define RCTProfileAddEvent(type, props...) \
|
|
|
|
[RCTProfileInfo[type] addObject:@{ \
|
|
|
|
@"pid": @([[NSProcessInfo processInfo] processIdentifier]), \
|
2015-05-25 12:19:53 +00:00
|
|
|
@"tid": RCTCurrentThreadName(), \
|
2015-04-20 11:55:05 +00:00
|
|
|
props \
|
|
|
|
}];
|
|
|
|
|
|
|
|
#define CHECK(...) \
|
|
|
|
if (!RCTProfileIsProfiling()) { \
|
|
|
|
return __VA_ARGS__; \
|
|
|
|
}
|
|
|
|
|
2015-04-22 14:03:55 +00:00
|
|
|
#define RCTProfileLock(...) \
|
|
|
|
[_RCTProfileLock lock]; \
|
|
|
|
__VA_ARGS__ \
|
|
|
|
[_RCTProfileLock unlock]
|
|
|
|
|
2015-04-20 11:55:05 +00:00
|
|
|
#pragma mark - Private Helpers
|
|
|
|
|
|
|
|
NSNumber *RCTProfileTimestamp(NSTimeInterval timestamp)
|
|
|
|
{
|
|
|
|
return @((timestamp - RCTProfileStartTime) * 1e6);
|
|
|
|
}
|
|
|
|
|
|
|
|
NSString *RCTProfileMemory(vm_size_t memory)
|
|
|
|
{
|
|
|
|
double mem = ((double)memory) / 1024 / 1024;
|
|
|
|
return [NSString stringWithFormat:@"%.2lfmb", mem];
|
|
|
|
}
|
|
|
|
|
|
|
|
NSDictionary *RCTProfileGetMemoryUsage(void)
|
|
|
|
{
|
|
|
|
struct task_basic_info info;
|
|
|
|
mach_msg_type_number_t size = sizeof(info);
|
|
|
|
kern_return_t kerr = task_info(mach_task_self(),
|
|
|
|
TASK_BASIC_INFO,
|
|
|
|
(task_info_t)&info,
|
|
|
|
&size);
|
|
|
|
if( kerr == KERN_SUCCESS ) {
|
|
|
|
return @{
|
|
|
|
@"suspend_count": @(info.suspend_count),
|
|
|
|
@"virtual_size": RCTProfileMemory(info.virtual_size),
|
|
|
|
@"resident_size": RCTProfileMemory(info.resident_size),
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return @{};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Public Functions
|
|
|
|
|
|
|
|
BOOL RCTProfileIsProfiling(void)
|
|
|
|
{
|
2015-04-22 14:03:55 +00:00
|
|
|
RCTProfileLock(
|
|
|
|
BOOL profiling = RCTProfileInfo != nil;
|
|
|
|
);
|
|
|
|
return profiling;
|
2015-04-20 11:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RCTProfileInit(void)
|
|
|
|
{
|
2015-04-22 14:03:55 +00:00
|
|
|
static dispatch_once_t onceToken;
|
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
|
_RCTProfileLock = [[NSLock alloc] init];
|
|
|
|
});
|
|
|
|
RCTProfileLock(
|
|
|
|
RCTProfileStartTime = CACurrentMediaTime();
|
|
|
|
RCTProfileOngoingEvents = [[NSMutableDictionary alloc] init];
|
|
|
|
RCTProfileInfo = @{
|
|
|
|
RCTProfileTraceEvents: [[NSMutableArray alloc] init],
|
|
|
|
RCTProfileSamples: [[NSMutableArray alloc] init],
|
|
|
|
};
|
|
|
|
);
|
2015-06-02 13:15:53 +00:00
|
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidStartProfiling
|
|
|
|
object:nil];
|
2015-04-20 11:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSString *RCTProfileEnd(void)
|
|
|
|
{
|
2015-06-02 13:15:53 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidEndProfiling
|
|
|
|
object:nil];
|
|
|
|
|
2015-04-22 14:03:55 +00:00
|
|
|
RCTProfileLock(
|
|
|
|
NSString *log = RCTJSONStringify(RCTProfileInfo, NULL);
|
|
|
|
RCTProfileEventID = 0;
|
|
|
|
RCTProfileInfo = nil;
|
|
|
|
RCTProfileOngoingEvents = nil;
|
|
|
|
);
|
2015-04-20 11:55:05 +00:00
|
|
|
return log;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSNumber *_RCTProfileBeginEvent(void)
|
|
|
|
{
|
|
|
|
CHECK(@0);
|
2015-04-22 14:03:55 +00:00
|
|
|
RCTProfileLock(
|
|
|
|
NSNumber *eventID = @(++RCTProfileEventID);
|
|
|
|
RCTProfileOngoingEvents[eventID] = RCTProfileTimestamp(CACurrentMediaTime());
|
|
|
|
);
|
2015-04-20 11:55:05 +00:00
|
|
|
return eventID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _RCTProfileEndEvent(NSNumber *eventID, NSString *name, NSString *categories, id args)
|
|
|
|
{
|
|
|
|
CHECK();
|
2015-04-22 14:03:55 +00:00
|
|
|
RCTProfileLock(
|
|
|
|
NSNumber *startTimestamp = RCTProfileOngoingEvents[eventID];
|
|
|
|
if (startTimestamp) {
|
|
|
|
NSNumber *endTimestamp = RCTProfileTimestamp(CACurrentMediaTime());
|
|
|
|
|
|
|
|
RCTProfileAddEvent(RCTProfileTraceEvents,
|
|
|
|
@"name": name,
|
|
|
|
@"cat": categories,
|
|
|
|
@"ph": @"X",
|
|
|
|
@"ts": startTimestamp,
|
|
|
|
@"dur": @(endTimestamp.doubleValue - startTimestamp.doubleValue),
|
|
|
|
@"args": args ?: @[],
|
|
|
|
);
|
|
|
|
[RCTProfileOngoingEvents removeObjectForKey:eventID];
|
|
|
|
}
|
2015-04-20 11:55:05 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RCTProfileImmediateEvent(NSString *name, NSTimeInterval timestamp, NSString *scope)
|
|
|
|
{
|
|
|
|
CHECK();
|
2015-04-22 14:03:55 +00:00
|
|
|
RCTProfileLock(
|
|
|
|
RCTProfileAddEvent(RCTProfileTraceEvents,
|
|
|
|
@"name": name,
|
|
|
|
@"ts": RCTProfileTimestamp(timestamp),
|
|
|
|
@"scope": scope,
|
|
|
|
@"ph": @"i",
|
|
|
|
@"args": RCTProfileGetMemoryUsage(),
|
|
|
|
);
|
2015-04-20 11:55:05 +00:00
|
|
|
);
|
|
|
|
}
|
2015-04-20 13:33:52 +00:00
|
|
|
|
2015-06-03 12:38:21 +00:00
|
|
|
NSNumber *_RCTProfileBeginFlowEvent(void)
|
|
|
|
{
|
|
|
|
static NSUInteger flowID = 0;
|
|
|
|
|
|
|
|
CHECK(@0);
|
|
|
|
RCTProfileAddEvent(RCTProfileTraceEvents,
|
|
|
|
@"name": @"flow",
|
|
|
|
@"id": @(++flowID),
|
|
|
|
@"cat": @"flow",
|
|
|
|
@"ph": @"s",
|
|
|
|
@"ts": RCTProfileTimestamp(CACurrentMediaTime()),
|
|
|
|
);
|
|
|
|
|
|
|
|
return @(flowID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _RCTProfileEndFlowEvent(NSNumber *flowID)
|
|
|
|
{
|
|
|
|
CHECK();
|
|
|
|
RCTProfileAddEvent(RCTProfileTraceEvents,
|
|
|
|
@"name": @"flow",
|
|
|
|
@"id": flowID,
|
|
|
|
@"cat": @"flow",
|
|
|
|
@"ph": @"f",
|
|
|
|
@"ts": RCTProfileTimestamp(CACurrentMediaTime()),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-04-20 13:33:52 +00:00
|
|
|
#endif
|