mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
src: stop including simdjson.h from env.h
env.h includes inspector_profiler.h, which included simdjson.h for the types of two virtual methods and a parser member. As a result, about 155 files in src/ parsed the amalgamated simdjson header, which is over 10 MB. Keep simdjson out of inspector_profiler.h: the profile connections now say which field of `result` holds the profile, and WriteProfile() takes the profile as raw JSON. The parser becomes a local variable, so its buffers are no longer kept alive for the lifetime of the Environment. Also drop the unused include from node_task_runner.h, and let the config file reader rewind its document instead of parsing the whole file a second time with a second parser. Now only the eight files that use simdjson include it. On an Apple M-series machine, a clean rebuild of the src/ objects takes about 15% less CPU time (376 s to 320 s) and 19% less wall time at -j14. Signed-off-by: Daniel Lemire <daniel@lemire.me> PR-URL: https://github.com/nodejs/node/pull/66620 Refs: https://github.com/simdjson/simdjson/pull/2913 Refs: https://github.com/nodejs/node/pull/66495 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com>
This commit is contained in:
1 parent
08a7e391b1
commit
2e9d43c3b7
5 files changed
+45
-70
No files matched your search
+32
-48
@@ -13,7 +13,9 @@
|
||||
|
||||
#include <cinttypes>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include "simdjson.h"
|
||||
#include "simdutf.h"
|
||||
|
||||
namespace node {
|
||||
@@ -109,6 +111,28 @@ bool StringViewToUTF8(const v8_inspector::StringView& source,
|
||||
return *utf8_length == result_len;
|
||||
}
|
||||
|
||||
// Return the raw JSON of the profile object in `result`: either the
|
||||
// `field` member of `result` or, if `field` is nullptr, `result` itself.
|
||||
static std::optional<std::string_view> GetProfile(
|
||||
simdjson::ondemand::object* result, const char* field, const char* type) {
|
||||
simdjson::ondemand::object profile_object;
|
||||
if (field == nullptr) {
|
||||
profile_object = *result;
|
||||
} else if ((*result)[field].get_object().get(profile_object)) {
|
||||
fprintf(
|
||||
stderr, "'%s' from %s profile result is not an Object\n", field, type);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::string_view profile_raw;
|
||||
if (profile_object.raw_json().get(profile_raw)) {
|
||||
fprintf(stderr,
|
||||
"Cannot get raw string of the 'profile' field from %s profile\n",
|
||||
type);
|
||||
return std::nullopt;
|
||||
}
|
||||
return profile_raw;
|
||||
}
|
||||
|
||||
void V8ProfilerConnection::V8ProfilerSessionDelegate::SendMessageToFrontend(
|
||||
const v8_inspector::StringView& message) {
|
||||
Environment* env = connection_->env();
|
||||
@@ -134,9 +158,10 @@ void V8ProfilerConnection::V8ProfilerSessionDelegate::SendMessageToFrontend(
|
||||
return;
|
||||
}
|
||||
|
||||
simdjson::ondemand::parser json_parser;
|
||||
simdjson::ondemand::document parsed;
|
||||
simdjson::ondemand::object response;
|
||||
if (connection_->json_parser_
|
||||
if (json_parser
|
||||
.iterate(
|
||||
message_utf8.data(), message_utf8_length, message_utf8.size())
|
||||
.get(parsed) ||
|
||||
@@ -184,7 +209,10 @@ void V8ProfilerConnection::V8ProfilerSessionDelegate::SendMessageToFrontend(
|
||||
return;
|
||||
}
|
||||
|
||||
connection_->WriteProfile(&result);
|
||||
auto profile = GetProfile(&result, connection_->profile_field(), type);
|
||||
if (profile.has_value()) {
|
||||
connection_->WriteProfile(*profile);
|
||||
}
|
||||
connection_->RemoveProfileId(id);
|
||||
}
|
||||
|
||||
@@ -214,32 +242,7 @@ std::string V8CoverageConnection::GetFilename() const {
|
||||
env()->thread_id());
|
||||
}
|
||||
|
||||
std::optional<std::string_view> V8ProfilerConnection::GetProfile(
|
||||
simdjson::ondemand::object* result) {
|
||||
simdjson::ondemand::object profile_object;
|
||||
if ((*result)["profile"].get_object().get(profile_object)) {
|
||||
fprintf(
|
||||
stderr, "'profile' from %s profile result is not an Object\n", type());
|
||||
return std::nullopt;
|
||||
}
|
||||
std::string_view profile_raw;
|
||||
if (profile_object.raw_json().get(profile_raw)) {
|
||||
fprintf(stderr,
|
||||
"Cannot get raw string of the 'profile' field from %s profile\n",
|
||||
type());
|
||||
return std::nullopt;
|
||||
}
|
||||
return profile_raw;
|
||||
}
|
||||
|
||||
void V8ProfilerConnection::WriteProfile(simdjson::ondemand::object* result) {
|
||||
// Generate the profile output from the subclass.
|
||||
auto profile_opt = GetProfile(result);
|
||||
if (!profile_opt.has_value()) {
|
||||
return;
|
||||
}
|
||||
std::string_view profile = profile_opt.value();
|
||||
|
||||
void V8ProfilerConnection::WriteProfile(std::string_view profile) {
|
||||
// Create the directory if necessary.
|
||||
std::string directory = GetDirectory();
|
||||
DCHECK(!directory.empty());
|
||||
@@ -254,7 +257,7 @@ void V8ProfilerConnection::WriteProfile(simdjson::ondemand::object* result) {
|
||||
WriteResult(env_, path.c_str(), profile);
|
||||
}
|
||||
|
||||
void V8CoverageConnection::WriteProfile(simdjson::ondemand::object* result) {
|
||||
void V8CoverageConnection::WriteProfile(std::string_view profile) {
|
||||
Isolate* isolate = env_->isolate();
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
@@ -271,13 +274,6 @@ void V8CoverageConnection::WriteProfile(simdjson::ondemand::object* result) {
|
||||
Local<Context> context = env_->context();
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
// Generate the profile output from the subclass.
|
||||
auto profile_opt = GetProfile(result);
|
||||
if (!profile_opt.has_value()) {
|
||||
return;
|
||||
}
|
||||
std::string_view profile = profile_opt.value();
|
||||
|
||||
// append source-map cache information to coverage object:
|
||||
Local<Value> source_map_cache_v;
|
||||
{
|
||||
@@ -349,18 +345,6 @@ void V8CoverageConnection::WriteProfile(simdjson::ondemand::object* result) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string_view> V8CoverageConnection::GetProfile(
|
||||
simdjson::ondemand::object* result) {
|
||||
std::string_view profile_raw;
|
||||
if (result->raw_json().get(profile_raw)) {
|
||||
fprintf(stderr,
|
||||
"Cannot get raw string of the 'profile' field from %s profile\n",
|
||||
type());
|
||||
return std::nullopt;
|
||||
}
|
||||
return profile_raw;
|
||||
}
|
||||
|
||||
std::string V8CoverageConnection::GetDirectory() const {
|
||||
return env()->coverage_directory();
|
||||
}
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
#error("This header can only be used when inspector is enabled")
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include "inspector_agent.h"
|
||||
#include "simdjson.h"
|
||||
|
||||
namespace node {
|
||||
// Forward declaration to break recursive dependency chain with src/env.h.
|
||||
@@ -59,11 +58,11 @@ class V8ProfilerConnection {
|
||||
virtual std::string GetDirectory() const = 0;
|
||||
// Return the filename the profile should be written as.
|
||||
virtual std::string GetFilename() const = 0;
|
||||
// Return the profile object parsed from `message.result`,
|
||||
// which will be then written as a JSON.
|
||||
virtual std::optional<std::string_view> GetProfile(
|
||||
simdjson::ondemand::object* result);
|
||||
virtual void WriteProfile(simdjson::ondemand::object* result);
|
||||
// Return the field of `message.result` that holds the profile object,
|
||||
// or nullptr if `message.result` is itself the profile object.
|
||||
virtual const char* profile_field() const { return "profile"; }
|
||||
// Write the profile, given as raw JSON.
|
||||
virtual void WriteProfile(std::string_view profile);
|
||||
|
||||
bool HasProfileId(uint64_t id) const { return profile_ids_.contains(id); }
|
||||
|
||||
@@ -76,7 +75,6 @@ class V8ProfilerConnection {
|
||||
std::unordered_set<uint64_t> profile_ids_;
|
||||
|
||||
protected:
|
||||
simdjson::ondemand::parser json_parser_;
|
||||
Environment* env_ = nullptr;
|
||||
};
|
||||
|
||||
@@ -92,9 +90,8 @@ class V8CoverageConnection : public V8ProfilerConnection {
|
||||
|
||||
std::string GetDirectory() const override;
|
||||
std::string GetFilename() const override;
|
||||
std::optional<std::string_view> GetProfile(
|
||||
simdjson::ondemand::object* result) override;
|
||||
void WriteProfile(simdjson::ondemand::object* result) override;
|
||||
const char* profile_field() const override { return nullptr; }
|
||||
void WriteProfile(std::string_view profile) override;
|
||||
void WriteSourceMapCache();
|
||||
void TakeCoverage();
|
||||
void StopCoverage();
|
||||
|
||||
+4
-10
@@ -573,19 +573,13 @@ ParseResult ConfigReader::ParseConfig(const std::string_view& config_path) {
|
||||
return ParseResult::InvalidContent;
|
||||
}
|
||||
|
||||
simdjson::ondemand::parser config_parser;
|
||||
simdjson::ondemand::document config_document;
|
||||
if (config_parser.iterate(file_content).get(config_document)) {
|
||||
FPrintF(stderr, "Can't parse %s\n", config_path.data());
|
||||
// Walk the document again, this time to parse the configuration.
|
||||
document.rewind();
|
||||
if (document.get_object().get(main_object)) {
|
||||
return ParseResult::InvalidContent;
|
||||
}
|
||||
|
||||
simdjson::ondemand::object config_object;
|
||||
if (config_document.get_object().get(config_object)) {
|
||||
return ParseResult::InvalidContent;
|
||||
}
|
||||
|
||||
return ParseConfigObject(&config_object, config_path, true);
|
||||
return ParseConfigObject(&main_object, config_path, true);
|
||||
}
|
||||
|
||||
std::string ConfigReader::GetNodeOptions() {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "node_task_runner.h"
|
||||
#include "simdjson.h"
|
||||
#include "util-inl.h"
|
||||
|
||||
#include <regex> // NOLINT(build/c++11)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
#include "node_internals.h"
|
||||
#include "simdjson.h"
|
||||
#include "spawn_sync.h"
|
||||
#include "uv.h"
|
||||
|
||||
|
||||
Reference in new issue
Block a user