Last active
April 21, 2021 17:49
-
-
Save sav007/d5b703556ee96034503f1c923a612f4d to your computer and use it in GitHub Desktop.
Track native module queue perf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override fun onCreate() { | |
reactNativeHost.reactInstanceManager.addReactInstanceEventListener { | |
val nativeModulesMessageQueueThread = ReactContext::class.java.getDeclaredField("mNativeModulesMessageQueueThread") | |
.apply { isAccessible = true } | |
.get(it) as MessageQueueThreadImpl | |
val messageHandlerField = MessageQueueThreadImpl::class.java.getDeclaredField("mHandler") | |
.apply { isAccessible = true } | |
val prevMessageHandler = messageHandlerField.get(nativeModulesMessageQueueThread) as MessageQueueThreadHandler | |
val exceptionHandler = MessageQueueThreadHandler::class.java.getDeclaredField("mExceptionHandler") | |
.apply { isAccessible = true } | |
.get(prevMessageHandler) as QueueThreadExceptionHandler | |
val newMessageHandler = PerfMessageQueueThreadHandler( | |
looper = prevMessageHandler.looper, | |
exceptionHandler = exceptionHandler | |
) | |
messageHandlerField.set(nativeModulesMessageQueueThread, newMessageHandler) | |
SystraceMessage::class.java.getDeclaredField("NOOP_BUILDER") | |
.apply { isAccessible = true } | |
.set(null, SystraceMessenger(newMessageHandler)) | |
} | |
} | |
private fun startBugsnag() { | |
val bugsnagConfig = Configuration.load(this) | |
bugsnagConfig.enabledReleaseStages = setOf("release", "development", "snapshot") | |
bugsnagConfig.appVersion = AppContext(this).getBuildIdentifier() | |
bugsnagConfig.releaseStage = AppContext(this).getBuildFlavour() | |
Bugsnag.start(this, bugsnagConfig) | |
} | |
override fun startDistributionService() = Unit | |
protected open fun initializeFlipper( | |
context: Context, | |
reactInstanceManager: ReactInstanceManager | |
) = Unit | |
} | |
private class PerfMessageQueueThreadHandler( | |
looper: Looper, | |
exceptionHandler: QueueThreadExceptionHandler | |
) : MessageQueueThreadHandler(looper, exceptionHandler) { | |
var currentMessageStartTime = -1L | |
private var totalMessageCount = 0L | |
private var averageQueueTime = 0L | |
override fun dispatchMessage(msg: Message) { | |
val startTime = msg.obj as? Long | |
if (startTime != null) { | |
val elapsedTime = (System.currentTimeMillis() - startTime) | |
if (elapsedTime > 0) { | |
totalMessageCount++ | |
averageQueueTime += (elapsedTime - averageQueueTime) / totalMessageCount | |
if (totalMessageCount % 10 == 0L) { | |
// println("!!! Average native message queue time: $averageQueueTime") | |
totalMessageCount = 0 | |
averageQueueTime = 0 | |
} | |
} | |
currentMessageStartTime = startTime | |
} else { | |
currentMessageStartTime = -1L | |
} | |
super.dispatchMessage(msg) | |
} | |
override fun sendMessageAtTime(msg: Message, uptimeMillis: Long): Boolean { | |
return super.sendMessageAtTime(msg.apply { | |
this.obj = System.currentTimeMillis() | |
}, uptimeMillis) | |
} | |
} | |
private class SystraceMessenger(val perfMessageQueueThreadHandler: PerfMessageQueueThreadHandler) : SystraceMessage.Builder() { | |
override fun flush() { | |
} | |
override fun arg(key: String?, value: Any?): SystraceMessage.Builder = apply { | |
if (key == "method" && value != null) { | |
if (value.toString().startsWith("CheckoutSDKModule.") && perfMessageQueueThreadHandler.currentMessageStartTime != -1L) { | |
val waitTime = System.currentTimeMillis() - perfMessageQueueThreadHandler.currentMessageStartTime | |
perfMessageQueueThreadHandler.currentMessageStartTime = -1L | |
println("!!! $value: wait time in queue: $waitTime ms") | |
} else { | |
println("!!! other native call: " + value) | |
} | |
} | |
} | |
override fun arg(key: String?, value: Int): SystraceMessage.Builder = apply { | |
} | |
override fun arg(key: String?, value: Long): SystraceMessage.Builder = apply { | |
} | |
override fun arg(key: String?, value: Double): SystraceMessage.Builder = apply { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment