Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal class PerfMonitorOverlayManager(

private var view: PerfMonitorOverlayView? = null
private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
private var perfIssueCount: Int = 0

/** Enable the Perf Monitor overlay. */
fun enable() {
Expand Down Expand Up @@ -72,8 +73,19 @@ internal class PerfMonitorOverlayManager(

override fun onRecordingStateChanged(state: TracingState) {
tracingState = state
if (state != TracingState.DISABLED) {
perfIssueCount = 0
}
UiThreadUtil.runOnUiThread {
view?.updateRecordingState(state)
view?.updatePerfIssueCount(perfIssueCount)
view?.show()
}
}

override fun onPerfIssueAdded(name: String) {
UiThreadUtil.runOnUiThread {
view?.updatePerfIssueCount(++perfIssueCount)
view?.show()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ internal class PerfMonitorOverlayView(
private val onButtonPress: () -> Unit,
) {
private val dialog: Dialog
private lateinit var statusIndicator: TextView
private lateinit var statusLabel: TextView
private lateinit var tooltipLabel: TextView
private lateinit var statusIndicator: TextView
private lateinit var issuesContainer: LinearLayout
private lateinit var issueCountLabel: TextView

init {
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
Expand Down Expand Up @@ -70,6 +72,11 @@ internal class PerfMonitorOverlayView(
dialog.show()
}

fun updatePerfIssueCount(count: Int) {
issueCountLabel.text = count.toString()
issuesContainer.visibility = if (count == 0) LinearLayout.GONE else LinearLayout.VISIBLE
}

private fun createToolbarDialog(): Dialog {
statusIndicator =
TextView(context).apply {
Expand All @@ -85,11 +92,7 @@ internal class PerfMonitorOverlayView(
val textContainer =
LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL
layoutParams =
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
)
setPadding(dpToPx(2f).toInt(), 0, 0, 0)
}
statusLabel =
TextView(context).apply {
Expand All @@ -106,10 +109,35 @@ internal class PerfMonitorOverlayView(
textContainer.addView(statusLabel)
textContainer.addView(tooltipLabel)

issuesContainer =
LinearLayout(context).apply {
setPadding(dpToPx(8f).toInt(), 0, 0, 0)
visibility = LinearLayout.GONE
}
issueCountLabel =
TextView(context).apply {
textSize = TEXT_SIZE_PRIMARY
setTextColor(Color.WHITE)
typeface = TYPEFACE_BOLD
val alertDrawable =
context.getDrawable(android.R.drawable.ic_dialog_alert)?.apply {
setBounds(
0,
1,
dpToPx(TEXT_SIZE_PRIMARY).toInt(),
dpToPx(TEXT_SIZE_PRIMARY).toInt() + 1,
)
}
setCompoundDrawables(alertDrawable, null, null, null)
compoundDrawablePadding = dpToPx(6f).toInt()
}
issuesContainer.addView(issueCountLabel)

val containerLayout = createInnerLayout()
containerLayout.setOnClickListener { onButtonPress() }
containerLayout.addView(statusIndicator)
containerLayout.addView(textContainer)
containerLayout.addView(issuesContainer)

val dialog =
createAnchoredDialog(dpToPx(12f), dpToPx(12f)).apply { setContentView(containerLayout) }
Expand Down Expand Up @@ -175,7 +203,7 @@ internal class PerfMonitorOverlayView(
showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
dividerDrawable =
object : ColorDrawable(Color.TRANSPARENT) {
override fun getIntrinsicWidth(): Int = dpToPx(8f).toInt()
override fun getIntrinsicWidth(): Int = dpToPx(10f).toInt()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.devsupport.perfmonitor

import com.facebook.react.devsupport.interfaces.TracingState
Expand All @@ -12,4 +13,7 @@ import com.facebook.react.devsupport.interfaces.TracingState
internal interface PerfMonitorUpdateListener {
/** Called when the recording state of the background performance trace has changed. */
fun onRecordingStateChanged(state: TracingState)

/** Called when a new Performance Issue is added. */
fun onPerfIssueAdded(name: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3ea1ee77358d99334a7c40bed44f2d90>>
* @generated SignedSource<<bac9e360daa589cba476d208f75ef2ca>>
*/

/**
Expand Down Expand Up @@ -372,6 +372,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = accessor.overrideBySynchronousMountPropsAtMountingAndroid()

/**
* Enable reporting Performance Issues (`detail.rnPerfIssue`). Displayed in the V2 Performance Monitor and the "Performance Issues" sub-panel in DevTools.
*/
@JvmStatic
public fun perfIssuesEnabled(): Boolean = accessor.perfIssuesEnabled()

/**
* Enable the V2 in-app Performance Monitor. This flag is global and should not be changed across React Host lifetimes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<007a5a1235a999716b382ffd4ca23158>>
* @generated SignedSource<<2003ae7fc2c782b997d21938cc7b2380>>
*/

/**
Expand Down Expand Up @@ -77,6 +77,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
private var perfIssuesEnabledCache: Boolean? = null
private var perfMonitorV2EnabledCache: Boolean? = null
private var preparedTextCacheSizeCache: Double? = null
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
Expand Down Expand Up @@ -615,6 +616,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun perfIssuesEnabled(): Boolean {
var cached = perfIssuesEnabledCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.perfIssuesEnabled()
perfIssuesEnabledCache = cached
}
return cached
}

override fun perfMonitorV2Enabled(): Boolean {
var cached = perfMonitorV2EnabledCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<8a775646d455cdb6d017fd08aee3e807>>
* @generated SignedSource<<986b35ba4f323ab1a65dd70a559889e9>>
*/

/**
Expand Down Expand Up @@ -142,6 +142,8 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean

@DoNotStrip @JvmStatic public external fun perfIssuesEnabled(): Boolean

@DoNotStrip @JvmStatic public external fun perfMonitorV2Enabled(): Boolean

@DoNotStrip @JvmStatic public external fun preparedTextCacheSize(): Double
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<afccaed3066598724041c48bfb524234>>
* @generated SignedSource<<43f629e3be734826b241d7e596daf6f4>>
*/

/**
Expand Down Expand Up @@ -137,6 +137,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = false

override fun perfIssuesEnabled(): Boolean = false

override fun perfMonitorV2Enabled(): Boolean = false

override fun preparedTextCacheSize(): Double = 200.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ebeb9b37b8d3d0e31f4d4966cbf42b3f>>
* @generated SignedSource<<806741418f4ff7e3b6dcac3d78fa27dd>>
*/

/**
Expand Down Expand Up @@ -81,6 +81,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
private var perfIssuesEnabledCache: Boolean? = null
private var perfMonitorV2EnabledCache: Boolean? = null
private var preparedTextCacheSizeCache: Double? = null
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
Expand Down Expand Up @@ -676,6 +677,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}

override fun perfIssuesEnabled(): Boolean {
var cached = perfIssuesEnabledCache
if (cached == null) {
cached = currentProvider.perfIssuesEnabled()
accessedFeatureFlags.add("perfIssuesEnabled")
perfIssuesEnabledCache = cached
}
return cached
}

override fun perfMonitorV2Enabled(): Boolean {
var cached = perfMonitorV2EnabledCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<1c4ea60d119996f37742542976fedcc8>>
* @generated SignedSource<<1a08578b36cb91a183a435b881ca272f>>
*/

/**
Expand Down Expand Up @@ -137,6 +137,8 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean

@DoNotStrip public fun perfIssuesEnabled(): Boolean

@DoNotStrip public fun perfMonitorV2Enabled(): Boolean

@DoNotStrip public fun preparedTextCacheSize(): Double
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
}
}

fun handleNativePerfIssueAdded(
name: String,
) {
perfMonitorListeners.forEach { listener -> listener.onPerfIssueAdded(name) }
}

override fun close() {
mHybridData.resetNative()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d04720bbbd42eaf338be612a0f3e36a6>>
* @generated SignedSource<<4c22217e5a773fd97f4041ef6e052ebc>>
*/

/**
Expand Down Expand Up @@ -381,6 +381,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}

bool perfIssuesEnabled() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("perfIssuesEnabled");
return method(javaProvider_);
}

bool perfMonitorV2Enabled() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("perfMonitorV2Enabled");
Expand Down Expand Up @@ -814,6 +820,11 @@ bool JReactNativeFeatureFlagsCxxInterop::overrideBySynchronousMountPropsAtMounti
return ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid();
}

bool JReactNativeFeatureFlagsCxxInterop::perfIssuesEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::perfIssuesEnabled();
}

bool JReactNativeFeatureFlagsCxxInterop::perfMonitorV2Enabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::perfMonitorV2Enabled();
Expand Down Expand Up @@ -1136,6 +1147,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"overrideBySynchronousMountPropsAtMountingAndroid",
JReactNativeFeatureFlagsCxxInterop::overrideBySynchronousMountPropsAtMountingAndroid),
makeNativeMethod(
"perfIssuesEnabled",
JReactNativeFeatureFlagsCxxInterop::perfIssuesEnabled),
makeNativeMethod(
"perfMonitorV2Enabled",
JReactNativeFeatureFlagsCxxInterop::perfMonitorV2Enabled),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<7679a91daba1f8941b78a4be4baea6ef>>
* @generated SignedSource<<91f5bbbab5f34321687c6f6d31ca49d8>>
*/

/**
Expand Down Expand Up @@ -201,6 +201,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool overrideBySynchronousMountPropsAtMountingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool perfIssuesEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool perfMonitorV2Enabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ void JReactHostInspectorTarget::onSetPausedInDebuggerMessage(
}
}

void JReactHostInspectorTarget::unstable_onPerfIssueAdded(
const PerfIssuePayload& issue) {
static auto method = javaClassStatic()->getMethod<void(local_ref<jstring>)>(
"handleNativePerfIssueAdded");
method(jobj_, make_jstring(issue.name));
}

void JReactHostInspectorTarget::loadNetworkResource(
const jsinspector_modern::LoadNetworkResourceRequest& params,
jsinspector_modern::ScopedExecutor<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
jsinspector_modern::HostTargetMetadata getMetadata() override;
void onReload(const PageReloadRequest &request) override;
void onSetPausedInDebuggerMessage(const OverlaySetPausedInDebuggerMessageRequest &request) override;
void unstable_onPerfIssueAdded(const jsinspector_modern::PerfIssuePayload &issue) override;
void loadNetworkResource(
const jsinspector_modern::LoadNetworkResourceRequest &params,
jsinspector_modern::ScopedExecutor<jsinspector_modern::NetworkRequestListener> executor) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ std::shared_ptr<HostTarget> HostTarget::create(
VoidExecutor executor) {
std::shared_ptr<HostTarget> hostTarget{new HostTarget(delegate)};
hostTarget->setExecutor(std::move(executor));
if (InspectorFlags::getInstance().getPerfIssuesEnabled()) {
hostTarget->installPerfIssuesBinding();
}
return hostTarget;
}

Expand Down Expand Up @@ -289,6 +292,17 @@ void HostTarget::sendCommand(HostCommand command) {
});
}

void HostTarget::installPerfIssuesBinding() {
perfMonitorUpdateHandler_ =
std::make_unique<PerfMonitorUpdateHandler>(delegate_);
perfMetricsBinding_ = std::make_unique<HostRuntimeBinding>(
*this, // Used immediately
"__react_native_perf_issues_reporter",
[this](const std::string& message) {
perfMonitorUpdateHandler_->handlePerfIssueAdded(message);
});
}

HostTargetController::HostTargetController(HostTarget& target)
: target_(target) {}

Expand Down
Loading
Loading