Skip to content

Commit e32bc7f

Browse files
committed
Merge bitcoin#35025: refactor: use SpanReader in deserialization benchmarks
13c8df4 refactor: replace `DataStream` with `SpanReader` in block deserialization tests (Lőrinc) 2529f25 refactor: use `SpanReader` in `PrevectorDeserialize` (Lőrinc) b8eb6c2 refactor: use `SpanReader` in `TestBlockAndIndex` (Lőrinc) 61d678a refactor: use `DataStream::clear` in `::read` and `::ignore` (Lőrinc) Pull request description: ### Problem Block deserialization benches still read immutable fixture bytes through `DataStream`, which keeps around mutable stream semantics and old compaction-oriented setup that these call sites do not need anymore. ### Fix We first remove the stale `Rewind()` parameter and failure path, which reduces rewinding to a simple reset of the read position that `clear()` can reuse. We then route fully consumed `read()` and `ignore()` paths through `clear()`, remove the leftover compaction references and dummy-byte workaround, and finally switch the block deserialization benchmark readers to `SpanReader`. `DeserializeBlockTest` can then deserialize directly from the fixture bytes without an untimed setup phase, while `CheckBlockTest` still keeps setup only to rebuild a fresh `CBlock` before the timed `CheckBlock()` call. ### Context This follows the same direction as bitcoin#34483 and is a follow-up to bitcoin#34208. The modified benchmarks retain their previous timing. ### Benchmarks The affected benchmarks speeds don't seem to be affected by the changes. <details><summary>Before & After</summary> > Before: ```bash | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 37,591,891.96 | 26.60 | 1.0% | 11.07 | `BlockToJsonVerboseWrite` | 155,664.09 | 6,424.09 | 0.1% | 10.99 | `BlockToJsonVerbosity1` | 28,620,345.39 | 34.94 | 0.1% | 10.99 | `BlockToJsonVerbosity2` | 28,637,604.74 | 34.92 | 0.1% | 11.01 | `BlockToJsonVerbosity3` | ns/block | block/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 530,167.00 | 1,886.20 | 4.7% | 0.01 | `CheckBlockTest` | 1,439,417.00 | 694.73 | 0.7% | 0.02 | `DeserializeBlockTest` | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 269.95 | 3,704,375.43 | 0.4% | 11.01 | `PrevectorDeserializeNontrivial` | 14.90 | 67,114,436.52 | 0.0% | 10.88 | `PrevectorDeserializeTrivial` ``` > After: ```bash | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 37,114,824.07 | 26.94 | 1.8% | 10.89 | `BlockToJsonVerboseWrite` | 154,881.99 | 6,456.53 | 0.2% | 10.99 | `BlockToJsonVerbosity1` | 28,546,697.37 | 35.03 | 0.2% | 10.98 | `BlockToJsonVerbosity2` | 28,547,328.27 | 35.03 | 0.3% | 11.02 | `BlockToJsonVerbosity3` | ns/block | block/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 522,750.00 | 1,912.96 | 4.7% | 0.01 | `CheckBlockTest` | 1,404,510.54 | 711.99 | 0.1% | 11.00 | `DeserializeBlockTest` | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 273.52 | 3,655,991.66 | 0.4% | 11.00 | `PrevectorDeserializeNontrivial` | 14.31 | 69,863,193.52 | 1.4% | 11.03 | `PrevectorDeserializeTrivial` ``` </details> ACKs for top commit: maflcko: review ACK 13c8df4 🐠 sedited: Re-ACK 13c8df4 Tree-SHA512: b469874908c694b6b7f45e686519bdce0c0f4da2ca56b3f7f9897c7f27bb19a787f9821466995f15414343d508f15616b24b7fd8f0fa389ade8698c8f190b669
2 parents d3a40dd + 13c8df4 commit e32bc7f

4 files changed

Lines changed: 21 additions & 51 deletions

File tree

src/bench/checkblock.cpp

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,44 @@
44

55
#include <bench/bench.h>
66
#include <bench/data/block413567.raw.h>
7-
#include <chainparams.h>
8-
#include <common/args.h>
97
#include <consensus/validation.h>
108
#include <primitives/block.h>
119
#include <primitives/transaction.h>
12-
#include <serialize.h>
13-
#include <span.h>
1410
#include <streams.h>
15-
#include <util/chaintype.h>
1611
#include <validation.h>
1712

1813
#include <cassert>
1914
#include <cstddef>
20-
#include <memory>
21-
#include <optional>
22-
#include <vector>
2315

2416
// These are the two major time-sinks which happen after we have fully received
2517
// a block off the wire, but before we can relay the block on to peers using
2618
// compact block relay.
2719

