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 @@ -5,10 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/

#include <variant>

#include "HermesRuntimeSamplingProfileSerializer.h"

#include <oscompat/OSCompat.h>

#include <variant>

namespace facebook::react::jsinspector_modern::tracing {

namespace {
Expand Down Expand Up @@ -163,6 +165,10 @@ HermesRuntimeSamplingProfileSerializer::serializeToTracingSamplingProfile(

return RuntimeSamplingProfile{
"Hermes",
// Hermes' Profile should be the source of truth for this,
// but it is safe to reuse the process ID here, since everything runs in
// the same process.
oscompat::getCurrentProcessId(),
std::move(reconciledSamples),
std::make_unique<RawHermesRuntimeProfile>(std::move(hermesProfile))};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ void InstanceAgent::maybeSendPendingConsoleMessages() {

void InstanceAgent::startTracing() {
if (runtimeAgent_) {
runtimeAgent_->registerForTracing();
runtimeAgent_->enableSamplingProfiler();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ RuntimeAgent::~RuntimeAgent() {
sessionState_.lastRuntimeAgentExportedState = getExportedState();
}

void RuntimeAgent::registerForTracing() {
targetController_.registerForTracing();
}

void RuntimeAgent::enableSamplingProfiler() {
targetController_.enableSamplingProfiler();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,6 @@ class RuntimeAgent final {
*/
ExportedState getExportedState();

/**
* Registers the corresponding RuntimeTarget for Tracing: might enable some
* capabilities that will be later used in Tracing Profile.
*/
void registerForTracing();

/**
* Start sampling profiler for the corresponding RuntimeTarget.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,6 @@ void RuntimeTargetController::notifyDebuggerSessionDestroyed() {
target_.emitDebuggerSessionDestroyed();
}

void RuntimeTargetController::registerForTracing() {
target_.registerForTracing();
}

void RuntimeTargetController::enableSamplingProfiler() {
target_.enableSamplingProfiler();
}
Expand All @@ -179,12 +175,6 @@ RuntimeTargetController::collectSamplingProfile() {
return target_.collectSamplingProfile();
}

void RuntimeTarget::registerForTracing() {
jsExecutor_([](auto& /*runtime*/) {
tracing::PerformanceTracer::getInstance().reportJavaScriptThread();
});
}

void RuntimeTarget::enableSamplingProfiler() {
delegate_.enableSamplingProfiler();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,6 @@ class RuntimeTargetController {
*/
void notifyDebuggerSessionDestroyed();

/**
* Registers the corresponding RuntimeTarget for Tracing: might enable some
* capabilities that will be later used in Tracing Profile.
*/
void registerForTracing();

/**
* Start sampling profiler for the corresponding RuntimeTarget.
*/
Expand Down Expand Up @@ -208,12 +202,6 @@ class JSINSPECTOR_EXPORT RuntimeTarget
const FrontendChannel& channel,
SessionState& sessionState);

/**
* Registers this Runtime for Tracing: might enable some
* capabilities that will be later used in Tracing Profile.
*/
void registerForTracing();

/**
* Start sampling profiler for a particular JavaScript runtime.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,14 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
performanceTracer.collectEvents(
dataCollectedCallback, TRACE_EVENT_CHUNK_SIZE);

tracing::RuntimeSamplingProfileTraceEventSerializer serializer(
performanceTracer,
dataCollectedCallback,
PROFILE_TRACE_EVENT_CHUNK_SIZE);
auto tracingProfile = instanceAgent_->collectTracingProfile();
serializer.serializeAndNotify(
tracing::IdGenerator profileIdGenerator;
tracing::RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
std::move(tracingProfile.runtimeSamplingProfile),
instanceTracingStartTimestamp_);
profileIdGenerator,
instanceTracingStartTimestamp_,
dataCollectedCallback,
PROFILE_TRACE_EVENT_CHUNK_SIZE);

frontendChannel_(cdp::jsonNotification(
"Tracing.tracingComplete",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,21 @@ PerformanceTracer::PerformanceTracer()
: processId_(oscompat::getCurrentProcessId()) {}

bool PerformanceTracer::startTracing() {
{
std::lock_guard lock(mutex_);
if (tracingAtomic_) {
return false;
}
tracingAtomic_ = true;
std::lock_guard lock(mutex_);
if (tracingAtomic_) {
return false;
}
tracingAtomic_ = true;

reportProcess(processId_, "React Native");

{
std::lock_guard lock(mutex_);
if (!tracingAtomic_) {
return false;
}
buffer_.emplace_back(TraceEvent{
.name = "TracingStartedInPage",
.cat = "disabled-by-default-devtools.timeline",
.ph = 'I',
.ts = HighResTimeStamp::now(),
.pid = processId_,
.tid = oscompat::getCurrentThreadId(),
.args = folly::dynamic::object("data", folly::dynamic::object()),
});
}
buffer_.emplace_back(TraceEvent{
.name = "TracingStartedInPage",
.cat = "disabled-by-default-devtools.timeline",
.ph = 'I',
.ts = HighResTimeStamp::now(),
.pid = processId_,
.tid = oscompat::getCurrentThreadId(),
.args = folly::dynamic::object("data", folly::dynamic::object()),
});

return true;
}
Expand Down Expand Up @@ -269,66 +259,6 @@ void PerformanceTracer::reportTimeStamp(
});
}

void PerformanceTracer::reportProcess(uint64_t id, const std::string& name) {
if (!tracingAtomic_) {
return;
}

std::lock_guard<std::mutex> lock(mutex_);
if (!tracingAtomic_) {
return;
}

buffer_.emplace_back(TraceEvent{
.name = "process_name",
.cat = "__metadata",
.ph = 'M',
.ts = TRACING_TIME_ORIGIN,
.pid = id,
.tid = 0,
.args = folly::dynamic::object("name", name),
});
}

void PerformanceTracer::reportJavaScriptThread() {
reportThread(oscompat::getCurrentThreadId(), "JavaScript");
}

void PerformanceTracer::reportThread(uint64_t id, const std::string& name) {
if (!tracingAtomic_) {
return;
}

std::lock_guard<std::mutex> lock(mutex_);
if (!tracingAtomic_) {
return;
}

buffer_.emplace_back(TraceEvent{
.name = "thread_name",
.cat = "__metadata",
.ph = 'M',
.ts = TRACING_TIME_ORIGIN,
.pid = processId_,
.tid = id,
.args = folly::dynamic::object("name", name),
});

// This is synthetic Trace Event, which should not be represented on a
// timeline. CDT will filter out threads that only have JavaScript samples and
// no timeline events or user timings. We use this event to avoid that.
// This could happen for non-bridgeless apps, where Performance interface is
// not supported and no spec-compliant Event Loop implementation.
buffer_.emplace_back(TraceEvent{
.name = "ReactNative-ThreadRegistered",
.cat = "disabled-by-default-devtools.timeline",
.ph = 'I',
.ts = TRACING_TIME_ORIGIN,
.pid = processId_,
.tid = id,
});
}

void PerformanceTracer::reportEventLoopTask(
HighResTimeStamp start,
HighResTimeStamp end) {
Expand Down Expand Up @@ -375,46 +305,49 @@ void PerformanceTracer::reportEventLoopMicrotasks(
});
}

folly::dynamic PerformanceTracer::getSerializedRuntimeProfileTraceEvent(
uint64_t threadId,
uint16_t profileId,
/* static */ TraceEvent PerformanceTracer::constructRuntimeProfileTraceEvent(
RuntimeProfileId profileId,
ProcessId processId,
ThreadId threadId,
HighResTimeStamp profileTimestamp) {
// CDT prioritizes event timestamp over startTime metadata field.
// https://fburl.com/lo764pf4
return TraceEventSerializer::serialize(TraceEvent{
return TraceEvent{
.id = profileId,
.name = "Profile",
.cat = "disabled-by-default-v8.cpu_profiler",
.ph = 'P',
.ts = profileTimestamp,
.pid = processId_,
.pid = processId,
.tid = threadId,
.args = folly::dynamic::object(
"data",
folly::dynamic::object(
"startTime",
highResTimeStampToTracingClockTimeStamp(profileTimestamp))),
});
};
}

folly::dynamic PerformanceTracer::getSerializedRuntimeProfileChunkTraceEvent(
uint16_t profileId,
uint64_t threadId,
/* static */ TraceEvent
PerformanceTracer::constructRuntimeProfileChunkTraceEvent(
RuntimeProfileId profileId,
ProcessId processId,
ProcessId threadId,
HighResTimeStamp chunkTimestamp,
tracing::TraceEventProfileChunk&& traceEventProfileChunk) {
return TraceEventSerializer::serialize(TraceEvent{
TraceEventProfileChunk&& traceEventProfileChunk) {
return TraceEvent{
.id = profileId,
.name = "ProfileChunk",
.cat = "disabled-by-default-v8.cpu_profiler",
.ph = 'P',
.ts = chunkTimestamp,
.pid = processId_,
.pid = processId,
.tid = threadId,
.args = folly::dynamic::object(
"data",
TraceEventSerializer::serializeProfileChunk(
std::move(traceEventProfileChunk))),
});
};
}

} // namespace facebook::react::jsinspector_modern::tracing
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,6 @@ class PerformanceTracer {
std::optional<std::string> trackGroup = std::nullopt,
std::optional<ConsoleTimeStampColor> color = std::nullopt);

/**
* Record a corresponding Trace Event for OS-level process.
*/
void reportProcess(uint64_t id, const std::string& name);

/**
* Record a corresponding Trace Event for OS-level thread.
*/
void reportThread(uint64_t id, const std::string& name);

/**
* Should only be called from the JavaScript thread, will buffer metadata
* Trace Event.
*/
void reportJavaScriptThread();

/**
* Record an Event Loop tick, which will be represented as an Event Loop task
* on a timeline view and grouped with JavaScript samples.
Expand All @@ -132,21 +116,25 @@ class PerformanceTracer {
void reportEventLoopMicrotasks(HighResTimeStamp start, HighResTimeStamp end);

/**
* Create and serialize Profile Trace Event.
* \return serialized Trace Event that represents a Profile for CDT.
* Creates "Profile" Trace Event.
*
* Can be serialized to JSON with TraceEventSerializer::serialize.
*/
folly::dynamic getSerializedRuntimeProfileTraceEvent(
uint64_t threadId,
uint16_t profileId,
static TraceEvent constructRuntimeProfileTraceEvent(
RuntimeProfileId profileId,
ProcessId processId,
ThreadId threadId,
HighResTimeStamp profileTimestamp);

/**
* Create and serialize ProfileChunk Trace Event.
* \return serialized Trace Event that represents a Profile Chunk for CDT.
* Creates "ProfileChunk" Trace Event.
*
* Can be serialized to JSON with TraceEventSerializer::serialize.
*/
folly::dynamic getSerializedRuntimeProfileChunkTraceEvent(
uint16_t profileId,
uint64_t threadId,
static TraceEvent constructRuntimeProfileChunkTraceEvent(
RuntimeProfileId profileId,
ProcessId processId,
ProcessId threadId,
HighResTimeStamp chunkTimestamp,
TraceEventProfileChunk&& traceEventProfileChunk);

Expand All @@ -156,7 +144,7 @@ class PerformanceTracer {
PerformanceTracer& operator=(const PerformanceTracer&) = delete;
~PerformanceTracer() = default;

const uint64_t processId_;
const ProcessId processId_;

/**
* The flag is atomic in order to enable any thread to read it (via
Expand Down
Loading
Loading