mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-09 22:43:10 +08:00
#15 Add a button in devtools to start/stop the Sampling Profiler
Differential Revision: D3555704 fbshipit-source-id: 4add16c923fcfd306892efec4630c24ae438d6dd
This commit is contained in:
committed by
Facebook Github Bot 8
parent
e762d961cd
commit
ec0ccf599a
@@ -18,6 +18,7 @@ import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.devsupport.JSCHeapCapture;
|
||||
import com.facebook.react.devsupport.JSCSamplingProfiler;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.modules.core.ExceptionsManagerModule;
|
||||
@@ -84,6 +85,7 @@ import com.facebook.systrace.Systrace;
|
||||
new Timing(catalystApplicationContext, mReactInstanceManager.getDevSupportManager()),
|
||||
new SourceCodeModule(mReactInstanceManager.getSourceUrl()),
|
||||
uiManagerModule,
|
||||
new JSCSamplingProfiler(catalystApplicationContext),
|
||||
new DebugComponentOwnershipModule(catalystApplicationContext)));
|
||||
|
||||
if (ReactBuildConfig.DEBUG) {
|
||||
@@ -103,6 +105,7 @@ import com.facebook.systrace.Systrace;
|
||||
AppRegistry.class,
|
||||
com.facebook.react.bridge.Systrace.class,
|
||||
HMRClient.class,
|
||||
JSCSamplingProfiler.SamplingProfiler.class,
|
||||
DebugComponentOwnershipModule.RCTDebugComponentOwnership.class));
|
||||
|
||||
if (ReactBuildConfig.DEBUG) {
|
||||
|
||||
@@ -375,6 +375,26 @@ public class DevSupportManagerImpl implements DevSupportManager {
|
||||
JSCHeapUpload.captureCallback(mDevServerHelper.getHeapCaptureUploadUrl()));
|
||||
}
|
||||
});
|
||||
options.put(
|
||||
mApplicationContext.getString(R.string.catalyst_poke_sampling_profiler),
|
||||
new DevOptionHandler() {
|
||||
@Override
|
||||
public void onOptionSelected() {
|
||||
try {
|
||||
List<String> pokeResults = JSCSamplingProfiler.poke(60000);
|
||||
for (String result : pokeResults) {
|
||||
Toast.makeText(
|
||||
mCurrentContext,
|
||||
result == null
|
||||
? "Started JSC Sampling Profiler"
|
||||
: "Stopped JSC Sampling Profiler",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} catch (JSCSamplingProfiler.ProfilerException e) {
|
||||
showNewJavaError(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
options.put(
|
||||
mApplicationContext.getString(R.string.catalyst_settings), new DevOptionHandler() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.devsupport;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
|
||||
public class JSCSamplingProfiler extends ReactContextBaseJavaModule {
|
||||
public interface SamplingProfiler extends JavaScriptModule {
|
||||
void poke(int token);
|
||||
}
|
||||
|
||||
public static class ProfilerException extends Exception {
|
||||
ProfilerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable SamplingProfiler mSamplingProfiler;
|
||||
private boolean mOperationInProgress;
|
||||
private int mOperationToken;
|
||||
private @Nullable String mOperationError;
|
||||
private @Nullable String mSamplingProfilerResult;
|
||||
|
||||
private static final HashSet<JSCSamplingProfiler> sRegisteredDumpers =
|
||||
new HashSet<>();
|
||||
|
||||
private static synchronized void registerSamplingProfiler(
|
||||
JSCSamplingProfiler dumper) {
|
||||
if (sRegisteredDumpers.contains(dumper)) {
|
||||
throw new RuntimeException(
|
||||
"a JSCSamplingProfiler registered more than once");
|
||||
}
|
||||
sRegisteredDumpers.add(dumper);
|
||||
}
|
||||
|
||||
private static synchronized void unregisterSamplingProfiler(
|
||||
JSCSamplingProfiler dumper) {
|
||||
sRegisteredDumpers.remove(dumper);
|
||||
}
|
||||
|
||||
public static synchronized List<String> poke(long timeout)
|
||||
throws ProfilerException {
|
||||
LinkedList<String> results = new LinkedList<>();
|
||||
if (sRegisteredDumpers.isEmpty()) {
|
||||
throw new ProfilerException("No JSC registered");
|
||||
}
|
||||
|
||||
for (JSCSamplingProfiler dumper : sRegisteredDumpers) {
|
||||
dumper.pokeHelper(timeout);
|
||||
results.add(dumper.mSamplingProfilerResult);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public JSCSamplingProfiler(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
mSamplingProfiler = null;
|
||||
mOperationInProgress = false;
|
||||
mOperationToken = 0;
|
||||
mOperationError = null;
|
||||
mSamplingProfilerResult = null;
|
||||
}
|
||||
|
||||
private synchronized void pokeHelper(long timeout) throws ProfilerException {
|
||||
if (mSamplingProfiler == null) {
|
||||
throw new ProfilerException("SamplingProfiler.js module not connected");
|
||||
}
|
||||
mSamplingProfiler.poke(getOperationToken());
|
||||
waitForOperation(timeout);
|
||||
}
|
||||
|
||||
private int getOperationToken() throws ProfilerException {
|
||||
if (mOperationInProgress) {
|
||||
throw new ProfilerException("Another operation already in progress.");
|
||||
}
|
||||
mOperationInProgress = true;
|
||||
return ++mOperationToken;
|
||||
}
|
||||
|
||||
private void waitForOperation(long timeout) throws ProfilerException {
|
||||
try {
|
||||
wait(timeout);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ProfilerException(
|
||||
"Waiting for heap capture failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (mOperationInProgress) {
|
||||
mOperationInProgress = false;
|
||||
throw new ProfilerException("heap capture timed out.");
|
||||
}
|
||||
|
||||
if (mOperationError != null) {
|
||||
throw new ProfilerException(mOperationError);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public synchronized void operationComplete(
|
||||
int token, String result, String error) {
|
||||
if (token == mOperationToken) {
|
||||
mOperationInProgress = false;
|
||||
mSamplingProfilerResult = result;
|
||||
mOperationError = error;
|
||||
this.notify();
|
||||
} else {
|
||||
throw new RuntimeException("Completed operation is not in progress.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "JSCSamplingProfiler";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
mSamplingProfiler =
|
||||
getReactApplicationContext().getJSModule(SamplingProfiler.class);
|
||||
registerSamplingProfiler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {
|
||||
super.onCatalystInstanceDestroy();
|
||||
unregisterSamplingProfiler(this);
|
||||
mSamplingProfiler = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user