Add additional Systrace support

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
This commit is contained in:
Christoph Purrer
2022-09-14 16:29:20 -07:00
committed by Facebook GitHub Bot
parent 447be62909
commit 9cb716ff76
4 changed files with 79 additions and 26 deletions
+15
View File
@@ -73,6 +73,15 @@ folly::dynamic RCTNativeModule::getConstants()
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;
@@ -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);
@@ -214,6 +227,8 @@ static MethodCallResult invokeInner(
#else
RCTFatalException(exception);
#endif
} @finally {
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
}
return folly::none;
+20
View File
@@ -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
*/
@@ -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(); \
@@ -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(); \
+33 -25
View File
@@ -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(
+11 -1
View File
@@ -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
@@ -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>