Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce memory reallocation in prefetch_blocks #598

Merged
merged 25 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
30a200c
Optimization: reduce memory reallocation in prefetch_blocks
yperbasis Mar 1, 2022
9ee25d6
Make kDefaultPrefetchWidth default param value
yperbasis Mar 2, 2022
66b5366
Tiny clean-up
yperbasis Mar 2, 2022
8fdbf17
Merge branch 'master' into prefetch
yperbasis Mar 3, 2022
962019a
Merge branch 'master' into prefetch
yperbasis Mar 4, 2022
0631edb
Decrease max prefetch blocks to 64
yperbasis Mar 4, 2022
2ab6a38
Clear prefetched blocks on whole buffer flush
yperbasis Mar 5, 2022
c8428c3
Merge branch 'master' into prefetch
yperbasis Mar 5, 2022
ffaaf2e
Merge branch 'master' into prefetch
yperbasis Mar 13, 2022
5b52d7c
prefetched_blocks_clear() in prefetch_blocks
yperbasis Mar 13, 2022
edb2365
Merge branch 'master' into prefetch
yperbasis Mar 25, 2022
c878f0e
Remove pleonastic assert
yperbasis Mar 27, 2022
2650f43
Batch block reading
yperbasis Mar 27, 2022
871e241
Remove unused include
yperbasis Mar 27, 2022
4caf787
read_block -> read_block_by_number
yperbasis Mar 28, 2022
f538438
Separate read_block & read_block_by_number
yperbasis Mar 28, 2022
58f2da0
Extract kMaxPrefetchedBlocks
yperbasis Mar 28, 2022
40df3e0
Circular buffer for prefetched blocks
yperbasis Mar 28, 2022
e759156
Restore some of the original logic
yperbasis Mar 28, 2022
5ce7789
Restore erroneously deleted break
yperbasis Mar 28, 2022
e5a38f1
A couple of renamings
yperbasis Mar 28, 2022
e73be23
A couple of fixes
yperbasis Mar 29, 2022
e51fce8
Merge branch 'master' into prefetch
yperbasis Mar 31, 2022
18d9e63
Make from const in prefetch_blocks
yperbasis Mar 31, 2022
86ac24c
Small comment fix
yperbasis Mar 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions cmd/check_changes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ int main(int argc, char* argv[]) {
ObjectPool<EvmoneExecutionState> state_pool;
std::vector<Receipt> receipts;
auto engine{consensus::engine_factory(chain_config.value())};
BlockWithHash bh;
Block block;
for (; block_num < to; ++block_num) {
txn.renew_reading();
if (!db::read_block(txn, block_num, /*read_senders=*/true, bh)) {
if (!db::read_block_by_number(txn, block_num, /*read_senders=*/true, block)) {
break;
}

db::Buffer buffer{txn, /*prune_from=*/0, /*historical_block=*/block_num};
db::Buffer buffer{txn, /*prune_history_threshold=*/0, /*historical_block=*/block_num};

ExecutionProcessor processor{bh.block, *engine, buffer, *chain_config};
ExecutionProcessor processor{block, *engine, buffer, *chain_config};
processor.evm().advanced_analysis_cache = &analysis_cache;
processor.evm().state_pool = &state_pool;

Expand Down Expand Up @@ -154,7 +154,6 @@ int main(int argc, char* argv[]) {
return -5;
}

t1 = absl::Now();
log::Info() << " Blocks [" << from << "; " << block_num << ") have been checked";
return 0;
}
15 changes: 7 additions & 8 deletions cmd/scan_txs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
limitations under the License.
*/

#include <filesystem>
#include <iostream>

#include <CLI/CLI.hpp>
Expand Down Expand Up @@ -76,21 +75,21 @@ int main(int argc, char* argv[]) {
// counters
uint64_t nTxs{0}, nErrors{0};

BlockWithHash bh;
Block block;
for (uint64_t block_num{from}; block_num < to; ++block_num) {
// Note: See the comment above. You may uncomment that line and comment the next line if you're certain
// that Erigon is not syncing on the same machine. If you use a long-running transaction by doing this, and
// you're mistaken (Erigon is syncing), the database file may 'grow quickly' as per the LMDB docs.
txn.renew_reading();

// Read the block
if (!db::read_block(txn, block_num, /*read_senders=*/true, bh)) {
if (!db::read_block_by_number(txn, block_num, /*read_senders=*/true, block)) {
break;
}

db::Buffer buffer{txn, /*prune_from=*/0, /*historical_block=*/block_num};
db::Buffer buffer{txn, /*prune_history_threshold=*/0, /*historical_block=*/block_num};

ExecutionProcessor processor{bh.block, *engine, buffer, *chain_config};
ExecutionProcessor processor{block, *engine, buffer, *chain_config};
processor.evm().advanced_analysis_cache = &analysis_cache;
processor.evm().state_pool = &state_pool;

Expand All @@ -100,11 +99,11 @@ int main(int argc, char* argv[]) {
}

// There is one receipt per transaction
assert(bh.block.transactions.size() == receipts.size());
assert(block.transactions.size() == receipts.size());

// Erigon returns success in the receipt even for pre-Byzantium txs.
for (auto receipt : receipts) {
nTxs++;
for (const auto& receipt : receipts) {
++nTxs;
nErrors += (!receipt.success);
}

Expand Down
23 changes: 12 additions & 11 deletions node/silkworm/db/access_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,29 +190,30 @@ void read_transactions(mdbx::cursor& txn_table, uint64_t base_id, uint64_t count
SILKWORM_ASSERT(i == count);
}

bool read_block(mdbx::txn& txn, BlockNum block_number, bool read_senders, BlockWithHash& bh) {
// Locate canonical hash

bool read_block_by_number(mdbx::txn& txn, BlockNum number, bool read_senders, Block& block) {
Cursor canonical_hashes_cursor(txn, table::kCanonicalHashes);
auto key{block_key(block_number)};
auto data{canonical_hashes_cursor.find(to_slice(key), false)};
const Bytes key{block_key(number)};
const auto data{canonical_hashes_cursor.find(to_slice(key), false)};
if (!data) {
return false;
}

SILKWORM_ASSERT(data.value.length() == kHashLength);
std::memcpy(bh.hash.bytes, data.value.data(), kHashLength);
const auto hash_ptr{static_cast<const uint8_t*>(data.value.data())};
return read_block(txn, gsl::span<const uint8_t, kHashLength>{hash_ptr, kHashLength}, number, read_senders, block);
}

bool read_block(mdbx::txn& txn, gsl::span<const uint8_t, kHashLength> hash, BlockNum number, bool read_senders,
Block& block) {
// Read header
key = block_key(block_number, bh.hash.bytes);
auto raw_header{read_header_raw(txn, key)};
const Bytes key{block_key(number, hash)};
const auto raw_header{read_header_raw(txn, key)};
if (raw_header.empty()) {
return false;
}
ByteView raw_header_view(raw_header);
rlp::success_or_throw(rlp::decode(raw_header_view, bh.block.header));
rlp::success_or_throw(rlp::decode(raw_header_view, block.header));

return read_body(txn, key, read_senders, bh.block);
return read_body(txn, key, read_senders, block);
}

bool read_body(mdbx::txn& txn, BlockNum block_number, const uint8_t (&hash)[kHashLength], bool read_senders,
Expand Down
17 changes: 12 additions & 5 deletions node/silkworm/db/access_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <optional>
#include <vector>

#include <gsl/span>

#include <silkworm/chain/config.hpp>
#include <silkworm/common/rlp_err.hpp>
#include <silkworm/db/mdbx.hpp>
Expand All @@ -46,7 +48,7 @@ Bytes read_header_raw(mdbx::txn& txn, ByteView key);
void write_header(mdbx::txn& txn, const BlockHeader& header, bool with_header_numbers = false);

//! \brief Writes header hash in table::kHeaderNumbers
void write_header_number(mdbx::txn& txn, const uint8_t (&hash)[kHashLength], const BlockNum number);
void write_header_number(mdbx::txn& txn, const uint8_t (&hash)[kHashLength], BlockNum number);

//! \brief Writes the header hash in table::kCanonicalHashes
void write_canonical_header(mdbx::txn& txn, const BlockHeader& header);
Expand All @@ -60,7 +62,7 @@ void write_canonical_header_hash(mdbx::txn& txn, const uint8_t (&hash)[kHashLeng
bool read_senders, BlockBody& out);

//! \brief Writes block body in table::kBlockBodies
void write_body(mdbx::txn& txn, const BlockBody& body, const uint8_t (&hash)[kHashLength], const BlockNum number);
void write_body(mdbx::txn& txn, const BlockBody& body, const uint8_t (&hash)[kHashLength], BlockNum number);

// See Erigon ReadTd
std::optional<intx::uint256> read_total_difficulty(mdbx::txn& txn, BlockNum block_number,
Expand All @@ -73,9 +75,14 @@ void write_total_difficulty(mdbx::txn& txn, const Bytes& key, const intx::uint25
void write_total_difficulty(mdbx::txn& txn, BlockNum block_number, const uint8_t (&hash)[kHashLength],
const intx::uint256& total_difficulty);

// See Erigon ReadBlockByNumber
// Returns true on success and false on missing block
[[nodiscard]] bool read_block(mdbx::txn& txn, BlockNum block_number, bool read_senders, BlockWithHash& out);
// Reads canonical block; see Erigon ReadBlockByNumber.
// Returns true on success and false on missing block.
[[nodiscard]] bool read_block_by_number(mdbx::txn& txn, BlockNum number, bool read_senders, Block& out);

// Reads a block; see Erigon ReadBlock.
// Returns true on success and false on missing block.
[[nodiscard]] bool read_block(mdbx::txn& txn, gsl::span<const uint8_t, kHashLength> hash, BlockNum number,
bool read_senders, Block& out);

// See Erigon ReadSenders
std::vector<evmc::address> read_senders(mdbx::txn& txn, const Bytes& key);
Expand Down
36 changes: 17 additions & 19 deletions node/silkworm/db/access_layer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,26 +429,25 @@ namespace db {
REQUIRE(header_from_db.has_value());
CHECK(*header_from_db == header);

SECTION("read_block") {
BlockWithHash bh;
SECTION("read_block_by_number") {
Block block;

bool read_senders{false};
CHECK(!read_block(txn, block_num, read_senders, bh));
CHECK(!read_block_by_number(txn, block_num, read_senders, block));

BlockBody body{sample_block_body()};
CHECK_NOTHROW(write_body(txn, body, hash.bytes, header.number));

REQUIRE(read_block(txn, block_num, read_senders, bh));
CHECK(bh.block.header == header);
CHECK(bh.block.ommers == body.ommers);
CHECK(bh.block.transactions == body.transactions);
CHECK(ByteView{bh.hash} == ByteView{hash.bytes});
REQUIRE(read_block_by_number(txn, block_num, read_senders, block));
CHECK(block.header == header);
CHECK(block.ommers == body.ommers);
CHECK(block.transactions == body.transactions);

CHECK(!bh.block.transactions[0].from);
CHECK(!bh.block.transactions[1].from);
CHECK(!block.transactions[0].from);
CHECK(!block.transactions[1].from);

read_senders = true;
CHECK_NOTHROW(read_block(txn, block_num, read_senders, bh));
CHECK_NOTHROW(read_block_by_number(txn, block_num, read_senders, block));

Bytes full_senders{
*from_hex("5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c"
Expand All @@ -458,14 +457,13 @@ namespace db {
Bytes key{block_key(header.number, hash.bytes)};
auto sender_table{db::open_cursor(txn, table::kSenders)};
sender_table.upsert(to_slice(key), to_slice(full_senders));
REQUIRE(read_block(txn, block_num, read_senders, bh));
CHECK(bh.block.header == header);
CHECK(bh.block.ommers == body.ommers);
CHECK(bh.block.transactions == body.transactions);
CHECK(ByteView{bh.hash} == ByteView{hash.bytes});

CHECK(bh.block.transactions[0].from == 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c_address);
CHECK(bh.block.transactions[1].from == 0x941591b6ca8e8dd05c69efdec02b77c72dac1496_address);
REQUIRE(read_block_by_number(txn, block_num, read_senders, block));
CHECK(block.header == header);
CHECK(block.ommers == body.ommers);
CHECK(block.transactions == body.transactions);

CHECK(block.transactions[0].from == 0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c_address);
CHECK(block.transactions[1].from == 0x941591b6ca8e8dd05c69efdec02b77c72dac1496_address);
}
}

Expand Down
4 changes: 2 additions & 2 deletions node/silkworm/db/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ Bytes block_key(BlockNum block_number) {
return key;
}

Bytes block_key(BlockNum block_number, const uint8_t (&hash)[kHashLength]) {
Bytes block_key(BlockNum block_number, gsl::span<const uint8_t, kHashLength> hash) {
Bytes key(8 + kHashLength, '\0');
endian::store_big_u64(&key[0], block_number);
std::memcpy(&key[8], hash, kHashLength);
std::memcpy(&key[8], hash.data(), kHashLength);
return key;
}

Expand Down
3 changes: 2 additions & 1 deletion node/silkworm/db/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ see its package dbutils.
#include <string>

#include <absl/container/btree_map.h>
#include <gsl/span>

#include <silkworm/common/base.hpp>
#include <silkworm/db/mdbx.hpp>
Expand Down Expand Up @@ -108,7 +109,7 @@ Bytes storage_prefix(ByteView address, uint64_t incarnation);
Bytes block_key(BlockNum block_number);

// Erigon HeaderKey & BlockBodyKey
Bytes block_key(BlockNum block_number, const uint8_t (&hash)[kHashLength]);
Bytes block_key(BlockNum block_number, gsl::span<const uint8_t, kHashLength> hash);

Bytes storage_change_key(BlockNum block_number, const evmc::address& address, uint64_t incarnation);

Expand Down
Loading