Skip to content

Commit

Permalink
Merge #2148: [Core] Prevector Optimizations 2
Browse files Browse the repository at this point in the history
b886a4c Fix header guards using reserved identifiers (Dan Raviv)
b389b3f speed up Unserialize_impl for prevector (Akio Nakamura)
13d2102 Minimal fix to slow prevector tests as stopgap measure (Jeremy Rubin)

Pull request description:

  Backports bitcoin#12324.
  The `DeserializeAndCheckBlock` benchmark (introduced in #2146) shows a speedup of about 4% (not as much as the upstream PR, due to the optimizations already included in #2083).

  Cherry-picks also
  - bitcoin#8671 (with minimal changes to the random context, due to bitcoin#8914 and bitcoin#9792 being already ported out of order).
  - bitcoin#11151

ACKs for top commit:
  Fuzzbawls:
    utACK b886a4c
  furszy:
    utACK b886a4c and merging..

Tree-SHA512: f5de40e5acfb0b875d413d8995d71dd90489730fe4853f0be03d76a1c44ec95eaeb28c0c40d8e91906f23529ad26501bda4f9779ce466cd8603ed97f1662ca98
  • Loading branch information
furszy committed Jan 25, 2021
2 parents 8ac7333 + b886a4c commit 07b88da
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 26 deletions.
6 changes: 3 additions & 3 deletions src/cuckoocache.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef _BITCOIN_CUCKOOCACHE_H_
#define _BITCOIN_CUCKOOCACHE_H_
#ifndef BITCOIN_CUCKOOCACHE_H
#define BITCOIN_CUCKOOCACHE_H

#include <array>
#include <algorithm>
Expand Down Expand Up @@ -454,4 +454,4 @@ class cache
};
} // namespace CuckooCache

#endif
#endif // BITCOIN_CUCKOOCACHE_H
21 changes: 18 additions & 3 deletions src/prevector.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef _BITCOIN_PREVECTOR_H_
#define _BITCOIN_PREVECTOR_H_
#ifndef BITCOIN_PREVECTOR_H
#define BITCOIN_PREVECTOR_H

#include <assert.h>
#include <stdlib.h>
Expand Down Expand Up @@ -381,6 +381,21 @@ class prevector {
}
}

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);
}
Expand Down Expand Up @@ -513,4 +528,4 @@ class prevector {
};
#pragma pack(pop)

#endif
#endif // BITCOIN_PREVECTOR_H
6 changes: 3 additions & 3 deletions src/serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ void Unserialize_impl(Stream& is, prevector<N, T>& 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;
}
Expand All @@ -821,8 +821,8 @@ void Unserialize_impl(Stream& is, prevector<N, T>& 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]);
}
}
Expand Down
84 changes: 67 additions & 17 deletions src/test/prevector_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,66 @@ class prevector_tester {
pretype pre_vector_alt;

typedef typename pretype::size_type Size;
bool passed = true;
FastRandomContext rand_cache;
uint256 rand_seed;

template <typename A, typename B>
void local_check_equal(A a, B b)
{
local_check(a == b);
}
void local_check(bool b)
{
passed &= b;
}
void test() {
const pretype& const_pre_vector = pre_vector;
BOOST_CHECK_EQUAL(real_vector.size(), pre_vector.size());
BOOST_CHECK_EQUAL(real_vector.empty(), pre_vector.empty());
local_check_equal(real_vector.size(), pre_vector.size());
local_check_equal(real_vector.empty(), pre_vector.empty());
for (Size s = 0; s < real_vector.size(); s++) {
BOOST_CHECK(real_vector[s] == pre_vector[s]);
BOOST_CHECK(&(pre_vector[s]) == &(pre_vector.begin()[s]));
BOOST_CHECK(&(pre_vector[s]) == &*(pre_vector.begin() + s));
BOOST_CHECK(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
local_check(real_vector[s] == pre_vector[s]);
local_check(&(pre_vector[s]) == &(pre_vector.begin()[s]));
local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s));
local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
}
// BOOST_CHECK(realtype(pre_vector) == real_vector);
BOOST_CHECK(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
BOOST_CHECK(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
// local_check(realtype(pre_vector) == real_vector);
local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
size_t pos = 0;

for (const T& v : pre_vector) {
BOOST_CHECK(v == real_vector[pos++]);
local_check(v == real_vector[pos++]);
}
pos = 0;
for (const T& v : const_pre_vector) {
BOOST_CHECK(v == real_vector[pos++]);
local_check(v == real_vector[pos++]);
}

CDataStream ss1(SER_DISK, 0);
CDataStream ss2(SER_DISK, 0);
ss1 << real_vector;
ss2 << pre_vector;
BOOST_CHECK_EQUAL(ss1.size(), ss2.size());
local_check_equal(ss1.size(), ss2.size());
for (Size s = 0; s < ss1.size(); s++) {
BOOST_CHECK_EQUAL(ss1[s], ss2[s]);
local_check_equal(ss1[s], ss2[s]);
}
}

public:
void resize(Size s) {
real_vector.resize(s);
BOOST_CHECK_EQUAL(real_vector.size(), s);
local_check_equal(real_vector.size(), s);
pre_vector.resize(s);
BOOST_CHECK_EQUAL(pre_vector.size(), s);
local_check_equal(pre_vector.size(), s);
test();
}

void reserve(Size s) {
real_vector.reserve(s);
BOOST_CHECK(real_vector.capacity() >= s);
local_check(real_vector.capacity() >= s);
pre_vector.reserve(s);
BOOST_CHECK(pre_vector.capacity() >= s);
local_check(pre_vector.capacity() >= s);
test();
}

Expand Down Expand Up @@ -165,6 +178,35 @@ class prevector_tester {
real_vector = real_vector_alt;
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());
}
prevector_tester() {
SeedInsecureRand();
rand_seed = InsecureRand256();
rand_cache = FastRandomContext(rand_seed);
}
};

BOOST_AUTO_TEST_CASE(PrevectorTestInt)
Expand Down Expand Up @@ -235,6 +277,14 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt)
if (((r >> 15) % 32) == 18) {
test.move();
}
if (InsecureRandBits(5) == 19) {
unsigned int num = 1 + (InsecureRandBits(4));
std::vector<int> values(num);
for (auto &v : values) {
v = InsecureRand32();
}
test.resize_uninitialized(values);
}
}
}
}
Expand Down

0 comments on commit 07b88da

Please sign in to comment.