Skip to content
Permalink
Browse files
Plumb through memory allocation profiler feature to Chrome Inspector
Summary: Changelog: Make allocation profiler feature of Chome Inspector work

Reviewed By: dulinriley

Differential Revision: D20383003

fbshipit-source-id: 8a10c310d5a639a6644763adb53f2f0017057587
  • Loading branch information
jbower-fb authored and facebook-github-bot committed Mar 31, 2020
1 parent 8454975 commit ed3054927c30c8823f78026b9c4cb42fbe4f8b00
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 9 deletions.
@@ -82,6 +82,10 @@ class Connection::Impl : public inspector::InspectorObserver,
void handle(const m::debugger::StepOutRequest &req) override;
void handle(const m::debugger::StepOverRequest &req) override;
void handle(const m::heapProfiler::TakeHeapSnapshotRequest &req) override;
void handle(
const m::heapProfiler::StartTrackingHeapObjectsRequest &req) override;
void handle(
const m::heapProfiler::StopTrackingHeapObjectsRequest &req) override;
void handle(const m::runtime::EvaluateRequest &req) override;
void handle(const m::runtime::GetPropertiesRequest &req) override;

@@ -95,6 +99,11 @@ class Connection::Impl : public inspector::InspectorObserver,
const std::string &objectGroup,
bool onlyOwnProperties);

void sendSnapshot(
int reqId,
std::string message,
bool reportProgress,
bool stopStackTraceCapture);
void sendToClient(const std::string &str);
void sendResponseToClient(const m::Response &resp);
void sendNotificationToClient(const m::Notification &resp);
@@ -389,15 +398,16 @@ void Connection::Impl::handle(
.thenError<std::exception>(sendErrorToClient(req.id));
}

