Skip to content

Commit eba880f

Browse files
authored
snapshots: optimize BodyTxsAmountQuery using skip (#2045)
1 parent 9df2b16 commit eba880f

File tree

5 files changed

+74
-20
lines changed

5 files changed

+74
-20
lines changed

silkworm/db/snapshots/body_txs_amount_query.cpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,20 @@
2323
namespace silkworm::snapshots {
2424

2525
BodyTxsAmountQuery::Result BodyTxsAmountQuery::exec() {
26-
auto path = snapshot_.path();
27-
uint64_t first_tx_id{0}, last_tx_id{0}, last_txs_amount{0};
28-
BlockNum number = path.block_from();
26+
size_t body_count = snapshot_.item_count();
27+
if (body_count == 0) {
28+
throw std::runtime_error("BodyTxsAmountQuery empty body snapshot: " + snapshot_.path().path().string());
29+
}
2930

3031
BodySnapshotReader reader{snapshot_};
31-
for (auto& body : reader) {
32-
if (number == path.block_from()) {
33-
first_tx_id = body.base_txn_id;
34-
}
35-
if (number >= path.block_to() - 1) {
36-
last_tx_id = body.base_txn_id;
37-
last_txs_amount = body.txn_count;
38-
}
39-
number++;
40-
}
32+
auto it = reader.begin();
33+
uint64_t first_tx_id = it->base_txn_id;
4134

42-
if ((first_tx_id == 0) && (last_tx_id == 0)) {
43-
throw std::runtime_error("BodyTxsAmountQuery empty body snapshot: " + path.path().string());
44-
}
35+
it += body_count - 1;
36+
auto& last_body = *it;
4537

46-
uint64_t count = last_tx_id + last_txs_amount - first_tx_id;
38+
uint64_t end_tx_id = last_body.base_txn_id + last_body.txn_count;
39+
uint64_t count = end_tx_id - first_tx_id;
4740

4841
return Result{
4942
first_tx_id,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright 2024 The Silkworm Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#include "body_txs_amount_query.hpp"
18+
19+
#include <catch2/catch.hpp>
20+
21+
#include <silkworm/db/snapshots/test_util/common.hpp>
22+
#include <silkworm/infra/common/directories.hpp>
23+
#include <silkworm/infra/common/log.hpp>
24+
#include <silkworm/infra/test_util/log.hpp>
25+
26+
namespace silkworm::snapshots {
27+
28+
TEST_CASE("BodyTxsAmountQuery") {
29+
silkworm::test_util::SetLogVerbosityGuard guard{log::Level::kNone};
30+
TemporaryDirectory tmp_dir;
31+
test_util::SampleBodySnapshotFile snapshot_file{tmp_dir.path()};
32+
test_util::SampleBodySnapshotPath snapshot_path{snapshot_file.path()};
33+
Snapshot snapshot{snapshot_path};
34+
snapshot.reopen_segment();
35+
36+
BodyTxsAmountQuery query{snapshot};
37+
auto result = query.exec();
38+
39+
CHECK(result.first_tx_id == 7'341'262);
40+
CHECK(result.count == 12);
41+
}
42+
43+
} // namespace silkworm::snapshots

silkworm/db/snapshots/index_builder_test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ TEST_CASE("TransactionIndex::build KO: invalid snapshot", "[silkworm][snapshot][
7979
tmp_dir.path(),
8080
"v1-015000-015500-bodies.seg",
8181
test::SnapshotHeader{
82-
.words_count = 0,
82+
.words_count = 7,
8383
.empty_words_count = 0,
8484
.patterns = {},
8585
.positions = {}},
@@ -147,9 +147,9 @@ TEST_CASE("TransactionIndex::build KO: invalid snapshot", "[silkworm][snapshot][
147147
tmp_dir.path(),
148148
"000000000000000e000000000000000000000000000000000000000000000004"
149149
"0100010801c6837004d980c001c6837004d980c001c6837004d980c001c68370"
150-
"04d980c001c6837004d980c001c6837004d980c001c6837004d980c001c78370" // {01, c7837004d980c0} <- c7 instead of c6
151150
"04d980c001c6837004d980c001c6837004d980c001c6837004d980c001c68370"
152-
"04d980c001c6837004d980c001c6837004d901c0"};
151+
"04d980c001c6837004d980c001c6837004d980c001c6837004d980c001c68370"
152+
"04d980c001c6837004d980c001c7837004d901c0"}; // {01, c7837004d980c0} <- c7 instead of c6
153153
test::SampleBodySnapshotPath bodies_snapshot_path{invalid_bodies_snapshot.path()};
154154
test::SampleTransactionSnapshotFile valid_txs_snapshot{tmp_dir.path()};
155155
test::SampleTransactionSnapshotPath txs_snapshot_path{valid_txs_snapshot.path()}; // necessary to tweak the block numbers

silkworm/db/snapshots/snapshot_reader.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ Snapshot::Iterator& Snapshot::Iterator::operator++() {
5959
return *this;
6060
}
6161

62+
Snapshot::Iterator& Snapshot::Iterator::operator+=(size_t count) {
63+
while ((count > 1) && it_.has_next()) {
64+
it_.skip();
65+
count--;
66+
}
67+
if (count > 0) {
68+
++*this;
69+
}
70+
return *this;
71+
}
72+
6273
bool operator==(const Snapshot::Iterator& lhs, const Snapshot::Iterator& rhs) {
6374
return (lhs.deserializer_ == rhs.deserializer_) &&
6475
(!lhs.deserializer_ || (lhs.it_ == rhs.it_));

silkworm/db/snapshots/snapshot_reader.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class Snapshot {
6363
Iterator operator++(int) { return std::exchange(*this, ++Iterator{*this}); }
6464
Iterator& operator++();
6565

66+
Iterator& operator+=(size_t count);
67+
6668
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) = default;
6769
friend bool operator==(const Iterator& lhs, const Iterator& rhs);
6870

@@ -135,6 +137,11 @@ class SnapshotReader {
135137
return *this;
136138
}
137139

140+
Iterator& operator+=(size_t count) {
141+
it_ += count;
142+
return *this;
143+
}
144+
138145
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) = default;
139146
friend bool operator==(const Iterator& lhs, const Iterator& rhs) = default;
140147

0 commit comments

Comments
 (0)