Skip to content

Commit

Permalink
Add additional Systrace support
Browse files Browse the repository at this point in the history
Summary:
Adding support for application to hook into further tracing methods

## Changelog

[General][Added] - Add additional Systrace support

Reviewed By: NickGerleman

Differential Revision: D38673212

fbshipit-source-id: 55a90a0cd57809bca5f01da7acddcf253e5852ba
  • Loading branch information
christophpurrer authored and facebook-github-bot committed Sep 14, 2022
1 parent 447be62 commit 9cb716f
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 26 deletions.
15 changes: 15 additions & 0 deletions React/CxxModule/RCTNativeModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ static MethodCallResult invokeInner(

void RCTNativeModule::invoke(unsigned int methodId, folly::dynamic &&params, int callId)
{
id<RCTBridgeMethod> method = m_moduleData.methods[methodId];
if (method) {
RCT_PROFILE_BEGIN_EVENT(
RCTProfileTagAlways,
@"[RCTNativeModule invoke]",
@{@"method" : [NSString stringWithUTF8String:method.JSMethodName]});
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
}

const char *moduleName = [m_moduleData.name UTF8String];
const char *methodName = m_moduleData.methods[methodId].JSMethodName;

Expand Down Expand Up @@ -173,6 +182,10 @@ static MethodCallResult invokeInner(
BridgeNativeModulePerfLogger::syncMethodCallArgConversionEnd(moduleName, methodName);
}

RCT_PROFILE_BEGIN_EVENT(
RCTProfileTagAlways,
@"[RCTNativeModule invokeInner]",
@{@"method" : [NSString stringWithUTF8String:method.JSMethodName]});
@try {
if (context == Sync) {
BridgeNativeModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName);
Expand Down Expand Up @@ -214,6 +227,8 @@ static MethodCallResult invokeInner(
#else
RCTFatalException(exception);
#endif
} @finally {
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
}

return folly::none;
Expand Down
20 changes: 20 additions & 0 deletions React/Profiler/RCTProfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ RCT_EXTERN void RCTProfileInit(RCTBridge *);
*/
RCT_EXTERN void RCTProfileEnd(RCTBridge *, void (^)(NSString *));

/**
* Route the RCT_PROFILE_BEGIN_EVENT hooks to our loom tracing.
*/
#ifdef WITH_LOOM_TRACE
RCT_EXTERN BOOL _RCTLoomIsProfiling(void);
RCT_EXTERN void
_RCTLoomBeginEvent(NSString *name, const char *file, size_t line, NSDictionary<NSString *, NSString *> *args);
RCT_EXTERN void _RCTLoomEndEvent();
#else
#define _RCTLoomIsProfiling(...) NO
#define _RCTLoomBeginEvent(...)
#define _RCTLoomEndEvent(...)
#endif

/**
* Collects the initial event information for the event and returns a reference ID
*/
Expand All @@ -68,6 +82,9 @@ RCT_EXTERN void _RCTProfileBeginEvent(
NSDictionary<NSString *, NSString *> *args);
#define RCT_PROFILE_BEGIN_EVENT(tag, name, args) \
do { \
if (_RCTLoomIsProfiling()) { \
_RCTLoomBeginEvent(name, __FILE__, __LINE__, args); \
} \
if (RCTProfileIsProfiling()) { \
NSThread *__calleeThread = [NSThread currentThread]; \
NSTimeInterval __time = CACurrentMediaTime(); \
Expand All @@ -89,6 +106,9 @@ RCT_EXTERN void _RCTProfileEndEvent(

#define RCT_PROFILE_END_EVENT(tag, category) \
do { \
if (_RCTLoomIsProfiling()) { \
_RCTLoomEndEvent(); \
} \
if (RCTProfileIsProfiling()) { \
NSThread *__calleeThread = [NSThread currentThread]; \
NSString *__threadName = RCTCurrentThreadName(); \
Expand Down
58 changes: 33 additions & 25 deletions ReactCommon/cxxreact/CxxNativeModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,34 +185,42 @@ void CxxNativeModule::invoke(
// stack. I'm told that will be possible in the future. TODO
// mhorowitz #7128529: convert C++ exceptions to Java

messageQueueThread_->runOnQueue(
[method, params = std::move(params), first, second, callId]() {
const auto &moduleName = name_;
SystraceSection s(
"CxxMethodCallQueue", "module", moduleName, "method", method.name);
messageQueueThread_->runOnQueue([method,
moduleName,
params = std::move(params),
first,
second,
callId]() {
#ifdef WITH_FBSYSTRACE
if (callId != -1) {
fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId);
}
if (callId != -1) {
fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId);
}
#else
(void)(callId);
(void)(callId);
#endif
SystraceSection s(method.name.c_str());
try {
method.func(std::move(params), first, second);
} catch (const facebook::xplat::JsArgumentException &ex) {
throw;
} catch (std::exception &e) {
LOG(ERROR) << "std::exception. Method call " << method.name.c_str()
<< " failed: " << e.what();
std::terminate();
} catch (std::string &error) {
LOG(ERROR) << "std::string. Method call " << method.name.c_str()
<< " failed: " << error.c_str();
std::terminate();
} catch (...) {
LOG(ERROR) << "Method call " << method.name.c_str()
<< " failed. unknown error";
std::terminate();
}
});
SystraceSection s(
"CxxMethodCallDispatch", "module", moduleName, "method", method.name);
try {
method.func(std::move(params), first, second);
} catch (const facebook::xplat::JsArgumentException &ex) {
throw;
} catch (std::exception &e) {
LOG(ERROR) << "std::exception. Method call " << method.name.c_str()
<< " failed: " << e.what();
std::terminate();
} catch (std::string &error) {
LOG(ERROR) << "std::string. Method call " << method.name.c_str()
<< " failed: " << error.c_str();
std::terminate();
} catch (...) {
LOG(ERROR) << "Method call " << method.name.c_str()
<< " failed. unknown error";
std::terminate();
}
});
}

MethodCallResult CxxNativeModule::callSerializableNativeHook(
Expand Down
12 changes: 11 additions & 1 deletion ReactCommon/cxxreact/SystraceSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@
namespace facebook {
namespace react {

/**
* Allow providing an fbsystrace implementation that can short-circuit out
* quickly and can throttle too frequent events so we can get useful traces even
* if rendering etc. is spinning. For throttling we'll need file/line info so we
* use a macro.
*/
#if defined(WITH_LOOM_TRACE)
#define SystraceSection \
static constexpr const char systraceSectionFile[] = __FILE__; \
fbsystrace::FbSystraceSection<systraceSectionFile, __LINE__>
/**
* This is a convenience class to avoid lots of verbose profiling
* #ifdefs. If WITH_FBSYSTRACE is not defined, the optimizer will
Expand All @@ -23,7 +33,7 @@ namespace react {
* different values in different files, there is no inconsistency in the sizes
* of defined symbols.
*/
#ifdef WITH_FBSYSTRACE
#elif defined(WITH_FBSYSTRACE)
struct ConcreteSystraceSection {
public:
template <typename... ConvertsToStringPiece>
Expand Down

0 comments on commit 9cb716f

Please sign in to comment.