Skip to content

Commit 86b47fa

Browse files
committed
speed up Unserialize_impl for prevector
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 introduce resize_uninitialized() to prevector that similar to resize() but does not call constructor, and added elements are explicitly initialized in Unserialize_imple(). The changes are as follows: 1. prevector.h Add a public member function named 'resize_uninitialized'. This function processes like as resize() but does not call constructors. So added elemensts needs explicitly initialized after this returns. 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&) Calls resize_uninitialized() instead of resize() 3. test/prevector_tests.cpp Add a test for resize_uninitialized().
1 parent b3a7153 commit 86b47fa

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
@@ -659,7 +659,7 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
659659
while (i < nSize)
660660
{
661661
unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
662-
v.resize(i + blk);
662+
v.resize_uninitialized(i + blk);
663663
is.read((char*)&v[i], blk * sizeof(T));
664664
i += blk;
665665
}
@@ -677,8 +677,8 @@ void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
677677
nMid += 5000000 / sizeof(T);
678678
if (nMid > nSize)
679679
nMid = nSize;
680-
v.resize(nMid);
681-
for (; i < nMid; i++)
680+
v.resize_uninitialized(nMid);
681+
for (; i < nMid; ++i)
682682
Unserialize(is, v[i]);
683683
}
684684
}

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)