2820
static void DeserializeBlockTest(benchmark::Bench& bench)
2921
{
30-
DataStream stream;
31-
bench.unit("block").epochIterations(1)
32-
.setup([&] { stream = DataStream{benchmark::data::block413567}; })
33-
.run([&] { CBlock block; stream >> TX_WITH_WITNESS(block); });
22+
const auto block_data{benchmark::data::block413567};
23+
bench.unit("block").run([&] {
24+
CBlock block;
25+
SpanReader{block_data} >> TX_WITH_WITNESS(block);
26+
assert(block.vtx.size() == 1557);
27+
});
3428
}
3529

3630
static void CheckBlockTest(benchmark::Bench& bench)
3731
{
38-
ArgsManager bench_args;
39-
const auto chainParams = CreateChainParams(bench_args, ChainType::MAIN);
32+
const auto& chain_params{CChainParams::Main()};
33+
const auto block_data{benchmark::data::block413567};
4034

4135
CBlock block;
4236
bench.unit("block").epochIterations(1)
4337
.setup([&] {
4438
block = CBlock{};
45-
DataStream stream{benchmark::data::block413567};
46-
stream >> TX_WITH_WITNESS(block);
39+
SpanReader{block_data} >> TX_WITH_WITNESS(block);
40+
assert(block.vtx.size() == 1557);
4741
})
4842
.run([&] {
4943
BlockValidationState validationState;
50-
bool checked = CheckBlock(block, validationState, chainParams->GetConsensus());
44+
const bool checked{CheckBlock(block, validationState, chain_params->GetConsensus())};
5145
assert(checked);
5246
});
5347
}

src/bench/prevector.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,22 @@ static void PrevectorResize(benchmark::Bench& bench)
6666
template <typename T>
6767
static void PrevectorDeserialize(benchmark::Bench& bench)
6868
{
69-
DataStream s0{};
69+
DataStream data{};
7070
prevector<CScriptBase::STATIC_SIZE, T> t0;
7171
t0.resize(CScriptBase::STATIC_SIZE);
7272
for (auto x = 0; x < 900; ++x) {
73-
s0 << t0;
73+
data << t0;
7474
}
7575
t0.resize(100);
76-
for (auto x = 0; x < 101; ++x) {
77-
s0 << t0;
76+
for (auto x = 0; x < 100; ++x) {
77+
data << t0;
7878
}
7979
bench.batch(1000).run([&] {
80+
SpanReader s0{data};
8081
prevector<CScriptBase::STATIC_SIZE, T> t1;
8182
for (auto x = 0; x < 1000; ++x) {
8283
s0 >> t1;
8384
}
84-
s0.Rewind();
8585
});
8686
}
8787

src/bench/rpc_blockchain.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ struct TestBlockAndIndex {
3131

3232
TestBlockAndIndex()
3333
{
34-
DataStream stream{benchmark::data::block413567};
35-
std::byte a{0};
36-
stream.write({&a, 1}); // Prevent compaction
37-
34+
SpanReader stream{benchmark::data::block413567};
3835
stream >> TX_WITH_WITNESS(block);
3936

4037
blockHash = block.GetHash();

src/streams.h

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -206,27 +206,6 @@ class DataStream
206206
value_type* data() { return vch.data() + m_read_pos; }
207207
const value_type* data() const { return vch.data() + m_read_pos; }
208208

209-
inline void Compact()
210-
{
211-
vch.erase(vch.begin(), vch.begin() + m_read_pos);
212-
m_read_pos = 0;
213-
}
214-
215-
bool Rewind(std::optional<size_type> n = std::nullopt)
216-
{
217-
// Total rewind if no size is passed
218-
if (!n) {
219-
m_read_pos = 0;
220-
return true;
221-
}
222-
// Rewind by n characters if the buffer hasn't been compacted yet
223-
if (*n > m_read_pos)
224-
return false;
225-
m_read_pos -= *n;
226-
return true;
227-
}
228-
229-
230209
//
231210
// Stream subset
232211
//
@@ -243,8 +222,8 @@ class DataStream
243222
}
244223
memcpy(dst.data(), &vch[m_read_pos], dst.size());
245224
if (next_read_pos.value() == vch.size()) {
246-
m_read_pos = 0;
247-
vch.clear();
225+
// If fully consumed, reset to empty state.
226+
clear();
248227
return;
249228
}
250229
m_read_pos = next_read_pos.value();
@@ -258,8 +237,8 @@ class DataStream
258237
throw std::ios_base::failure("DataStream::ignore(): end of data");
259238
}
260239
if (next_read_pos.value() == vch.size()) {
261-
m_read_pos = 0;
262-
vch.clear();
240+
// If all bytes are ignored, reset to empty state.
241+
clear();
263242
return;
264243
}
265244
m_read_pos = next_read_pos.value();

0 commit comments

Comments
 (0)