Skip to content

Commit 60a8d6c

Browse files
committed
perf: generate buffer chunks in C++ memory without using JS
1 parent 62b7be6 commit 60a8d6c

2 files changed

Lines changed: 118 additions & 159 deletions

File tree

NativeScript/inspector/ns-v8-tracing-agent-impl.h

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include <stdio.h>
1313

14+
#include <sstream>
15+
#include <string>
16+
#include <vector>
17+
1418
#include "libplatform/v8-tracing.h"
1519
#include "v8.h"
1620

@@ -19,42 +23,46 @@ namespace inspector {
1923

2024
using v8::platform::tracing::TraceBuffer;
2125
using v8::platform::tracing::TraceBufferChunk;
22-
using v8::platform::tracing::TraceWriter;
26+
using v8::platform::tracing::TraceConfig;
2327
using v8::platform::tracing::TraceObject;
28+
using v8::platform::tracing::TraceWriter;
2429
using v8::platform::tracing::TracingController;
25-
using v8::platform::tracing::TraceConfig;
2630

27-
class NSInMemoryTraceWriter: public TraceWriter {
28-
public:
29-
NSInMemoryTraceWriter(): stream_() {};
30-
void AppendTraceEvent(TraceObject *trace_event);
31-
void Flush();
32-
std::string getTrace();
33-
private:
34-
int total_traces_ = 0;
35-
std::stringstream stream_;
36-
std::unique_ptr<TraceWriter> json_trace_writer_;
31+
class NSInMemoryTraceWriter : public TraceWriter {
32+
public:
33+
NSInMemoryTraceWriter(std::string prefix, std::string suffix)
34+
: stream_(), prefix_(prefix), suffix_(suffix) {};
35+
void AppendTraceEvent(TraceObject* trace_event);
36+
void Flush();
37+
std::vector<std::string> getTrace();
38+
39+
private:
40+
void MaybeCreateChunk();
41+
void MaybeFinalizeChunk();
42+
int total_traces_ = 0;
43+
std::ostringstream stream_;
44+
std::unique_ptr<TraceWriter> json_trace_writer_;
45+
std::string prefix_;
46+
std::string suffix_;
47+
std::vector<std::string> traces_;
3748
};
3849

3950
class TracingAgentImpl {
40-
public:
41-
TracingAgentImpl();
42-
bool start();
43-
bool end();
44-
std::string getLastTrace() {
45-
return lastTrace_;
46-
}
47-
void SendToDevtools(v8::Local<v8::Context> context, std::string jsonData);
48-
private:
49-
bool tracing_ = false;
50-
TracingController* tracing_controller_;
51-
NSInMemoryTraceWriter* current_trace_writer_;
52-
53-
std::string lastTrace_;
54-
};
51+
public:
52+
TracingAgentImpl();
53+
bool start();
54+
bool end();
55+
const std::vector<std::string>& getLastTrace() { return lastTrace_; }
5556

56-
} // namespace inspector
57-
} // namespace tns
57+
private:
58+
bool tracing_ = false;
59+
TracingController* tracing_controller_;
60+
NSInMemoryTraceWriter* current_trace_writer_;
61+
62+
std::vector<std::string> lastTrace_;
63+
};
5864

65+
} // namespace inspector
66+
} // namespace tns
5967

6068
#endif /* ns_v8_tracing_agent_impl_hpp */

NativeScript/inspector/ns-v8-tracing-agent-impl.mm

Lines changed: 81 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -6,163 +6,114 @@
66
// Copyright © 2023. Progress. All rights reserved.
77
//
88

9-
//#include <iostream>
10-
//#include <vector>
11-
//#include <string>
9+
// #include <iostream>
10+
// #include <vector>
11+
// #include <string>
1212
#include <sstream>
1313

14-
#include "ns-v8-tracing-agent-impl.h"
15-
#include "Runtime.h"
1614
#include "Helpers.h"
15+
#include "Runtime.h"
16+
#include "ns-v8-tracing-agent-impl.h"
1717

