Skip to content

Commit 8777a80

Browse files
committed
Merge #12324: speed up Unserialize_impl for prevector
86b47fa speed up Unserialize_impl for prevector (Akio Nakamura) Pull request description: The unserializer for prevector uses `resize()` for reserve the area, but it's prefer to use `reserve()` because `resize()` have overhead to call its constructor many times. However, `reserve()` does not change the value of `_size` (a private member of prevector). This PR make the logic of read from stream to callback function, and prevector handles initilizing new values with that call-back and ajust the value of `_size`. The changes are as follows: 1. prevector.h Add a public member function named 'append'. This function has 2 params, number of elemenst to append and call-back function that initilizing new appended values. 2. serialize.h In the following two function: - `Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)` - `Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)` Make a callback function from each original logic of reading values from stream, and call prevector's `append()`. 3. test/prevector_tests.cpp Add a test for `append()`. ## A benchmark result is following: [Machine] MacBook Pro (macOS 10.13.3/i7 2.2GHz/mem 16GB/SSD) [result] DeserializeAndCheckBlockTest => 22% faster DeserializeBlockTest => 29% faster [before PR] # Benchmark, evals, iterations, total, min, max, median DeserializeAndCheckBlockTest, 60, 160, 94.4901, 0.0094644, 0.0104715, 0.0098339 DeserializeBlockTest, 60, 130, 65.0964, 0.00800362, 0.00895134, 0.00824187 [After PR] # Benchmark, evals, iterations, total, min, max, median DeserializeAndCheckBlockTest, 60, 160, 77.1597, 0.00767013, 0.00858959, 0.00805757 DeserializeBlockTest, 60, 130, 49.9443, 0.00613926, 0.00691187, 0.00635527 ACKs for top commit: laanwj: utACK 86b47fa Tree-SHA512: 62ea121ccd45a306fefc67485a1b03a853435af762607dae2426a87b15a3033d802c8556e1923727ddd1023a1837d0e5f6720c2c77b38196907e750e15fbb902
2 parents e2182b0 + 86b47fa commit 8777a80

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

src/prevector.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,21 @@ class prevector {
378378
fill(ptr, first, last);
379379
}
380380

381+
inline void resize_uninitialized(size_type new_size) {
382+
// resize_uninitialized changes the size of the prevector but does not initialize it.
383+
// If size < new_size, the added elements must be initialized explicitly.
384+
if (capacity() < new_size) {
385+
change_capacity(new_size);
386+
_size += new_size - size();
387+
return;
388+
}
389+
if (new_size < size()) {
390+
erase(item_ptr(new_size), end());
391+
} else {
392+
_size += new_size - size();
393+
}
394+
}
395+
381396
iterator erase(iterator pos) {
382397
return erase(pos, pos + 1);
383398
}

src/serialize.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
670670
while (i < nSize)
671671
{
672672
unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
673-
v.resize(i + blk);
673+
v.resize_uninitialized(i + blk);
674674
is.read((char*)&v[i], blk * sizeof(T));
675675
i += blk;
676676
}
@@ -688,8 +688,8 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
688688
nMid += 5000000 / sizeof(T);
689689
if (nMid > nSize)
690690
nMid = nSize;
691-
v.resize(nMid);
692-
for (; i < nMid; i++)
691+
v.resize_uninitialized(nMid);
692+
for (; i < nMid; ++i)
693693
Unserialize(is, v[i]);
694694
}
695695
}

src/test/prevector_tests.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,26 @@ class prevector_tester {
183183
pre_vector = pre_vector_alt;
184184
}
185185

186+
void resize_uninitialized(realtype values) {
187+
size_t r = values.size();
188+
size_t s = real_vector.size() / 2;
189+
if (real_vector.capacity() < s + r) {
190+
real_vector.reserve(s + r);
191+
}
192+
real_vector.resize(s);
193+
pre_vector.resize_uninitialized(s);
194+
for (auto v : values) {
195+
real_vector.push_back(v);
196+
}
197+
auto p = pre_vector.size();
198+
pre_vector.resize_uninitialized(p + r);
199+
for (auto v : values) {
200+
pre_vector[p] = v;
201+
++p;
202+
}
203+
test();
204+
}
205+
186206
~prevector_tester() {
187207
BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString());
188208
}
@@ -260,6 +280,14 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt)
260280
if (InsecureRandBits(5) == 18) {
261281
test.move();
262282
}
283+
if (InsecureRandBits(5) == 19) {
284+
unsigned int num = 1 + (InsecureRandBits(4));
285+
std::vector<int> values(num);
286+
for (auto &v : values) {
287+
v = InsecureRand32();
288+
}
289+
test.resize_uninitialized(values);
290+
}
263291
}
264292
}
265293
}

0 commit comments

Comments
 (0)