RCTProfile.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import <Foundation/Foundation.h>
  8. #import <React/RCTAssert.h>
  9. #import <React/RCTDefines.h>
  10. /**
  11. * RCTProfile
  12. *
  13. * This file provides a set of functions and macros for performance profiling
  14. *
  15. * NOTE: This API is a work in progress, please consider carefully before
  16. * using it.
  17. */
  18. RCT_EXTERN NSString *const RCTProfileDidStartProfiling;
  19. RCT_EXTERN NSString *const RCTProfileDidEndProfiling;
  20. RCT_EXTERN const uint64_t RCTProfileTagAlways;
  21. #if RCT_PROFILE
  22. @class RCTBridge;
  23. #define RCTProfileBeginFlowEvent() \
  24. _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") NSUInteger __rct_profile_flow_id = \
  25. _RCTProfileBeginFlowEvent(); \
  26. _Pragma("clang diagnostic pop")
  27. #define RCTProfileEndFlowEvent() _RCTProfileEndFlowEvent(__rct_profile_flow_id)
  28. RCT_EXTERN dispatch_queue_t RCTProfileGetQueue(void);
  29. RCT_EXTERN NSUInteger _RCTProfileBeginFlowEvent(void);
  30. RCT_EXTERN void _RCTProfileEndFlowEvent(NSUInteger);
  31. /**
  32. * Returns YES if the profiling information is currently being collected
  33. */
  34. RCT_EXTERN BOOL RCTProfileIsProfiling(void);
  35. /**
  36. * Start collecting profiling information
  37. */
  38. RCT_EXTERN void RCTProfileInit(RCTBridge *);
  39. /**
  40. * Stop profiling and return a JSON string of the collected data - The data
  41. * returned is compliant with google's trace event format - the format used
  42. * as input to trace-viewer
  43. */
  44. RCT_EXTERN void RCTProfileEnd(RCTBridge *, void (^)(NSString *));
  45. /**
  46. * Collects the initial event information for the event and returns a reference ID
  47. */
  48. RCT_EXTERN void _RCTProfileBeginEvent(
  49. NSThread *calleeThread,
  50. NSTimeInterval time,
  51. uint64_t tag,
  52. NSString *name,
  53. NSDictionary<NSString *, NSString *> *args);
  54. #define RCT_PROFILE_BEGIN_EVENT(tag, name, args) \
  55. do { \
  56. if (RCTProfileIsProfiling()) { \
  57. NSThread *__calleeThread = [NSThread currentThread]; \
  58. NSTimeInterval __time = CACurrentMediaTime(); \
  59. _RCTProfileBeginEvent(__calleeThread, __time, tag, name, args); \
  60. } \
  61. } while (0)
  62. /**
  63. * The ID returned by BeginEvent should then be passed into EndEvent, with the
  64. * rest of the event information. Just at this point the event will actually be
  65. * registered
  66. */
  67. RCT_EXTERN void _RCTProfileEndEvent(
  68. NSThread *calleeThread,
  69. NSString *threadName,
  70. NSTimeInterval time,
  71. uint64_t tag,
  72. NSString *category);
  73. #define RCT_PROFILE_END_EVENT(tag, category) \
  74. do { \
  75. if (RCTProfileIsProfiling()) { \
  76. NSThread *__calleeThread = [NSThread currentThread]; \
  77. NSString *__threadName = RCTCurrentThreadName(); \
  78. NSTimeInterval __time = CACurrentMediaTime(); \
  79. _RCTProfileEndEvent(__calleeThread, __threadName, __time, tag, category); \
  80. } \
  81. } while (0)
  82. /**
  83. * Collects the initial event information for the event and returns a reference ID
  84. */
  85. RCT_EXTERN NSUInteger
  86. RCTProfileBeginAsyncEvent(uint64_t tag, NSString *name, NSDictionary<NSString *, NSString *> *args);
  87. /**
  88. * The ID returned by BeginEvent should then be passed into EndEvent, with the
  89. * rest of the event information. Just at this point the event will actually be
  90. * registered
  91. */
  92. RCT_EXTERN void
  93. RCTProfileEndAsyncEvent(uint64_t tag, NSString *category, NSUInteger cookie, NSString *name, NSString *threadName);
  94. /**
  95. * An event that doesn't have a duration (i.e. Notification, VSync, etc)
  96. */
  97. RCT_EXTERN void RCTProfileImmediateEvent(uint64_t tag, NSString *name, NSTimeInterval time, char scope);
  98. /**
  99. * Helper to profile the duration of the execution of a block. This method uses
  100. * self and _cmd to name this event for simplicity sake.
  101. *
  102. * NOTE: The block can't expect any argument
  103. *
  104. * DEPRECATED: this approach breaks debugging and stepping through instrumented block functions
  105. */
  106. #define RCTProfileBlock(block, tag, category, arguments) \
  107. ^{ \
  108. RCT_PROFILE_BEGIN_EVENT(tag, @(__PRETTY_FUNCTION__), nil); \
  109. block(); \
  110. RCT_PROFILE_END_EVENT(tag, category, arguments); \
  111. }
  112. /**
  113. * Hook into a bridge instance to log all bridge module's method calls
  114. */
  115. RCT_EXTERN void RCTProfileHookModules(RCTBridge *);
  116. /**
  117. * Unhook from a given bridge instance's modules
  118. */
  119. RCT_EXTERN void RCTProfileUnhookModules(RCTBridge *);
  120. /**
  121. * Hook into all of a module's methods
  122. */
  123. RCT_EXTERN void RCTProfileHookInstance(id instance);
  124. /**
  125. * Send systrace or cpu profiling information to the packager
  126. * to present to the user
  127. */
  128. RCT_EXTERN void RCTProfileSendResult(RCTBridge *bridge, NSString *route, NSData *profileData);
  129. /**
  130. * Systrace gluecode
  131. *
  132. * allow to use systrace to back RCTProfile
  133. */
  134. typedef struct {
  135. const char *key;
  136. unsigned long key_len;
  137. const char *value;
  138. unsigned long value_len;
  139. } systrace_arg_t;
  140. typedef struct {
  141. char *(*start)(void);
  142. void (*stop)(void);
  143. void (*begin_section)(uint64_t tag, const char *name, size_t numArgs, systrace_arg_t *args);
  144. void (*end_section)(uint64_t tag, size_t numArgs, systrace_arg_t *args);
  145. void (*begin_async_section)(uint64_t tag, const char *name, int cookie, size_t numArgs, systrace_arg_t *args);
  146. void (*end_async_section)(uint64_t tag, const char *name, int cookie, size_t numArgs, systrace_arg_t *args);
  147. void (*instant_section)(uint64_t tag, const char *name, char scope);
  148. void (*begin_async_flow)(uint64_t tag, const char *name, int cookie);
  149. void (*end_async_flow)(uint64_t tag, const char *name, int cookie);
  150. } RCTProfileCallbacks;
  151. RCT_EXTERN void RCTProfileRegisterCallbacks(RCTProfileCallbacks *);
  152. /**
  153. * Systrace control window
  154. */
  155. RCT_EXTERN void RCTProfileShowControls(void);
  156. RCT_EXTERN void RCTProfileHideControls(void);
  157. #else
  158. #define RCTProfileBeginFlowEvent()
  159. #define _RCTProfileBeginFlowEvent() @0
  160. #define RCTProfileEndFlowEvent()
  161. #define _RCTProfileEndFlowEvent(...)
  162. #define RCTProfileIsProfiling(...) NO
  163. #define RCTProfileInit(...)
  164. #define RCTProfileEnd(...) @""
  165. #define _RCTProfileBeginEvent(...)
  166. #define _RCTProfileEndEvent(...)
  167. #define RCT_PROFILE_BEGIN_EVENT(...)
  168. #define RCT_PROFILE_END_EVENT(...)
  169. #define RCTProfileBeginAsyncEvent(...) 0
  170. #define RCTProfileEndAsyncEvent(...)
  171. #define RCTProfileImmediateEvent(...)
  172. #define RCTProfileBlock(block, ...) block
  173. #define RCTProfileHookModules(...)
  174. #define RCTProfileHookInstance(...)
  175. #define RCTProfileUnhookModules(...)
  176. #define RCTProfileSendResult(...)
  177. #define RCTProfileShowControls(...)
  178. #define RCTProfileHideControls(...)
  179. #endif