Optimize MessageDifferencer repeated field comparison and reflection lookups.

Repeated field comparison in `MessageDifferencer` incurs significant CPU and heap allocation overhead from dynamic `std::vector` allocations per repeated field, atomic reflection synchronization in `SimpleFieldComparator`, template parsing in `StreamReporter`, and scalar element-by-element iteration across contiguous memory buffers.

Introduce a depth-indexed vector pool `match_list_pool_` to eliminate repeated heap reallocations across recursive submessage comparisons. Augment `FieldContext` to pass pre-resolved `Reflection` pointers directly to `SimpleFieldComparator::SimpleCompare`, bypassing atomic synchronization. Optimize `StreamReporter` with direct `PrintRaw` and stack-based scalar formatting, replace two-pass map key checks with single-pass `LookupMapValue`, and add fast-path contiguous buffer mismatch scanning for repeated primitive fields under default comparator settings.

PiperOrigin-RevId: 970077641
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
index 0736262..04ffe6d 100644
--- a/src/google/protobuf/util/field_comparator.cc
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -66,9 +66,15 @@
 FieldComparator::ComparisonResult SimpleFieldComparator::SimpleCompare(
     const Message& message_1, const Message& message_2,
     const FieldDescriptor* field, int index_1, int index_2,
-    const util::FieldContext* /*field_context*/) {
-  const Reflection* reflection_1 = message_1.GetReflection();
-  const Reflection* reflection_2 = message_2.GetReflection();
+    const util::FieldContext* field_context) {
+  const Reflection* reflection_1 =
+      (field_context && field_context->reflection1())
+          ? field_context->reflection1()
+          : message_1.GetReflection();
+  const Reflection* reflection_2 =
+      (field_context && field_context->reflection2())
+          ? field_context->reflection2()
+          : message_2.GetReflection();
 
   switch (field->cpp_type()) {
 #define COMPARE_FIELD(METHOD)                                                 \
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index ae685a4..058db17 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -14,9 +14,12 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
+#include <cstring>
 #include <functional>
 #include <limits>
 #include <memory>
+#include <numeric>
+#include <type_traits>
 #include <utility>
 #include <vector>
 
@@ -217,6 +220,89 @@
   }
 }
 