void Connection::Impl::handle(
const m::heapProfiler::TakeHeapSnapshotRequest &req) {
const auto id = req.id;
const bool reportProgress = req.reportProgress && *req.reportProgress;

void Connection::Impl::sendSnapshot(
int reqId,
std::string message,
bool reportProgress,
bool stopStackTraceCapture) {
inspector_
->executeIfEnabled(
"HeapProfiler.takeHeapSnapshot",
[this, reportProgress](const debugger::ProgramState &) {
message,
[this, reportProgress, stopStackTraceCapture](
const debugger::ProgramState &) {
if (reportProgress) {
// A progress notification with finished = true indicates the
// snapshot has been captured and is ready to be sent. Our
@@ -421,13 +431,53 @@ void Connection::Impl::handle(
});

getRuntime().instrumentation().createSnapshotToStream(cos);
if (stopStackTraceCapture) {
getRuntime()
.instrumentation()
.stopTrackingHeapObjectStackTraces();
}
})
.via(executor_.get())
.thenValue([this, reqId](auto &&) {
sendResponseToClient(m::makeOkResponse(reqId));
})
.thenError<std::exception>(sendErrorToClient(reqId));
}

void Connection::Impl::handle(
const m::heapProfiler::TakeHeapSnapshotRequest &req) {
sendSnapshot(
req.id,
"HeapSnapshot.takeHeapSnapshot",
req.reportProgress && *req.reportProgress,
/* stopStackTraceCapture */ false);
}

void Connection::Impl::handle(
const m::heapProfiler::StartTrackingHeapObjectsRequest &req) {
const auto id = req.id;

inspector_
->executeIfEnabled(
"HeapProfiler.startTrackingHeapObjects",
[this](const debugger::ProgramState &) {
getRuntime().instrumentation().startTrackingHeapObjectStackTraces();
})
.via(executor_.get())
.thenValue(
[this, id](auto &&) { sendResponseToClient(m::makeOkResponse(id)); })
.thenError<std::exception>(sendErrorToClient(req.id));
}

void Connection::Impl::handle(
const m::heapProfiler::StopTrackingHeapObjectsRequest &req) {
sendSnapshot(
req.id,
"HeapSnapshot.takeHeapSnapshot",
req.reportProgress && *req.reportProgress,
/* stopStackTraceCapture */ true);
}

void Connection::Impl::handle(const m::runtime::EvaluateRequest &req) {
auto remoteObjPtr = std::make_shared<m::runtime::RemoteObject>();

@@ -1,5 +1,5 @@
// Copyright 2004-present Facebook. All Rights Reserved.
// @generated SignedSource<<633984dcfe87d2822ef0e80c1aab93ef>>
// @generated SignedSource<<4ab81efd6f767bd583d00c806b7d1d9b>>

#include "MessageTypes.h"

@@ -40,6 +40,10 @@ std::unique_ptr<Request> Request::fromJsonThrowOnError(const std::string &str) {
{"Debugger.stepInto", makeUnique<debugger::StepIntoRequest>},
{"Debugger.stepOut", makeUnique<debugger::StepOutRequest>},
{"Debugger.stepOver", makeUnique<debugger::StepOverRequest>},
{"HeapProfiler.startTrackingHeapObjects",
makeUnique<heapProfiler::StartTrackingHeapObjectsRequest>},
{"HeapProfiler.stopTrackingHeapObjects",
makeUnique<heapProfiler::StopTrackingHeapObjectsRequest>},
{"HeapProfiler.takeHeapSnapshot",
makeUnique<heapProfiler::TakeHeapSnapshotRequest>},
{"Runtime.evaluate", makeUnique<runtime::EvaluateRequest>},
@@ -587,6 +591,66 @@ void debugger::StepOverRequest::accept(RequestHandler &handler) const {
handler.handle(*this);
}

heapProfiler::StartTrackingHeapObjectsRequest::StartTrackingHeapObjectsRequest()
: Request("HeapProfiler.startTrackingHeapObjects") {}

heapProfiler::StartTrackingHeapObjectsRequest::StartTrackingHeapObjectsRequest(
const dynamic &obj)
: Request("HeapProfiler.startTrackingHeapObjects") {
assign(id, obj, "id");
assign(method, obj, "method");

dynamic params = obj.at("params");
assign(trackAllocations, params, "trackAllocations");
}

dynamic heapProfiler::StartTrackingHeapObjectsRequest::toDynamic() const {
dynamic params = dynamic::object;
put(params, "trackAllocations", trackAllocations);

dynamic obj = dynamic::object;
put(obj, "id", id);
put(obj, "method", method);
put(obj, "params", std::move(params));
return obj;
}

void heapProfiler::StartTrackingHeapObjectsRequest::accept(
RequestHandler &handler) const {
handler.handle(*this);
}

heapProfiler::StopTrackingHeapObjectsRequest::StopTrackingHeapObjectsRequest()
: Request("HeapProfiler.stopTrackingHeapObjects") {}

heapProfiler::StopTrackingHeapObjectsRequest::StopTrackingHeapObjectsRequest(
const dynamic &obj)
: Request("HeapProfiler.stopTrackingHeapObjects") {
assign(id, obj, "id");
assign(method, obj, "method");

dynamic params = obj.at("params");
assign(reportProgress, params, "reportProgress");
assign(treatGlobalObjectsAsRoots, params, "treatGlobalObjectsAsRoots");
}

dynamic heapProfiler::StopTrackingHeapObjectsRequest::toDynamic() const {
dynamic params = dynamic::object;
put(params, "reportProgress", reportProgress);
put(params, "treatGlobalObjectsAsRoots", treatGlobalObjectsAsRoots);

dynamic obj = dynamic::object;
put(obj, "id", id);
put(obj, "method", method);
put(obj, "params", std::move(params));
return obj;
}

void heapProfiler::StopTrackingHeapObjectsRequest::accept(
RequestHandler &handler) const {
handler.handle(*this);
}

heapProfiler::TakeHeapSnapshotRequest::TakeHeapSnapshotRequest()
: Request("HeapProfiler.takeHeapSnapshot") {}

@@ -1,5 +1,5 @@
// Copyright 2004-present Facebook. All Rights Reserved.
// @generated SignedSource<<16a6754d1896fef0cbab2a05800f6885>>
// @generated SignedSource<<0a1a011902fd18d4eebd2fe12fafb8b1>>

#pragma once

@@ -68,6 +68,8 @@ using UnserializableValue = std::string;
namespace heapProfiler {
struct AddHeapSnapshotChunkNotification;
struct ReportHeapSnapshotProgressNotification;
struct StartTrackingHeapObjectsRequest;
struct StopTrackingHeapObjectsRequest;
struct TakeHeapSnapshotRequest;
} // namespace heapProfiler

@@ -88,6 +90,10 @@ struct RequestHandler {
virtual void handle(const debugger::StepIntoRequest &req) = 0;
virtual void handle(const debugger::StepOutRequest &req) = 0;
virtual void handle(const debugger::StepOverRequest &req) = 0;
virtual void handle(
const heapProfiler::StartTrackingHeapObjectsRequest &req) = 0;
virtual void handle(
const heapProfiler::StopTrackingHeapObjectsRequest &req) = 0;
virtual void handle(const heapProfiler::TakeHeapSnapshotRequest &req) = 0;
virtual void handle(const runtime::EvaluateRequest &req) = 0;
virtual void handle(const runtime::GetPropertiesRequest &req) = 0;
@@ -108,6 +114,10 @@ struct NoopRequestHandler : public RequestHandler {
void handle(const debugger::StepIntoRequest &req) override {}
void handle(const debugger::StepOutRequest &req) override {}
void handle(const debugger::StepOverRequest &req) override {}
void handle(
const heapProfiler::StartTrackingHeapObjectsRequest &req) override {}
void handle(
const heapProfiler::StopTrackingHeapObjectsRequest &req) override {}
void handle(const heapProfiler::TakeHeapSnapshotRequest &req) override {}
void handle(const runtime::EvaluateRequest &req) override {}
void handle(const runtime::GetPropertiesRequest &req) override {}
@@ -369,6 +379,27 @@ struct debugger::StepOverRequest : public Request {
void accept(RequestHandler &handler) const override;
};

struct heapProfiler::StartTrackingHeapObjectsRequest : public Request {
StartTrackingHeapObjectsRequest();
explicit StartTrackingHeapObjectsRequest(const folly::dynamic &obj);

folly::dynamic toDynamic() const override;
void accept(RequestHandler &handler) const override;

folly::Optional<bool> trackAllocations;
};

struct heapProfiler::StopTrackingHeapObjectsRequest : public Request {
StopTrackingHeapObjectsRequest();
explicit StopTrackingHeapObjectsRequest(const folly::dynamic &obj);

folly::dynamic toDynamic() const override;
void accept(RequestHandler &handler) const override;

folly::Optional<bool> reportProgress;
folly::Optional<bool> treatGlobalObjectsAsRoots;
};

struct heapProfiler::TakeHeapSnapshotRequest : public Request {
TakeHeapSnapshotRequest();
explicit TakeHeapSnapshotRequest(const folly::dynamic &obj);
@@ -17,6 +17,8 @@ Debugger.stepOver
HeapProfiler.addHeapSnapshotChunk
HeapProfiler.reportHeapSnapshotProgress
HeapProfiler.takeHeapSnapshot
HeapProfiler.startTrackingHeapObjects
HeapProfiler.stopTrackingHeapObjects
Runtime.consoleAPICalled
Runtime.evaluate
Runtime.executionContextCreated
@@ -335,6 +335,14 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
plain().instrumentation().collectGarbage();
}

void startTrackingHeapObjectStackTraces() override {
plain().instrumentation().startTrackingHeapObjectStackTraces();
}

void stopTrackingHeapObjectStackTraces() override {
plain().instrumentation().stopTrackingHeapObjectStackTraces();
}

void createSnapshotToFile(const std::string& path) override {
plain().instrumentation().createSnapshotToFile(path);
}
@@ -52,6 +52,13 @@ class Instrumentation {
/// perform a full garbage collection
virtual void collectGarbage() = 0;

/// Start capturing JS stack-traces for all JS heap allocated objects. These
/// can be accessed via \c ::createSnapshotToFile().
virtual void startTrackingHeapObjectStackTraces() = 0;

/// Stop capture JS stack-traces for JS heap allocated objects.
virtual void stopTrackingHeapObjectStackTraces() = 0;

/// Captures the heap to a file
///
/// \param path to save the heap capture
@@ -99,6 +99,9 @@ Instrumentation& Runtime::instrumentation() {

void collectGarbage() override {}

void startTrackingHeapObjectStackTraces() override {}
void stopTrackingHeapObjectStackTraces() override {}

void createSnapshotToFile(const std::string&) override {
throw JSINativeException(
"Default instrumentation cannot create a heap snapshot");

0 comments on commit ed30549

Please sign in to comment.