Commit 2e9d43c3b70 for nodejs

commit 2e9d43c3b708118d3998ad29ec6370f6c7487ca2
Author: Daniel Lemire <daniel@lemire.me>
Date:   Tue Oct 6 17:11:53 2026 -0400

    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>

diff --git a/src/inspector_profiler.cc b/src/inspector_profiler.cc
index 559b4fd27d5..791ff993f84 100644
--- a/src/inspector_profiler.cc
+++ b/src/inspector_profiler.cc
@@ -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();
 }
diff --git a/src/inspector_profiler.h b/src/inspector_profiler.h
index d07334c818d..cdd6bcf6f0a 100644
--- a/src/inspector_profiler.h
+++ b/src/inspector_profiler.h
@@ -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();
diff --git a/src/node_config_file.cc b/src/node_config_file.cc
index b4d23325e9f..373067fc41d 100644
--- a/src/node_config_file.cc
+++ b/src/node_config_file.cc
@@ -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());
-    return ParseResult::InvalidContent;
-  }
-
-  simdjson::ondemand::object config_object;
-  if (config_document.get_object().get(config_object)) {
+  // Walk the document again, this time to parse the configuration.
+  document.rewind();
+  if (document.get_object().get(main_object)) {
     return ParseResult::InvalidContent;
   }

-  return ParseConfigObject(&config_object, config_path, true);
+  return ParseConfigObject(&main_object, config_path, true);
 }

 std::string ConfigReader::GetNodeOptions() {
diff --git a/src/node_task_runner.cc b/src/node_task_runner.cc
index 55f348afc69..136dec24fa0 100644
--- a/src/node_task_runner.cc
+++ b/src/node_task_runner.cc
@@ -1,4 +1,5 @@
 #include "node_task_runner.h"
+#include "simdjson.h"
 #include "util-inl.h"

 #include <regex>  // NOLINT(build/c++11)
diff --git a/src/node_task_runner.h b/src/node_task_runner.h
index 15573498f73..8cdfe572353 100644
--- a/src/node_task_runner.h
+++ b/src/node_task_runner.h
@@ -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"