+// Returns true if the repeated field elements are stored contiguously in memory
+// and can be compared using fast-path contiguous memory operations (like
+// std::equal or std::memcmp). This is only supported for scalar types under the
+// default field comparator settings. 'default_field_comparator' must be
+// non-null and represents the comparator settings to check.
+bool CanUseContiguousScalarCompare(
+    const FieldDescriptor* field,
+    const DefaultFieldComparator* default_field_comparator) {
+  if (!field->is_repeated() || field->is_map()) {
+    return false;
+  }
+  if (default_field_comparator == nullptr) return false;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_BOOL:
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return true;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return default_field_comparator->float_comparison() ==
+                 SimpleFieldComparator::EXACT &&
+             !default_field_comparator->treat_nan_as_equal();
+    default:
+      return false;
+  }
+}
+
+// Helper function that dynamically dispatches the repeated field to its
+// concrete scalar type and calls the provided callable 'fn' with pointers to
+// the contiguous data buffers and their sizes. 'fn' must accept arguments:
+// (const T* data1, const T* data2, int size1, int size2) for the scalar type T.
+template <typename Fn>
+auto DispatchScalarRepeatedField(const Reflection* reflection1,
+                                 const Message& message1,
+                                 const Reflection* reflection2,
+                                 const Message& message2,
+                                 const FieldDescriptor* field, Fn&& fn) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_ENUM: {
+      const auto& r1 = reflection1->GetRepeatedField<int32_t>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<int32_t>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    case FieldDescriptor::CPPTYPE_INT64: {
+      const auto& r1 = reflection1->GetRepeatedField<int64_t>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<int64_t>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    case FieldDescriptor::CPPTYPE_UINT32: {
+      const auto& r1 = reflection1->GetRepeatedField<uint32_t>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<uint32_t>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    case FieldDescriptor::CPPTYPE_UINT64: {
+      const auto& r1 = reflection1->GetRepeatedField<uint64_t>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<uint64_t>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    case FieldDescriptor::CPPTYPE_FLOAT: {
+      const auto& r1 = reflection1->GetRepeatedField<float>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<float>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    case FieldDescriptor::CPPTYPE_DOUBLE: {
+      const auto& r1 = reflection1->GetRepeatedField<double>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<double>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    case FieldDescriptor::CPPTYPE_BOOL: {
+      const auto& r1 = reflection1->GetRepeatedField<bool>(message1, field);
+      const auto& r2 = reflection2->GetRepeatedField<bool>(message2, field);
+      return fn(r1.data(), r2.data(), r1.size(), r2.size());
+    }
+    default:
+      ABSL_LOG(FATAL) << "Unexpected cpp_type in DispatchScalarRepeatedField: "
+                      << field->cpp_type();
+  }
+}
+
 void AddSpecificIndex(
     google::protobuf::util::MessageDifferencer::SpecificField* specific_field,
     const Message& message, const FieldDescriptor* field, int index) {
@@ -1091,16 +1177,7 @@
     return false;
   }
 
-  // First pass: check whether the same keys are present.
-  for (ConstMapIterator it = reflection1->ConstMapBegin(&message1, map_field),
-                        it_end = reflection1->ConstMapEnd(&message1, map_field);
-       it != it_end; ++it) {
-    if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
-      return false;
-    }
-  }
-
-  // Second pass: compare values for matching keys.
+  // Compare values for matching keys in a single pass.
   const FieldDescriptor* val_des = map_field->message_type()->map_value();
   switch (val_des->cpp_type()) {
 #define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD)                           \
@@ -1110,7 +1187,10 @@
              it_end = reflection1->ConstMapEnd(&message1, map_field);         \
          it != it_end; ++it) {                                                \
       MapValueConstRef value2;                                                \
-      reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \
+      if (!reflection2->LookupMapValue(message2, map_field, it.GetKey(),      \
+                                       &value2)) {                            \
+        return false;                                                         \
+      }                                                                       \
       if (!comparator->Compare##COMPAREMETHOD(*val_des,                       \
                                               it.GetValueRef().Get##METHOD(), \
                                               value2.Get##METHOD())) {        \
@@ -1133,12 +1213,12 @@
       for (ConstMapIterator it =
                reflection1->ConstMapBegin(&message1, map_field);
            it != reflection1->ConstMapEnd(&message1, map_field); ++it) {
-        if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
+        MapValueConstRef value2;
+        if (!reflection2->LookupMapValue(message2, map_field, it.GetKey(),
+                                         &value2)) {
           return false;
         }
         bool compare_result;
-        MapValueConstRef value2;
-        reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2);
         // Append currently compared field to the end of parent_fields.
         SpecificField specific_value_field;
         specific_value_field.message1 = &message1;
@@ -1236,10 +1316,23 @@
     return false;
   }
 
-  // These two list are used for store the index of the correspondent
-  // element in peer repeated field.
-  std::vector<int> match_list1;
-  std::vector<int> match_list2;
+  if (static_cast<size_t>(repeated_field_depth_) >= match_list_pool_.size()) {
+    match_list_pool_.resize(repeated_field_depth_ + 1);
+  }
+  if (!match_list_pool_[repeated_field_depth_]) {
+    match_list_pool_[repeated_field_depth_] = std::make_unique<MatchListPair>();
+  }
+  MatchListPair* match_lists = match_list_pool_[repeated_field_depth_].get();
+  // These two lists are used to store the index of the corresponding
+  // element in the peer repeated field.
+  std::vector<int>& match_list1 = match_lists->match_list1;
+  std::vector<int>& match_list2 = match_lists->match_list2;
+
+  struct DepthGuard {
+    int& depth;
+    ~DepthGuard() { --depth; }
+  } depth_guard{repeated_field_depth_};
+  ++repeated_field_depth_;
 
   const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
   bool smart_list = IsTreatedAsSmartList(repeated_field);
@@ -1247,6 +1340,43 @@
                      !IsTreatedAsSet(repeated_field) &&
                      !IsTreatedAsSmartSet(repeated_field) && !smart_list;
 
+  const bool can_scalar_compare =
+      key_comparator == nullptr && field_comparator_kind_ == kFCDefault &&
+      CanUseContiguousScalarCompare(repeated_field,
+                                    field_comparator_.default_impl);
+
+  if (simple_list && can_scalar_compare) {
+    if (reporter_ == nullptr && !treated_as_subset) {
+      // count1 == count2 is already checked above.
+      return DispatchScalarRepeatedField(
+          reflection1, message1, reflection2, message2, repeated_field,
+          [](const auto* data1, const auto* data2, int count1, int count2) {
+            if (count1 == 0) return true;
+            if constexpr (std::is_same_v<std::decay_t<decltype(*data1)>,
+                                         float> ||
+                          std::is_same_v<std::decay_t<decltype(*data1)>,
+                                         double>) {
+              return std::equal(data1, data1 + count1, data2);
+            } else {
+              return std::memcmp(data1, data2, count1 * sizeof(*data1)) == 0;
+            }
+          });
+    }
+  }
+
+  int prefix_len = 0;
+  if (can_scalar_compare) {
+    DispatchScalarRepeatedField(
+        reflection1, message1, reflection2, message2, repeated_field,
+        [&](const auto* data1, const auto* data2, int count1, int count2) {
+          const int min_count = std::min(count1, count2);
+          if (min_count > 0) {
+            auto [m1, m2] = std::mismatch(data1, data1 + min_count, data2);
+            prefix_len = static_cast<int>(m1 - data1);
+          }
+        });
+  }
+
   // For simple lists, we avoid matching repeated field indices, saving the
   // memory allocations that would otherwise be needed for match_list1 and
   // match_list2.
@@ -1270,7 +1400,13 @@
   // At this point, we have already matched pairs of fields (with the reporting
   // to be done later). Now to check if the paired elements are different.
   int next_unmatched_index = 0;
-  for (int i = 0; i < count1; i++) {
+  int start_i = 0;
+  if (can_scalar_compare && !report_matches_) {
+    start_i = prefix_len;
+    next_unmatched_index = prefix_len;
+  }
+
+  for (int i = start_i; i < count1; i++) {
     if (simple_list && i >= count2) {
       break;
     }
@@ -1337,7 +1473,9 @@
   }
 
   // Report any remaining additions or deletions.
-  for (int i = 0; i < count2; ++i) {
+  const int add_start =
+      simple_list ? count1 : (can_scalar_compare ? prefix_len : 0);
+  for (int i = add_start; i < count2; ++i) {
     if (!simple_list && match_list2[i] != -1) continue;
     if (simple_list && i < count1) continue;
     if (!treated_as_subset) {
@@ -1352,7 +1490,9 @@
     parent_fields->pop_back();
   }
 
-  for (int i = 0; i < count1; ++i) {
+  const int del_start =
+      simple_list ? count2 : (can_scalar_compare ? prefix_len : 0);
+  for (int i = del_start; i < count1; ++i) {
     if (!simple_list && match_list1[i] != -1) continue;
     if (simple_list && i < count2) continue;
     assert(reporter_ != nullptr);
@@ -1378,7 +1518,9 @@
     const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* field, int index1, int index2,
     std::vector<SpecificField>* parent_fields) {
-  FieldContext field_context(parent_fields);
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+  FieldContext field_context(parent_fields, reflection1, reflection2);
   FieldComparator::ComparisonResult result = GetFieldComparisonResult(
       message1, message2, field, index1, index2, &field_context);
 
@@ -1386,8 +1528,6 @@
       result == FieldComparator::RECURSE) {
     // Get the nested messages and compare them using one of the Compare
     // methods.
-    const Reflection* reflection1 = message1.GetReflection();
-    const Reflection* reflection2 = message2.GetReflection();
     const Message& m1 =
         field->is_repeated()
             ? reflection1->GetRepeatedMessage(message1, field, index1)
@@ -1917,8 +2057,8 @@
   // which (hopefully) do not contain further repeated fields.
   if (count1 == 1 && count2 == 1 && reporter_ == nullptr &&
       key_comparator == nullptr) {
-    match_list1->at(0) = 0;
-    match_list2->at(0) = 0;
+    (*match_list1)[0] = 0;
+    (*match_list2)[0] = 0;
     return true;
   }
 
@@ -1955,16 +2095,44 @@
     success = success && (match_count == count1);
   } else {
     int start_offset = 0;
-    // If the two repeated fields are treated as sets, optimize for the case
-    // where both start with same items stored in the same order.
-    if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set ||
-        IsTreatedAsSmartList(repeated_field)) {
+    const bool is_set_or_smart = IsTreatedAsSet(repeated_field) ||
+                                 is_treated_as_smart_set ||
+                                 IsTreatedAsSmartList(repeated_field);
+    const bool can_simd = is_set_or_smart && key_comparator == nullptr &&
+                          field_comparator_kind_ == kFCDefault &&
+                          CanUseContiguousScalarCompare(
+                              repeated_field, field_comparator_.default_impl);
+
+    // If the repeated fields are contiguous scalars and we can use the default
+    // comparator, use SIMD to scan for common prefix and suffix.
+    if (can_simd) {
+      DispatchScalarRepeatedField(
+          message1.GetReflection(), message1, message2.GetReflection(),
+          message2, repeated_field,
+          [&](const auto* data1, const auto* data2, int count1, int count2) {
+            const int min_count = std::min(count1, count2);
+            int prefix_len = 0;
+            if (min_count > 0) {
+              auto [m1, m2] = std::mismatch(data1, data1 + min_count, data2);
+              prefix_len = static_cast<int>(m1 - data1);
+            }
+            if (prefix_len > 0) {
+              std::iota(match_list1->begin(), match_list1->begin() + prefix_len,
+                        0);
+              std::iota(match_list2->begin(), match_list2->begin() + prefix_len,
+                        0);
+            }
+            start_offset = prefix_len;
+          });
+      // If the two repeated fields are treated as sets, optimize for the case
+      // where both start with same items stored in the same order.
+    } else if (is_set_or_smart) {
       start_offset = std::min(count1, count2);
       for (int i = 0; i < count1 && i < count2; i++) {
         if (IsMatch(repeated_field, key_comparator, &message1, &message2,
                     unpacked_any, parent_fields, nullptr, i, i)) {
-          match_list1->at(i) = i;
-          match_list2->at(i) = i;
+          (*match_list1)[i] = i;
+          (*match_list2)[i] = i;
         } else {
           start_offset = i;
           break;
@@ -1977,9 +2145,9 @@
       int matched_j = -1;
 
       for (int j = start_offset; j < count2; j++) {
-        if (match_list2->at(j) != -1) {
+        if ((*match_list2)[j] != -1) {
           if (!is_treated_as_smart_set || num_diffs_list1[i] == 0 ||
-              num_diffs_list1[match_list2->at(j)] == 0) {
+              num_diffs_list1[(*match_list2)[j]] == 0) {
             continue;
           }
         }
@@ -2004,8 +2172,8 @@
             if (num_diffs < num_diffs_list1[i]) {
               // If j has been already matched to some element, ensure the
               // current num_diffs is smaller.
-              if (match_list2->at(j) == -1 ||
-                  num_diffs < num_diffs_list1[match_list2->at(j)]) {
+              if ((*match_list2)[j] == -1 ||
+                  num_diffs < num_diffs_list1[(*match_list2)[j]]) {
                 num_diffs_list1[i] = num_diffs;
                 match = true;
               }
@@ -2023,13 +2191,13 @@
 
       match = (matched_j != -1);
       if (match) {
-        if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) {
+        if (is_treated_as_smart_set && (*match_list2)[matched_j] != -1) {
           // This is to revert the previously matched index in list2.
-          match_list1->at(match_list2->at(matched_j)) = -1;
+          (*match_list1)[(*match_list2)[matched_j]] = -1;
           match = false;
         }
-        match_list1->at(i) = matched_j;
-        match_list2->at(matched_j) = i;
+        (*match_list1)[i] = matched_j;
+        (*match_list2)[matched_j] = i;
       }
       if (!match && reporter == nullptr) return false;
       success = success && match;
@@ -2108,15 +2276,17 @@
       }
     }
     if (i > 0) {
-      printer_->Print(".");
+      printer_->PrintRaw(".");
     }
     if (specific_field.field != nullptr) {
       if (specific_field.field->is_extension()) {
-        printer_->Print("($name$)", "name", specific_field.field->full_name());
+        printer_->PrintRaw("(");
+        printer_->PrintRaw(specific_field.field->full_name());
+        printer_->PrintRaw(")");
       } else {
         printer_->PrintRaw(specific_field.field->name());
         if (specific_field.forced_compare_no_presence_) {
-          printer_->Print(" (added for better PARTIAL comparison)");
+          printer_->PrintRaw(" (added for better PARTIAL comparison)");
         }
       }
 
@@ -2125,14 +2295,18 @@
         continue;
       }
     } else {
-      printer_->PrintRaw(absl::StrCat(specific_field.unknown_field_number));
+      printer_->PrintRaw(
+          absl::AlphaNum(specific_field.unknown_field_number).Piece());
     }
     if (left_side && specific_field.index >= 0) {
-      printer_->Print("[$name$]", "name", absl::StrCat(specific_field.index));
+      printer_->PrintRaw("[");
+      printer_->PrintRaw(absl::AlphaNum(specific_field.index).Piece());
+      printer_->PrintRaw("]");
     }
     if (!left_side && specific_field.new_index >= 0) {
-      printer_->Print("[$name$]", "name",
-                      absl::StrCat(specific_field.new_index));
+      printer_->PrintRaw("[");
+      printer_->PrintRaw(absl::AlphaNum(specific_field.new_index).Piece());
+      printer_->PrintRaw("]");
     }
   }
 }
@@ -2143,10 +2317,67 @@
   const SpecificField& specific_field = field_path.back();
   const FieldDescriptor* field = specific_field.field;
   if (field != nullptr) {
-    std::string output;
     int index = left_side ? specific_field.index : specific_field.new_index;
+    const Reflection* reflection = message.GetReflection();
+    switch (field->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_INT32: {
+        int32_t val = field->is_repeated()
+                          ? reflection->GetRepeatedInt32(message, field, index)
+                          : reflection->GetInt32(message, field);
+        printer_->PrintRaw(absl::AlphaNum(val).Piece());
+        return;
+      }
+      case FieldDescriptor::CPPTYPE_INT64: {
+        int64_t val = field->is_repeated()
+                          ? reflection->GetRepeatedInt64(message, field, index)
+                          : reflection->GetInt64(message, field);
+        printer_->PrintRaw(absl::AlphaNum(val).Piece());
+        return;
+      }
+      case FieldDescriptor::CPPTYPE_UINT32: {
+        uint32_t val =
+            field->is_repeated()
+                ? reflection->GetRepeatedUInt32(message, field, index)
+                : reflection->GetUInt32(message, field);
+        printer_->PrintRaw(absl::AlphaNum(val).Piece());
+        return;
+      }
+      case FieldDescriptor::CPPTYPE_UINT64: {
+        uint64_t val =
+            field->is_repeated()
+                ? reflection->GetRepeatedUInt64(message, field, index)
+                : reflection->GetUInt64(message, field);
+        printer_->PrintRaw(absl::AlphaNum(val).Piece());
+        return;
+      }
+      case FieldDescriptor::CPPTYPE_BOOL: {
+        bool val = field->is_repeated()
+                       ? reflection->GetRepeatedBool(message, field, index)
+                       : reflection->GetBool(message, field);
+        printer_->PrintRaw(val ? "true" : "false");
+        return;
+      }
+      case FieldDescriptor::CPPTYPE_ENUM: {
+        const EnumValueDescriptor* enum_desc =
+            field->is_repeated()
+                ? reflection->GetRepeatedEnum(message, field, index)
+                : reflection->GetEnum(message, field);
+        if (enum_desc != nullptr) {
+          printer_->PrintRaw(enum_desc->name());
+        } else {
+          int val =
+              field->is_repeated()
+                  ? reflection->GetRepeatedEnumValue(message, field, index)
+                  : reflection->GetEnumValue(message, field);
+          printer_->PrintRaw(absl::AlphaNum(val).Piece());
+        }
+        return;
+      }
+      default:
+        break;
+    }
+    std::string output;
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      const Reflection* reflection = message.GetReflection();
       const Message& field_message =
           field->is_repeated()
               ? reflection->GetRepeatedMessage(message, field, index)
@@ -2165,13 +2396,15 @@
         output = PrintShortTextFormat(field_message);
       }
       if (output.empty()) {
-        printer_->Print("{ }");
+        printer_->PrintRaw("{ }");
       } else {
         if ((fd != nullptr) &&
             (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
           printer_->PrintRaw(output);
         } else {
-          printer_->Print("{ $name$ }", "name", output);
+          printer_->PrintRaw("{ ");
+          printer_->PrintRaw(output);
+          printer_->PrintRaw(" }");
         }
       }
     } else {
@@ -2257,21 +2490,21 @@
 void MessageDifferencer::StreamReporter::ReportAdded(
     const Message& /*message1*/, const Message& message2,
     const std::vector<SpecificField>& field_path) {
-  printer_->Print("added: ");
+  printer_->PrintRaw("added: ");
   PrintPath(field_path, false);
-  printer_->Print(": ");
+  printer_->PrintRaw(": ");
   PrintValue(message2, field_path, false);
-  printer_->Print("\n");  // Print for newlines.
+  printer_->PrintRaw("\n");  // Print for newlines.
 }
 
 void MessageDifferencer::StreamReporter::ReportDeleted(
     const Message& message1, const Message& /*message2*/,
     const std::vector<SpecificField>& field_path) {
-  printer_->Print("deleted: ");
+  printer_->PrintRaw("deleted: ");
   PrintPath(field_path, true);
-  printer_->Print(": ");
+  printer_->PrintRaw(": ");
   PrintValue(message1, field_path, true);
-  printer_->Print("\n");  // Print for newlines
+  printer_->PrintRaw("\n");  // Print for newlines
 }
 
 void MessageDifferencer::StreamReporter::ReportModified(
@@ -2290,55 +2523,55 @@
     }
   }
 
-  printer_->Print("modified: ");
+  printer_->PrintRaw("modified: ");
   PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
-    printer_->Print(" -> ");
+    printer_->PrintRaw(" -> ");
     PrintPath(field_path, false);
   }
-  printer_->Print(": ");
+  printer_->PrintRaw(": ");
   PrintValue(message1, field_path, true);
-  printer_->Print(" -> ");
+  printer_->PrintRaw(" -> ");
   PrintValue(message2, field_path, false);
-  printer_->Print("\n");  // Print for newlines.
+  printer_->PrintRaw("\n");  // Print for newlines.
 }
 
 void MessageDifferencer::StreamReporter::ReportMoved(
     const Message& message1, const Message& /*message2*/,
     const std::vector<SpecificField>& field_path) {
-  printer_->Print("moved: ");
+  printer_->PrintRaw("moved: ");
   PrintPath(field_path, true);
-  printer_->Print(" -> ");
+  printer_->PrintRaw(" -> ");
   PrintPath(field_path, false);
-  printer_->Print(" : ");
+  printer_->PrintRaw(" : ");
   PrintValue(message1, field_path, true);
-  printer_->Print("\n");  // Print for newlines.
+  printer_->PrintRaw("\n");  // Print for newlines.
 }
 
 void MessageDifferencer::StreamReporter::ReportMatched(
     const Message& message1, const Message& /*message2*/,
     const std::vector<SpecificField>& field_path) {
-  printer_->Print("matched: ");
+  printer_->PrintRaw("matched: ");
   PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
-    printer_->Print(" -> ");
+    printer_->PrintRaw(" -> ");
     PrintPath(field_path, false);
   }
-  printer_->Print(" : ");
+  printer_->PrintRaw(" : ");
   PrintValue(message1, field_path, true);
-  printer_->Print("\n");  // Print for newlines.
+  printer_->PrintRaw("\n");  // Print for newlines.
 }
 
 void MessageDifferencer::StreamReporter::ReportIgnored(
     const Message& /*message1*/, const Message& /*message2*/,
     const std::vector<SpecificField>& field_path) {
-  printer_->Print("ignored: ");
+  printer_->PrintRaw("ignored: ");
   PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
-    printer_->Print(" -> ");
+    printer_->PrintRaw(" -> ");
     PrintPath(field_path, false);
   }
-  printer_->Print("\n");  // Print for newlines.
+  printer_->PrintRaw("\n");  // Print for newlines.
 }
 
 void MessageDifferencer::StreamReporter::SetMessages(const Message& message1,
@@ -2350,13 +2583,13 @@
 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
     const Message& /*message1*/, const Message& /*message2*/,
     const std::vector<SpecificField>& field_path) {
-  printer_->Print("ignored: ");
+  printer_->PrintRaw("ignored: ");
   PrintPath(field_path, true);
   if (CheckPathChanged(field_path)) {
-    printer_->Print(" -> ");
+    printer_->PrintRaw(" -> ");
     PrintPath(field_path, false);
   }
-  printer_->Print("\n");  // Print for newlines.
+  printer_->PrintRaw("\n");  // Print for newlines.
 }
 
 MessageDifferencer::MapKeyComparator*
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index d3f0b80..5b83647 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -975,6 +975,19 @@
       match_indices_for_smart_list_callback_;
 
   MessageDifferencer::UnpackAnyField unpack_any_field_;
+
+  // Holds the indices of matching elements for a repeated field comparison at
+  // a particular recursion depth.
+  struct MatchListPair {
+    std::vector<int> match_list1;
+    std::vector<int> match_list2;
+  };
+  // A pool of MatchListPair objects used to avoid reallocating match lists
+  // during recursive submessage comparisons. Indexed by repeated field depth.
+  std::vector<std::unique_ptr<MatchListPair>> match_list_pool_;
+  // The current depth of repeated field comparison recursion. Used to index
+  // into match_list_pool_.
+  int repeated_field_depth_ = 0;
 };
 
 // This class provides extra information to the FieldComparator::Compare
@@ -982,15 +995,27 @@
 class PROTOBUF_EXPORT FieldContext {
  public:
   explicit FieldContext(
-      std::vector<MessageDifferencer::SpecificField>* parent_fields)
-      : parent_fields_(parent_fields) {}
+      std::vector<MessageDifferencer::SpecificField>* parent_fields,
+      const Reflection* reflection1 = nullptr,
+      const Reflection* reflection2 = nullptr)
+      : parent_fields_(parent_fields),
+        reflection1_(reflection1),
+        reflection2_(reflection2) {}
 
   std::vector<MessageDifferencer::SpecificField>* parent_fields() const {
     return parent_fields_;
   }
+  const Reflection* reflection1() const { return reflection1_; }
+  const Reflection* reflection2() const { return reflection2_; }
 
  private:
   std::vector<MessageDifferencer::SpecificField>* parent_fields_;
+  // Pre-resolved Reflection pointer for message1, used to avoid redundant
+  // reflection lookups during comparison.
+  const Reflection* reflection1_;
+  // Pre-resolved Reflection pointer for message2, used to avoid redundant
+  // reflection lookups during comparison.
+  const Reflection* reflection2_;
 };
 
 }  // namespace util