From 86b47fa741408b061ab0bda784b8678bfd7dfa88 Mon Sep 17 00:00:00 2001 From: Akio Nakamura Date: Thu, 1 Feb 2018 19:34:50 +0900 Subject: 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& v, const unsigned char&) Unserialize_impl(Stream& is, prevector& v, const V&) Calls resize_uninitialized() instead of resize() 3. test/prevector_tests.cpp Add a test for resize_uninitialized(). --- src/prevector.h | 15 +++++++++++++++ src/serialize.h | 6 +++--- src/test/prevector_tests.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/prevector.h b/src/prevector.h index 99e5751634..2f368a5c66 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -378,6 +378,21 @@ public: fill(ptr, first, last); } + inline void resize_uninitialized(size_type new_size) { + // resize_uninitialized changes the size of the prevector but does not initialize it. + // If size < new_size, the added elements must be initialized explicitly. + if (capacity() < new_size) { + change_capacity(new_size); + _size += new_size - size(); + return; + } + if (new_size < size()) { + erase(item_ptr(new_size), end()); + } else { + _size += new_size - size(); + } + } + iterator erase(iterator pos) { return erase(pos, pos + 1); } diff --git a/src/serialize.h b/src/serialize.h index 2d0cfbbbf0..cb48dc174a 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -659,7 +659,7 @@ void Unserialize_impl(Stream& is, prevector& v, const unsigned char&) while (i < nSize) { unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); - v.resize(i + blk); + v.resize_uninitialized(i + blk); is.read((char*)&v[i], blk * sizeof(T)); i += blk; } @@ -677,8 +677,8 @@ void Unserialize_impl(Stream& is, prevector& v, const V&) nMid += 5000000 / sizeof(T); if (nMid > nSize) nMid = nSize; - v.resize(nMid); - for (; i < nMid; i++) + v.resize_uninitialized(nMid); + for (; i < nMid; ++i) Unserialize(is, v[i]); } } diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 7341389208..84c1abc14a 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -183,6 +183,26 @@ public: pre_vector = pre_vector_alt; } + void resize_uninitialized(realtype values) { + size_t r = values.size(); + size_t s = real_vector.size() / 2; + if (real_vector.capacity() < s + r) { + real_vector.reserve(s + r); + } + real_vector.resize(s); + pre_vector.resize_uninitialized(s); + for (auto v : values) { + real_vector.push_back(v); + } + auto p = pre_vector.size(); + pre_vector.resize_uninitialized(p + r); + for (auto v : values) { + pre_vector[p] = v; + ++p; + } + test(); + } + ~prevector_tester() { BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString()); } @@ -260,6 +280,14 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) if (InsecureRandBits(5) == 18) { test.move(); } + if (InsecureRandBits(5) == 19) { + unsigned int num = 1 + (InsecureRandBits(4)); + std::vector values(num); + for (auto &v : values) { + v = InsecureRand32(); + } + test.resize_uninitialized(values); + } } } } -- cgit v1.2.3