mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
refactor RuntimeSamplingProfile serializer (#52916)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52916 # Changelog: [Internal] Align with other serializers in `jsinspector-modern` to have just static public method. Reviewed By: rubennorte Differential Revision: D79131985 fbshipit-source-id: 3f1f08641bb96a9fbd067992b8ce294af9d27688
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a8f6c96bc2
commit
b58c2ffd72
@@ -110,12 +110,14 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
|
||||
performanceTracer.collectEvents(
|
||||
dataCollectedCallback, TRACE_EVENT_CHUNK_SIZE);
|
||||
|
||||
tracing::RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
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",
|
||||
|
||||
+107
-42
@@ -27,10 +27,6 @@ HighResTimeStamp getHighResTimeStampForSample(
|
||||
return HighResTimeStamp::fromChronoSteadyClockTimePoint(chronoTimePoint);
|
||||
}
|
||||
|
||||
// Right now we only emit single Profile. We might revisit this decision in the
|
||||
// future, once we support multiple VMs being sampled at the same time.
|
||||
constexpr RuntimeProfileId PROFILE_ID = 1;
|
||||
|
||||
/// Fallback script ID for artificial call frames, such as (root), (idle) or
|
||||
/// (program). Required for emulating the payload in a format that is expected
|
||||
/// by Chrome DevTools.
|
||||
@@ -62,7 +58,7 @@ TraceEventProfileChunk::CPUProfile::Node convertToTraceEventProfileNode(
|
||||
|
||||
return TraceEventProfileChunk::CPUProfile::Node{
|
||||
.id = node.getId(),
|
||||
.callFrame = traceEventCallFrame,
|
||||
.callFrame = std::move(traceEventCallFrame),
|
||||
.parentId = node.hasParent() ? std::optional<uint32_t>(node.getParentId())
|
||||
: std::nullopt,
|
||||
};
|
||||
@@ -95,22 +91,55 @@ class ProfileTreeRootNode : public ProfileTreeNode {
|
||||
createArtificialCallFrame(ROOT_FRAME_NAME)) {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
struct ProfileChunk {
|
||||
ProfileChunk(
|
||||
uint16_t chunkSize,
|
||||
ProcessId chunkProcessId,
|
||||
ThreadId chunkThreadId,
|
||||
HighResTimeStamp chunkTimestamp)
|
||||
: size(chunkSize),
|
||||
processId(chunkProcessId),
|
||||
threadId(chunkThreadId),
|
||||
timestamp(chunkTimestamp) {
|
||||
samples.reserve(size);
|
||||
timeDeltas.reserve(size);
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::sendProfileTraceEvent(
|
||||
inline bool isFull() const {
|
||||
return samples.size() == size;
|
||||
}
|
||||
|
||||
inline bool isEmpty() const {
|
||||
return samples.empty();
|
||||
}
|
||||
|
||||
std::vector<ProfileTreeNode> nodes;
|
||||
std::vector<uint32_t> samples;
|
||||
std::vector<HighResDuration> timeDeltas;
|
||||
uint16_t size;
|
||||
ProcessId processId;
|
||||
ThreadId threadId;
|
||||
HighResTimeStamp timestamp;
|
||||
};
|
||||
|
||||
// Construct and send "Profile" Trace Event with dispatchCallback.
|
||||
void sendProfileTraceEvent(
|
||||
ProcessId processId,
|
||||
ThreadId threadId,
|
||||
RuntimeProfileId profileId,
|
||||
HighResTimeStamp profileStartTimestamp) const {
|
||||
HighResTimeStamp profileStartTimestamp,
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>&
|
||||
dispatchCallback) {
|
||||
auto traceEvent = PerformanceTracer::constructRuntimeProfileTraceEvent(
|
||||
profileId, processId, threadId, profileStartTimestamp);
|
||||
folly::dynamic serializedTraceEvent =
|
||||
TraceEventSerializer::serialize(std::move(traceEvent));
|
||||
|
||||
notificationCallback_(folly::dynamic::array(std::move(serializedTraceEvent)));
|
||||
dispatchCallback(folly::dynamic::array(std::move(serializedTraceEvent)));
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::chunkEmptySample(
|
||||
// Add an empty sample to the chunk.
|
||||
void chunkEmptySample(
|
||||
ProfileChunk& chunk,
|
||||
uint32_t idleNodeId,
|
||||
HighResDuration samplesTimeDelta) {
|
||||
@@ -118,13 +147,12 @@ void RuntimeSamplingProfileTraceEventSerializer::chunkEmptySample(
|
||||
chunk.timeDeltas.push_back(samplesTimeDelta);
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::bufferProfileChunkTraceEvent(
|
||||
// Take the current local ProfileChunk, serialize it as "ProfileChunk" Trace
|
||||
// Event and buffer it.
|
||||
void bufferProfileChunkTraceEvent(
|
||||
ProfileChunk&& chunk,
|
||||
RuntimeProfileId profileId) {
|
||||
if (chunk.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeProfileId profileId,
|
||||
folly::dynamic& traceEventBuffer) {
|
||||
std::vector<TraceEventProfileChunk::CPUProfile::Node> traceEventNodes;
|
||||
traceEventNodes.reserve(chunk.nodes.size());
|
||||
for (const auto& node : chunk.nodes) {
|
||||
@@ -146,16 +174,17 @@ void RuntimeSamplingProfileTraceEventSerializer::bufferProfileChunkTraceEvent(
|
||||
auto serializedTraceEvent =
|
||||
TraceEventSerializer::serialize(std::move(traceEvent));
|
||||
|
||||
traceEventBuffer_.push_back(std::move(serializedTraceEvent));
|
||||
traceEventBuffer.push_back(std::move(serializedTraceEvent));
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::processCallStack(
|
||||
// Process a call stack of a single sample and add it to the chunk.
|
||||
void processCallStack(
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame>&& callStack,
|
||||
ProfileChunk& chunk,
|
||||
ProfileTreeNode& rootNode,
|
||||
uint32_t idleNodeId,
|
||||
HighResDuration samplesTimeDelta,
|
||||
NodeIdGenerator& nodeIdGenerator) {
|
||||
IdGenerator& nodeIdGenerator) {
|
||||
if (callStack.empty()) {
|
||||
chunkEmptySample(chunk, idleNodeId, samplesTimeDelta);
|
||||
return;
|
||||
@@ -190,39 +219,71 @@ void RuntimeSamplingProfileTraceEventSerializer::processCallStack(
|
||||
chunk.timeDeltas.push_back(samplesTimeDelta);
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::
|
||||
sendBufferedTraceEventsAndClear() {
|
||||
notificationCallback_(std::move(traceEventBuffer_));
|
||||
|
||||
traceEventBuffer_ = folly::dynamic::array();
|
||||
traceEventBuffer_.reserve(traceEventChunkSize_);
|
||||
// Send buffered Trace Events and reset the buffer.
|
||||
void sendBufferedTraceEvents(
|
||||
folly::dynamic&& traceEventBuffer,
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>&
|
||||
dispatchCallback) {
|
||||
dispatchCallback(std::move(traceEventBuffer));
|
||||
}
|
||||
|
||||
void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
} // namespace
|
||||
|
||||
/* static */ void
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::vector<RuntimeSamplingProfile>&& profiles,
|
||||
IdGenerator& profileIdGenerator,
|
||||
HighResTimeStamp tracingStartTime,
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>&
|
||||
dispatchCallback,
|
||||
uint16_t traceEventChunkSize,
|
||||
uint16_t profileChunkSize) {
|
||||
for (auto&& profile : profiles) {
|
||||
serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
dispatchCallback,
|
||||
traceEventChunkSize,
|
||||
profileChunkSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
RuntimeSamplingProfile&& profile,
|
||||
HighResTimeStamp tracingStartTime) {
|
||||
IdGenerator& profileIdGenerator,
|
||||
HighResTimeStamp tracingStartTime,
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>&
|
||||
dispatchCallback,
|
||||
uint16_t traceEventChunkSize,
|
||||
uint16_t profileChunkSize) {
|
||||
auto samples = std::move(profile.samples);
|
||||
if (samples.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadId firstChunkThreadId = samples.front().threadId;
|
||||
auto traceEventBuffer = folly::dynamic::array();
|
||||
traceEventBuffer.reserve(traceEventChunkSize);
|
||||
|
||||
ThreadId threadId = samples.front().threadId;
|
||||
HighResTimeStamp previousSampleTimestamp = tracingStartTime;
|
||||
HighResTimeStamp currentChunkTimestamp = tracingStartTime;
|
||||
auto profileId = profileIdGenerator.getNext();
|
||||
|
||||
sendProfileTraceEvent(
|
||||
profile.processId, firstChunkThreadId, PROFILE_ID, tracingStartTime);
|
||||
profile.processId,
|
||||
threadId,
|
||||
profileId,
|
||||
tracingStartTime,
|
||||
dispatchCallback);
|
||||
|
||||
// There could be any number of new nodes in this chunk. Empty if all nodes
|
||||
// are already emitted in previous chunks.
|
||||
ProfileChunk chunk{
|
||||
profileChunkSize_,
|
||||
profile.processId,
|
||||
firstChunkThreadId,
|
||||
currentChunkTimestamp};
|
||||
|
||||
NodeIdGenerator nodeIdGenerator{};
|
||||
profileChunkSize, profile.processId, threadId, currentChunkTimestamp};
|
||||
|
||||
IdGenerator nodeIdGenerator{};
|
||||
ProfileTreeRootNode rootNode(nodeIdGenerator.getNext());
|
||||
chunk.nodes.push_back(rootNode);
|
||||
|
||||
@@ -248,16 +309,20 @@ void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
// We should group samples by thread id once we support executing JavaScript
|
||||
// on different threads.
|
||||
if (currentSampleThreadId != chunk.threadId || chunk.isFull()) {
|
||||
bufferProfileChunkTraceEvent(std::move(chunk), PROFILE_ID);
|
||||
bufferProfileChunkTraceEvent(
|
||||
std::move(chunk), profileId, traceEventBuffer);
|
||||
chunk = ProfileChunk{
|
||||
profileChunkSize_,
|
||||
profileChunkSize,
|
||||
profile.processId,
|
||||
currentSampleThreadId,
|
||||
currentChunkTimestamp};
|
||||
}
|
||||
|
||||
if (traceEventBuffer_.size() == traceEventChunkSize_) {
|
||||
sendBufferedTraceEventsAndClear();
|
||||
if (traceEventBuffer.size() == traceEventChunkSize) {
|
||||
sendBufferedTraceEvents(std::move(traceEventBuffer), dispatchCallback);
|
||||
|
||||
traceEventBuffer = folly::dynamic::array();
|
||||
traceEventBuffer.reserve(traceEventChunkSize);
|
||||
}
|
||||
|
||||
processCallStack(
|
||||
@@ -272,11 +337,11 @@ void RuntimeSamplingProfileTraceEventSerializer::serializeAndNotify(
|
||||
}
|
||||
|
||||
if (!chunk.isEmpty()) {
|
||||
bufferProfileChunkTraceEvent(std::move(chunk), PROFILE_ID);
|
||||
bufferProfileChunkTraceEvent(std::move(chunk), profileId, traceEventBuffer);
|
||||
}
|
||||
|
||||
if (!traceEventBuffer_.empty()) {
|
||||
sendBufferedTraceEventsAndClear();
|
||||
if (!traceEventBuffer.empty()) {
|
||||
sendBufferedTraceEvents(std::move(traceEventBuffer), dispatchCallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+25
-130
@@ -7,16 +7,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ProfileTreeNode.h"
|
||||
#include "RuntimeSamplingProfile.h"
|
||||
|
||||
#include <react/timing/primitives.h>
|
||||
|
||||
namespace facebook::react::jsinspector_modern::tracing {
|
||||
|
||||
namespace {
|
||||
|
||||
struct NodeIdGenerator {
|
||||
struct IdGenerator {
|
||||
public:
|
||||
uint32_t getNext() {
|
||||
return ++counter_;
|
||||
@@ -26,144 +23,42 @@ struct NodeIdGenerator {
|
||||
uint32_t counter_ = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* Serializes RuntimeSamplingProfile into collection of specific Trace Events,
|
||||
* which represent Profile information on a timeline.
|
||||
*/
|
||||
class RuntimeSamplingProfileTraceEventSerializer {
|
||||
struct ProfileChunk {
|
||||
ProfileChunk(
|
||||
uint16_t chunkSize,
|
||||
ProcessId chunkProcessId,
|
||||
ThreadId chunkThreadId,
|
||||
HighResTimeStamp chunkTimestamp)
|
||||
: size(chunkSize),
|
||||
processId(chunkProcessId),
|
||||
threadId(chunkThreadId),
|
||||
timestamp(chunkTimestamp) {
|
||||
samples.reserve(size);
|
||||
timeDeltas.reserve(size);
|
||||
}
|
||||
|
||||
bool isFull() const {
|
||||
return samples.size() == size;
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return samples.empty();
|
||||
}
|
||||
|
||||
std::vector<ProfileTreeNode> nodes;
|
||||
std::vector<uint32_t> samples;
|
||||
std::vector<HighResDuration> timeDeltas;
|
||||
uint16_t size;
|
||||
ProcessId processId;
|
||||
ThreadId threadId;
|
||||
HighResTimeStamp timestamp;
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* \param notificationCallback A reference to a callback, which is called
|
||||
* when a chunk of trace events is ready to be sent.
|
||||
* \param traceEventChunkSize The maximum number of ProfileChunk trace
|
||||
* events that can be sent in a single CDP Tracing.dataCollected message.
|
||||
* \param profile What we will be serializing.
|
||||
* \param profileIdGenerator A reference to an IdGenerator, which will be
|
||||
* used for generating unique ids for ProfileChunks.
|
||||
* \param tracingStartTime A timestamp of when tracing started, will be used
|
||||
* as a starting reference point of JavaScript samples recording.
|
||||
* \param dispatchCallback A reference to a callback, which is called when a
|
||||
* chunk of trace events is ready to be sent.
|
||||
* \param traceEventChunkSize The maximum number of ProfileChunk trace events
|
||||
* that can be sent in a single CDP Tracing.dataCollected message.
|
||||
* \param profileChunkSize The maximum number of ProfileChunk trace events
|
||||
* that can be sent in a single ProfileChunk trace event.
|
||||
*/
|
||||
RuntimeSamplingProfileTraceEventSerializer(
|
||||
std::function<void(folly::dynamic&& traceEventsChunk)>
|
||||
notificationCallback,
|
||||
uint16_t traceEventChunkSize,
|
||||
uint16_t profileChunkSize = 10)
|
||||
: notificationCallback_(std::move(notificationCallback)),
|
||||
traceEventChunkSize_(traceEventChunkSize),
|
||||
profileChunkSize_(profileChunkSize) {
|
||||
traceEventBuffer_ = folly::dynamic::array();
|
||||
traceEventBuffer_.reserve(traceEventChunkSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param profile What we will be serializing.
|
||||
* \param tracingStartTime A timestamp of when tracing of an Instance started,
|
||||
* will be used as a starting reference point of JavaScript samples recording.
|
||||
*/
|
||||
void serializeAndNotify(
|
||||
static void serializeAndDispatch(
|
||||
RuntimeSamplingProfile&& profile,
|
||||
HighResTimeStamp tracingStartTime);
|
||||
IdGenerator& profileIdGenerator,
|
||||
HighResTimeStamp tracingStartTime,
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>&
|
||||
dispatchCallback,
|
||||
uint16_t traceEventChunkSize,
|
||||
uint16_t profileChunkSize = 10);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Sends a single "Profile" Trace Event via notificationCallback_.
|
||||
|
||||
* \param processId The id of the process, where the Profile was collected.
|
||||
* \param threadId The id of the thread, where the Profile was collected.
|
||||
* \param profileId The id of the Profile.
|
||||
* \param profileStartUnixTimestamp The Unix timestamp of the start of the
|
||||
* profile.
|
||||
*/
|
||||
void sendProfileTraceEvent(
|
||||
ProcessId processId,
|
||||
ThreadId threadId,
|
||||
RuntimeProfileId profileId,
|
||||
HighResTimeStamp profileStartTimestamp) const;
|
||||
|
||||
/**
|
||||
* Encapsulates logic for processing the empty sample, when the VM was idling.
|
||||
* \param chunk The profile chunk, which will record this sample.
|
||||
* \param idleNodeId The id of the (idle) node.
|
||||
* \param samplesTimeDelta Delta between the current sample and the
|
||||
* previous one.
|
||||
*/
|
||||
void chunkEmptySample(
|
||||
ProfileChunk& chunk,
|
||||
uint32_t idleNodeId,
|
||||
HighResDuration samplesTimeDelta);
|
||||
|
||||
/**
|
||||
* Records ProfileChunk as a "ProfileChunk" Trace Event in traceEventBuffer_.
|
||||
* \param chunk The chunk that will be buffered.
|
||||
* \param profileId The id of the Profile.
|
||||
*/
|
||||
void bufferProfileChunkTraceEvent(
|
||||
ProfileChunk&& chunk,
|
||||
RuntimeProfileId profileId);
|
||||
|
||||
/**
|
||||
* Encapsulates logic for processing the call stack of the sample.
|
||||
* \param callStack The call stack that will be processed.
|
||||
* \param chunk The profile chunk, which will buffer the sample with the
|
||||
* provided call stack.
|
||||
* \param rootNode The (root) node. Will be the parent node of the
|
||||
* corresponding profile tree branch.
|
||||
* \param idleNodeId Id of the (idle) node. Will be the only node that is used
|
||||
* for the corresponding profile tree branch, in case of an empty call stack.
|
||||
* \param samplesTimeDelta Delta between the current sample and the previous
|
||||
* one.
|
||||
* \param nodeIdGenerator NodeIdGenerator instance that will be used for
|
||||
* generating unique node ids.
|
||||
*/
|
||||
void processCallStack(
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame>&& callStack,
|
||||
ProfileChunk& chunk,
|
||||
ProfileTreeNode& rootNode,
|
||||
uint32_t idleNodeId,
|
||||
HighResDuration samplesTimeDelta,
|
||||
NodeIdGenerator& nodeIdGenerator);
|
||||
|
||||
/**
|
||||
* Sends buffered Trace Events via notificationCallback_ and then clears it.
|
||||
*/
|
||||
void sendBufferedTraceEventsAndClear();
|
||||
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>
|
||||
notificationCallback_;
|
||||
const uint16_t traceEventChunkSize_;
|
||||
const uint16_t profileChunkSize_;
|
||||
|
||||
folly::dynamic traceEventBuffer_;
|
||||
static void serializeAndDispatch(
|
||||
std::vector<RuntimeSamplingProfile>&& profiles,
|
||||
IdGenerator& profileIdGenerator,
|
||||
HighResTimeStamp tracingStartTime,
|
||||
const std::function<void(folly::dynamic&& traceEventsChunk)>&
|
||||
dispatchCallback,
|
||||
uint16_t traceEventChunkSize,
|
||||
uint16_t profileChunkSize = 10);
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern::tracing
|
||||
|
||||
+44
-22
@@ -67,14 +67,18 @@ class RuntimeSamplingProfileTraceEventSerializerTest : public ::testing::Test {
|
||||
TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptyProfile) {
|
||||
// Setup
|
||||
auto notificationCallback = createNotificationCallback();
|
||||
RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
notificationCallback, 10);
|
||||
IdGenerator profileIdGenerator;
|
||||
|
||||
auto profile = createEmptyProfile();
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
notificationCallback,
|
||||
10);
|
||||
|
||||
// Nothing should be reported if the profile is empty.
|
||||
EXPECT_TRUE(notificationEvents_.empty());
|
||||
@@ -85,8 +89,7 @@ TEST_F(
|
||||
SameCallFramesAreMerged) {
|
||||
// Setup
|
||||
auto notificationCallback = createNotificationCallback();
|
||||
RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
notificationCallback, 10);
|
||||
IdGenerator profileIdGenerator;
|
||||
|
||||
// [ foo ]
|
||||
// [ bar ]
|
||||
@@ -122,7 +125,12 @@ TEST_F(
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
notificationCallback,
|
||||
10);
|
||||
|
||||
// Verify
|
||||
ASSERT_EQ(notificationEvents_.size(), 2);
|
||||
@@ -135,8 +143,7 @@ TEST_F(
|
||||
TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptySample) {
|
||||
// Setup
|
||||
auto notificationCallback = createNotificationCallback();
|
||||
RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
notificationCallback, 10);
|
||||
IdGenerator profileIdGenerator;
|
||||
|
||||
// Create an empty sample (no call stack)
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> emptyCallStack;
|
||||
@@ -150,12 +157,13 @@ TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptySample) {
|
||||
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Mock the performance tracer methods
|
||||
folly::dynamic profileEvent = folly::dynamic::object;
|
||||
folly::dynamic chunkEvent = folly::dynamic::object;
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
notificationCallback,
|
||||
10);
|
||||
|
||||
// Verify
|
||||
// [["Profile"], ["ProfileChunk"]]
|
||||
@@ -171,8 +179,7 @@ TEST_F(
|
||||
SamplesFromDifferentThreads) {
|
||||
// Setup
|
||||
auto notificationCallback = createNotificationCallback();
|
||||
RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
notificationCallback, 10);
|
||||
IdGenerator profileIdGenerator;
|
||||
|
||||
// Create samples with different thread IDs
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack = {
|
||||
@@ -192,7 +199,12 @@ TEST_F(
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
notificationCallback,
|
||||
10);
|
||||
|
||||
// [["Profile"], ["ProfileChunk", "ProfileChunk", "ProfileChunk]]
|
||||
// Samples from different thread should never be grouped together in the same
|
||||
@@ -206,10 +218,9 @@ TEST_F(
|
||||
TraceEventChunkSizeLimit) {
|
||||
// Setup
|
||||
auto notificationCallback = createNotificationCallback();
|
||||
IdGenerator profileIdGenerator;
|
||||
uint16_t traceEventChunkSize = 2;
|
||||
uint16_t profileChunkSize = 2;
|
||||
RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
notificationCallback, traceEventChunkSize, profileChunkSize);
|
||||
|
||||
// Create multiple samples
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack = {
|
||||
@@ -228,7 +239,13 @@ TEST_F(
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
notificationCallback,
|
||||
traceEventChunkSize,
|
||||
profileChunkSize);
|
||||
|
||||
// [["Profile"], ["ProfileChunk", "ProfileChunk"], ["ProfileChunk"]]
|
||||
ASSERT_EQ(notificationEvents_.size(), 3);
|
||||
@@ -242,12 +259,11 @@ TEST_F(
|
||||
TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, ProfileChunkSizeLimit) {
|
||||
// Setup
|
||||
auto notificationCallback = createNotificationCallback();
|
||||
IdGenerator profileIdGenerator;
|
||||
// Set a small profile chunk size to test profile chunking
|
||||
uint16_t traceEventChunkSize = 10;
|
||||
uint16_t profileChunkSize = 2;
|
||||
double samplesCount = 5;
|
||||
RuntimeSamplingProfileTraceEventSerializer serializer(
|
||||
notificationCallback, traceEventChunkSize, profileChunkSize);
|
||||
|
||||
// Create multiple samples
|
||||
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack = {
|
||||
@@ -266,7 +282,13 @@ TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, ProfileChunkSizeLimit) {
|
||||
auto tracingStartTime = HighResTimeStamp::now();
|
||||
|
||||
// Execute
|
||||
serializer.serializeAndNotify(std::move(profile), tracingStartTime);
|
||||
RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
|
||||
std::move(profile),
|
||||
profileIdGenerator,
|
||||
tracingStartTime,
|
||||
notificationCallback,
|
||||
traceEventChunkSize,
|
||||
profileChunkSize);
|
||||
|
||||
// [["Profile"], ["ProfileChunk", "ProfileChunk", "ProfileChunk"]]
|
||||
ASSERT_EQ(notificationEvents_.size(), 2);
|
||||
|
||||
Reference in New Issue
Block a user