From e4a4d863ab23066ccbd36f22f41119a524fad45e Mon Sep 17 00:00:00 2001 From: Advit Arora Date: Mon, 24 Aug 2026 20:43:20 +0530 Subject: [PATCH 1/3] GH-48977: [C++] Add a schema construction benchmark --- cpp/src/arrow/type_benchmark.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cpp/src/arrow/type_benchmark.cc b/cpp/src/arrow/type_benchmark.cc index f502c4b7c860..6544e3e4f990 100644 --- a/cpp/src/arrow/type_benchmark.cc +++ b/cpp/src/arrow/type_benchmark.cc @@ -170,6 +170,20 @@ static void SchemaEqualsWithMetadata( state.SetItemsProcessed(state.iterations() * 2); } +static void SchemaConstruct(benchmark::State& state, // NOLINT non-const reference + bool duplicate_names) { + const int num_fields = static_cast(state.range(0)); + FieldVector fields(num_fields); + for (int i = 0; i < num_fields; ++i) { + fields[i] = field(duplicate_names ? "f" : "f" + std::to_string(i), int32()); + } + + for (auto _ : state) { + benchmark::DoNotOptimize(::arrow::schema(fields)); + } + state.SetItemsProcessed(state.iterations() * num_fields); +} + // ------------------------------------------------------------------------ // Micro-benchmark various error reporting schemes @@ -541,6 +555,14 @@ BENCHMARK(TypeEqualsComplex); BENCHMARK(TypeEqualsWithMetadata); BENCHMARK(SchemaEquals); BENCHMARK(SchemaEqualsWithMetadata); +BENCHMARK_CAPTURE(SchemaConstruct, distinct_names, /*duplicate_names=*/false) + ->Arg(100) + ->Arg(1000) + ->Arg(10000); +BENCHMARK_CAPTURE(SchemaConstruct, duplicate_names, /*duplicate_names=*/true) + ->Arg(100) + ->Arg(1000) + ->Arg(10000); BENCHMARK(ErrorSchemeNoError); BENCHMARK(ErrorSchemeBool); From 123aab5ba887ef03cbb372e19359977a828656a5 Mon Sep 17 00:00:00 2001 From: Advit Arora Date: Mon, 24 Aug 2026 20:43:20 +0530 Subject: [PATCH 2/3] GH-48977: [C++] Fix quadratic field name index construction on libc++ --- cpp/src/arrow/type.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/type.cc b/cpp/src/arrow/type.cc index 1dedf1978dab..1de3f7ae7f9d 100644 --- a/cpp/src/arrow/type.cc +++ b/cpp/src/arrow/type.cc @@ -1333,8 +1333,10 @@ namespace { std::unordered_multimap CreateNameToIndexMap( const FieldVector& fields) { std::unordered_multimap name_to_index; + name_to_index.reserve(fields.size()); for (size_t i = 0; i < fields.size(); ++i) { - name_to_index.emplace(fields[i]->name(), static_cast(i)); + const std::string_view name = fields[i]->name(); + name_to_index.emplace_hint(name_to_index.find(name), name, static_cast(i)); } return name_to_index; } @@ -2294,7 +2296,7 @@ Schema::Schema(FieldVector fields, std::shared_ptr metad impl_(new Impl(std::move(fields), Endianness::Native, std::move(metadata))) {} Schema::Schema(const Schema& schema) - : detail::Fingerprintable(), impl_(new Impl(*schema.impl_)) {} + : Schema(schema.impl_->fields_, schema.impl_->endianness_, schema.impl_->metadata_) {} Schema::~Schema() = default; @@ -2568,7 +2570,9 @@ class SchemaBuilder::Impl { } Status AppendField(const std::shared_ptr& field) { - name_to_index_.emplace(field->name(), static_cast(fields_.size())); + const std::string_view name = field->name(); + name_to_index_.emplace_hint(name_to_index_.find(name), name, + static_cast(fields_.size())); fields_.push_back(field); return Status::OK(); } From 4cacc16929928103bb881859fdbd24571e5a7998 Mon Sep 17 00:00:00 2001 From: Advit Arora Date: Tue, 25 Aug 2026 10:15:16 +0530 Subject: [PATCH 3/3] GH-48977: [C++] Comment the hinted-insert motivation --- cpp/src/arrow/type.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/arrow/type.cc b/cpp/src/arrow/type.cc index 1de3f7ae7f9d..e841f0918097 100644 --- a/cpp/src/arrow/type.cc +++ b/cpp/src/arrow/type.cc @@ -1336,6 +1336,7 @@ std::unordered_multimap CreateNameToIndexMap( name_to_index.reserve(fields.size()); for (size_t i = 0; i < fields.size(); ++i) { const std::string_view name = fields[i]->name(); + // The find() hint avoids libc++'s quadratic scan of equal keys on plain emplace. name_to_index.emplace_hint(name_to_index.find(name), name, static_cast(i)); } return name_to_index;