1818
namespace tns {
1919
namespace inspector {
2020

2121
using v8::platform::tracing::TraceBuffer;
2222
using v8::platform::tracing::TraceBufferChunk;
23-
using v8::platform::tracing::TraceWriter;
24-
using v8::platform::tracing::TraceObject;
25-
using v8::platform::tracing::TracingController;
2623
using v8::platform::tracing::TraceConfig;
24+
using v8::platform::tracing::TraceObject;
2725
using v8::platform::tracing::TraceRecordMode;
26+
using v8::platform::tracing::TraceWriter;
27+
using v8::platform::tracing::TracingController;
2828

29-
void NSInMemoryTraceWriter::AppendTraceEvent(TraceObject *trace_event) {
30-
if(total_traces_ == 0) {
31-
// create a v8 JSON trace writer
32-
json_trace_writer_.reset(TraceWriter::CreateJSONTraceWriter(stream_));
33-
}
34-
35-
++total_traces_;
36-
json_trace_writer_->AppendTraceEvent(trace_event);
29+
int traces_per_chunk_ = 20;
30+
31+
void NSInMemoryTraceWriter::AppendTraceEvent(TraceObject* trace_event) {
32+
MaybeCreateChunk();
33+
34+
json_trace_writer_->AppendTraceEvent(trace_event);
35+
total_traces_++;
36+
if (total_traces_ > 0 && (total_traces_ % traces_per_chunk_ == 0)) {
37+
MaybeFinalizeChunk();
38+
}
3739
}
3840

39-
void NSInMemoryTraceWriter::Flush() {
40-
if(json_trace_writer_.get() != nullptr) {
41-
json_trace_writer_->Flush();
42-
}
41+
void NSInMemoryTraceWriter::MaybeCreateChunk() {
42+
if (json_trace_writer_.get() != nullptr) {
43+
return;
44+
}
45+
stream_.str(prefix_);
46+
stream_.seekp(0, std::ios::end);
47+
// create a v8 JSON trace writer
48+
json_trace_writer_.reset(TraceWriter::CreateJSONTraceWriter(stream_, "value"));
4349
}
4450

45-
std::string NSInMemoryTraceWriter::getTrace() {
46-
if(total_traces_ == 0) {
47-
return "";
48-
}
49-
50-
// ensures the trace json is closed
51-
json_trace_writer_.reset();
52-
std::string str = stream_.str();
53-
54-
// clear stream?
55-
stream_.str("");
56-
stream_.clear();
57-
58-
return str;
51+
void NSInMemoryTraceWriter::MaybeFinalizeChunk() {
52+
if (json_trace_writer_.get() == nullptr) {
53+
return;
54+
}
55+
json_trace_writer_.reset();
56+
stream_ << suffix_;
57+
traces_.push_back(stream_.str());
58+
stream_.str("");
59+
}
60+
61+
void NSInMemoryTraceWriter::Flush() {
62+
if (json_trace_writer_.get() != nullptr) {
63+
json_trace_writer_->Flush();
64+
}
5965
}
6066

67+
std::vector<std::string> NSInMemoryTraceWriter::getTrace() {
68+
MaybeFinalizeChunk();
69+
return std::move(traces_);
70+
}
6171

6272
TracingAgentImpl::TracingAgentImpl() {
63-
tracing_controller_ = reinterpret_cast<TracingController*>(tns::Runtime::GetPlatform()->GetTracingController());
73+
tracing_controller_ =
74+
reinterpret_cast<TracingController*>(tns::Runtime::GetPlatform()->GetTracingController());
6475
}
6576

6677
bool TracingAgentImpl::start() {
67-
if(!tracing_) {
68-
tracing_ = true;
69-
70-
// start tracing...
71-
current_trace_writer_ = new NSInMemoryTraceWriter();
72-
tracing_controller_->Initialize(
73-
TraceBuffer::CreateTraceBufferRingBuffer(
74-
TraceBuffer::kRingBufferChunks,
75-
current_trace_writer_
76-
)
77-
);
78-
// todo: create TraceConfig based on params.
79-
TraceConfig* config = TraceConfig::CreateDefaultTraceConfig();
80-
config->AddIncludedCategory("disabled-by-default-v8.cpu_profiler");
81-
config->SetTraceRecordMode(TraceRecordMode::RECORD_CONTINUOUSLY);
82-
tracing_controller_->StartTracing(config);
83-
}
84-
85-
return true;
78+
if (!tracing_) {
79+
tracing_ = true;
80+
81+
// start tracing...
82+
current_trace_writer_ =
83+
new NSInMemoryTraceWriter(R"({"method": "Tracing.dataCollected", "params":)", "}");
84+
tracing_controller_->Initialize(TraceBuffer::CreateTraceBufferRingBuffer(
85+
TraceBuffer::kRingBufferChunks, current_trace_writer_));
86+
// todo: create TraceConfig based on params.
87+
TraceConfig* config = TraceConfig::CreateDefaultTraceConfig();
88+
config->AddIncludedCategory("disabled-by-default-v8.cpu_profiler");
89+
config->SetTraceRecordMode(TraceRecordMode::RECORD_CONTINUOUSLY);
90+
tracing_controller_->StartTracing(config);
91+
}
92+
93+
return true;
8694
}
8795

8896
bool TracingAgentImpl::end() {
89-
if(tracing_) {
90-
tracing_controller_->StopTracing();
91-
92-
if(current_trace_writer_ != nullptr) {
93-
// store last trace on the agent.
94-
lastTrace_ = current_trace_writer_->getTrace();
95-
current_trace_writer_ = nullptr;
96-
}
97-
tracing_controller_->Initialize(nullptr);
98-
99-
tracing_ = false;
97+
if (tracing_) {
98+
tracing_controller_->StopTracing();
99+
100+
if (current_trace_writer_ != nullptr) {
101+
// store last trace on the agent.
102+
lastTrace_ = current_trace_writer_->getTrace();
103+
if (lastTrace_.size() > 0) {
104+
lastTrace_.push_back(
105+
R"({"method": "Tracing.tracingComplete", "params": {"dataLossOccurred": false}})");
106+
}
107+
108+
current_trace_writer_ = nullptr;
100109
}
101-
102-
return true;
103-
}
110+
tracing_controller_->Initialize(nullptr);
104111

105-
void TracingAgentImpl::SendToDevtools(v8::Local<v8::Context> context, std::string jsonData) {
106-
std::string source = R"(
107-
(() => {
108-
function processTraceData(traceJSON) {
109-
110-
try {
111-
// handle empty traces (e.g. when the user cancels the trace immediately)
112-
if(!traceJSON || traceJSON.trim().length === 0) {
113-
traceJSON = "{}";
114-
}
115-
const data = JSON.parse(traceJSON);
116-
117-
for (let i = 0; i < data.traceEvents?.length; i = i + 20) {
118-
const chunk = data.traceEvents.slice(i, i + 20);
119-
120-
__inspectorSendEvent(
121-
JSON.stringify({
122-
method: "Tracing.dataCollected",
123-
params: {
124-
value: chunk,
125-
},
126-
})
127-
);
128-
}
129-
130-
__inspectorSendEvent(
131-
JSON.stringify({
132-
method: "Tracing.tracingComplete",
133-
params: {
134-
dataLossOccurred: false,
135-
},
136-
})
137-
);
138-
} catch (err) {
139-
console.log("[Inspector] Failed to parse trace data", err, traceJSON);
140-
}
141-
}
142-
return processTraceData;
143-
})();
144-
)";
145-
146-
v8::Isolate* isolate = context->GetIsolate();
147-
v8::Locker locker(isolate);
148-
v8::Isolate::Scope isolate_scope(isolate);
149-
v8::HandleScope handle_scope(isolate);
150-
151-
v8::Local<v8::Script> script;
152-
bool success = v8::Script::Compile(context, tns::ToV8String(isolate, source)).ToLocal(&script);
153-
tns::Assert(success && !script.IsEmpty(), isolate);
154-
155-
v8::Local<v8::Value> result;
156-
success = script->Run(context).ToLocal(&result);
157-
tns::Assert(success, isolate);
158-
159-
v8::Local<v8::Function> processTraceData = result.As<v8::Function>();
160-
161-
v8::Local<v8::Value> args[1] = { tns::ToV8String(isolate, jsonData) };
162-
success = processTraceData->Call(context, processTraceData, 1, args).ToLocal(&result);
163-
tns::Assert(success, isolate);
164-
}
112+
tracing_ = false;
113+
}
165114

115+
return true;
116+
}
166117

167-
} // namespace inspector
168-
} // namespace tns
118+
} // namespace inspector
119+
} // namespace tns

0 commit comments

Comments
 (0)