Capture heap from the dev menu
Reviewed By: foghina Differential Revision: D3229856 fb-gh-sync-id: c6321cfb309c93572a51bba625d63246a75f0254 fbshipit-source-id: c6321cfb309c93572a51bba625d63246a75f0254
This commit is contained in:
parent
84e696867b
commit
24b2990467
|
@ -24,6 +24,7 @@ const JSTimersExecution = require('JSTimersExecution');
|
|||
|
||||
BatchedBridge.registerCallableModule('Systrace', Systrace);
|
||||
BatchedBridge.registerCallableModule('JSTimersExecution', JSTimersExecution);
|
||||
BatchedBridge.registerCallableModule('HeapCapture', require('HeapCapture'));
|
||||
|
||||
if (__DEV__) {
|
||||
BatchedBridge.registerCallableModule('HMRClient', require('HMRClient'));
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule HeapCapture
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var HeapCapture = {
|
||||
captureHeap: function (token: number, path: string) {
|
||||
var error = null;
|
||||
try {
|
||||
global.nativeCaptureHeap(path);
|
||||
console.log('HeapCapture.captureHeap succeeded: ' + path);
|
||||
} catch (e) {
|
||||
console.log('HeapCapture.captureHeap error: ' + e.toString());
|
||||
error = e.toString();
|
||||
}
|
||||
require('NativeModules').JSCHeapCapture.operationComplete(token, error);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = HeapCapture;
|
|
@ -16,6 +16,7 @@ import java.util.List;
|
|||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.devsupport.JSCHeapCapture;
|
||||
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;
|
|||
mReactInstanceManager.getSourceUrl(),
|
||||
mReactInstanceManager.getDevSupportManager().getSourceMapUrl()),
|
||||
uiManagerModule,
|
||||
new JSCHeapCapture(catalystApplicationContext),
|
||||
new DebugComponentOwnershipModule(catalystApplicationContext));
|
||||
}
|
||||
|
||||
|
@ -97,6 +99,7 @@ import com.facebook.systrace.Systrace;
|
|||
AppRegistry.class,
|
||||
com.facebook.react.bridge.Systrace.class,
|
||||
HMRClient.class,
|
||||
JSCHeapCapture.HeapCapture.class,
|
||||
DebugComponentOwnershipModule.RCTDebugComponentOwnership.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -304,6 +304,23 @@ public class DevSupportManagerImpl implements DevSupportManager {
|
|||
mReactInstanceCommandsHandler.toggleElementInspector();
|
||||
}
|
||||
});
|
||||
options.put(
|
||||
mApplicationContext.getString(R.string.catalyst_heap_capture),
|
||||
new DevOptionHandler() {
|
||||
@Override
|
||||
public void onOptionSelected() {
|
||||
try {
|
||||
String heapDumpPath = mApplicationContext.getCacheDir() + "/heapdump.json";
|
||||
JSCHeapCapture.captureHeap(heapDumpPath, 60000);
|
||||
Toast.makeText(
|
||||
mCurrentContext,
|
||||
"Heap captured to " + heapDumpPath,
|
||||
Toast.LENGTH_LONG).show();
|
||||
} catch (JSCHeapCapture.CaptureException e) {
|
||||
showNewJavaError(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
options.put(
|
||||
mDevSettings.isFpsDebugEnabled()
|
||||
? mApplicationContext.getString(R.string.catalyst_perf_monitor_off)
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* 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 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 JSCHeapCapture extends ReactContextBaseJavaModule {
|
||||
public interface HeapCapture extends JavaScriptModule {
|
||||
void captureHeap(int token, String path);
|
||||
void setAllocationTracking(int token, boolean enabled);
|
||||
}
|
||||
|
||||
public static class CaptureException extends Exception {
|
||||
CaptureException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable HeapCapture mHeapCapture;
|
||||
private boolean mOperationInProgress;
|
||||
private int mOperationToken;
|
||||
private @Nullable String mOperationError;
|
||||
|
||||
private static @Nullable JSCHeapCapture sJSCHeapCapture = null;
|
||||
|
||||
private static synchronized void registerHeapCapture(JSCHeapCapture dumper) {
|
||||
if (sJSCHeapCapture != null) {
|
||||
throw new RuntimeException(
|
||||
"JSCHeapCapture already registered. Are you running more than one JSC?");
|
||||
}
|
||||
sJSCHeapCapture = dumper;
|
||||
}
|
||||
|
||||
private static synchronized void unregisterHeapCapture(JSCHeapCapture dumper) {
|
||||
if (sJSCHeapCapture != dumper) {
|
||||
throw new RuntimeException("Can't unregister JSCHeapCapture that is not registered.");
|
||||
}
|
||||
sJSCHeapCapture = null;
|
||||
}
|
||||
|
||||
public static synchronized void captureHeap(String path, long timeout) throws CaptureException {
|
||||
if (sJSCHeapCapture == null) {
|
||||
throw new CaptureException("No JSC registered.");
|
||||
}
|
||||
sJSCHeapCapture.captureHeapHelper(path, timeout);
|
||||
}
|
||||
|
||||
public JSCHeapCapture(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
mHeapCapture = null;
|
||||
mOperationInProgress = false;
|
||||
mOperationToken = 0;
|
||||
mOperationError = null;
|
||||
}
|
||||
|
||||
private synchronized void captureHeapHelper(String path, long timeout) throws CaptureException {
|
||||
if (mHeapCapture == null) {
|
||||
throw new CaptureException("HeapCapture.js module not connected");
|
||||
}
|
||||
mHeapCapture.captureHeap(getOperationToken(), path);
|
||||
waitForOperation(timeout);
|
||||
}
|
||||
|
||||
private int getOperationToken() throws CaptureException {
|
||||
if (mOperationInProgress) {
|
||||
throw new CaptureException("Another operation already in progress.");
|
||||
}
|
||||
mOperationInProgress = true;
|
||||
return ++mOperationToken;
|
||||
}
|
||||
|
||||
private void waitForOperation(long timeout) throws CaptureException {
|
||||
try {
|
||||
wait(timeout);
|
||||
} catch (InterruptedException e) {
|
||||
throw new CaptureException("Waiting for heap capture failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (mOperationInProgress) {
|
||||
mOperationInProgress = false;
|
||||
throw new CaptureException("heap capture timed out.");
|
||||
}
|
||||
|
||||
if (mOperationError != null) {
|
||||
throw new CaptureException(mOperationError);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public synchronized void operationComplete(int token, String error) {
|
||||
if (token == mOperationToken) {
|
||||
mOperationInProgress = false;
|
||||
mOperationError = error;
|
||||
this.notify();
|
||||
} else {
|
||||
throw new RuntimeException("Completed operation is not in progress.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "JSCHeapCapture";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
mHeapCapture = getReactApplicationContext().getJSModule(HeapCapture.class);
|
||||
registerHeapCapture(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCatalystInstanceDestroy() {
|
||||
super.onCatalystInstanceDestroy();
|
||||
unregisterHeapCapture(this);
|
||||
mHeapCapture = null;
|
||||
}
|
||||
}
|
|
@ -19,4 +19,5 @@
|
|||
<string name="catalyst_element_inspector" project="catalyst" translatable="false">Toggle Inspector</string>
|
||||
<string name="catalyst_start_profile" project="catalyst" translatable="false">Start Profile</string>
|
||||
<string name="catalyst_stop_profile" project="catalyst" translatable="false">Stop Profile</string>
|
||||
<string name="catalyst_heap_capture" project="catalyst" translatable="false">Capture Heap</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue