Skip to content

Commit 0ed61f0

Browse files
ezbrcopybara-github
authored andcommitted
Use linear search instead of binary search in flat mode of ExtensionSet.
PiperOrigin-RevId: 667651319
1 parent d4fc727 commit 0ed61f0

File tree

2 files changed

+23
-31
lines changed

2 files changed

+23
-31
lines changed

src/google/protobuf/extension_set.cc

+17-15
Original file line numberDiff line numberDiff line change
@@ -1239,9 +1239,9 @@ uint8_t* ExtensionSet::_InternalSerializeImpl(
12391239
return target;
12401240
}
12411241
const KeyValue* end = flat_end();
1242-
for (const KeyValue* it = std::lower_bound(
1243-
flat_begin(), end, start_field_number, KeyValue::FirstComparator());
1244-
it != end && it->first < end_field_number; ++it) {
1242+
const KeyValue* it = flat_begin();
1243+
while (it != end && it->first < start_field_number) ++it;
1244+
for (; it != end && it->first < end_field_number; ++it) {
12451245
target = it->second.InternalSerializeFieldWithCachedSizesToArray(
12461246
extendee, this, it->first, target, stream);
12471247
}
@@ -1566,9 +1566,11 @@ const ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) const {
15661566
if (flat_size_ == 0) {
15671567
return nullptr;
15681568
} else if (PROTOBUF_PREDICT_TRUE(!is_large())) {
1569-
auto it = std::lower_bound(flat_begin(), flat_end() - 1, key,
1570-
KeyValue::FirstComparator());
1571-
return it->first == key ? &it->second : nullptr;
1569+
for (auto it = flat_begin(), end = flat_end();
1570+
it != end && it->first <= key; ++it) {
1571+
if (it->first == key) return &it->second;
1572+
}
1573+
return nullptr;
15721574
} else {
15731575
return FindOrNullInLargeMap(key);
15741576
}
@@ -1601,10 +1603,9 @@ std::pair<ExtensionSet::Extension*, bool> ExtensionSet::Insert(int key) {
16011603
return {&maybe.first->second, maybe.second};
16021604
}
16031605
KeyValue* end = flat_end();
1604-
KeyValue* it =
1605-
std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator());
1606-
if (it != end && it->first == key) {
1607-
return {&it->second, false};
1606+
KeyValue* it = flat_begin();
1607+
for (; it != end && it->first <= key; ++it) {
1608+
if (it->first == key) return {&it->second, false};
16081609
}
16091610
if (flat_size_ < flat_capacity_) {
16101611
std::copy_backward(it, end, end + 1);
@@ -1681,11 +1682,12 @@ void ExtensionSet::Erase(int key) {
16811682
return;
16821683
}
16831684
KeyValue* end = flat_end();
1684-
KeyValue* it =
1685-
std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator());
1686-
if (it != end && it->first == key) {
1687-
std::copy(it + 1, end, it);
1688-
--flat_size_;
1685+
for (KeyValue* it = flat_begin(); it != end && it->first <= key; ++it) {
1686+
if (it->first == key) {
1687+
std::copy(it + 1, end, it);
1688+
--flat_size_;
1689+
return;
1690+
}
16891691
}
16901692
}
16911693

src/google/protobuf/extension_set.h

+6-16
Original file line numberDiff line numberDiff line change
@@ -725,27 +725,17 @@ class PROTOBUF_EXPORT ExtensionSet {
725725
const FieldDescriptor* descriptor;
726726
};
727727

728-
// The Extension struct is small enough to be passed by value, so we use it
729-
// directly as the value type in mappings rather than use pointers. We use
728+
// The Extension struct is small enough to be passed by value so we use it
729+
// directly as the value type in mappings rather than use pointers. We use
730730
// sorted maps rather than hash-maps because we expect most ExtensionSets will
731-
// only contain a small number of extension. Also, we want AppendToList and
732-
// deterministic serialization to order fields by field number.
731+
// only contain a small number of extensions, and we want AppendToList and
732+
// deterministic serialization to order fields by field number. In flat mode,
733+
// the number of elements is small enough that linear search is faster than
734+
// binary search.
733735

734736
struct KeyValue {
735737
int first;
736738
Extension second;
737-
738-
struct FirstComparator {
739-
bool operator()(const KeyValue& lhs, const KeyValue& rhs) const {
740-
return lhs.first < rhs.first;
741-
}
742-
bool operator()(const KeyValue& lhs, int key) const {
743-
return lhs.first < key;
744-
}
745-
bool operator()(int key, const KeyValue& rhs) const {
746-
return key < rhs.first;
747-
}
748-
};
749739
};
750740

751741
using LargeMap = absl::btree_map<int, Extension>;

0 commit comments

Comments
 (0)