Skip to content

Commit 03d0dce

Browse files
committed
src: dynamic block sync size
Co-authored-by: nahuhh
1 parent a1dc85c commit 03d0dce

File tree

7 files changed

+75
-13
lines changed

7 files changed

+75
-13
lines changed

src/cryptonote_config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@
9898
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4 100 //by default, blocks count in blocks downloading
9999
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 20 //by default, blocks count in blocks downloading
100100
#define BLOCKS_SYNCHRONIZING_MAX_COUNT 2048 //must be a power of 2, greater than 128, equal to SEEDHASH_EPOCH_BLOCKS
101+
#define BLOCKS_MEDIAN_WINDOW 100 //by default, compute median weights of last 100 blocks
102+
#define BATCH_MAX_WEIGHT 20 //by default, maximum size of batch in [mB]
103+
#define BATCH_MAX_ALLOWED_WEIGHT 50 //maximum allowed size of batch in [mB]
104+
#define BLOCKS_HUGE_THRESHOLD_SIZE ((BATCH_MAX_WEIGHT * 1000000) / 2) //blocks that we consider huge [B]
101105

102106
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME (86400*3) //seconds, three days
103107
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week

src/cryptonote_core/blockchain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,11 @@ namespace cryptonote
14431443
* @param weights return-by-reference the list of weights
14441444
* @param count the number of blocks to get weights for
14451445
*/
1446+
public:
14461447
void get_last_n_blocks_weights(std::vector<uint64_t>& weights, size_t count) const;
1448+
#ifndef IN_UNIT_TESTS
1449+
private:
1450+
#endif
14471451

14481452
/**
14491453
* @brief gets block long term weight median

src/cryptonote_core/cryptonote_core.cpp

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ namespace cryptonote
168168
, "How many blocks to sync at once during chain synchronization (0 = adaptive)."
169169
, 0
170170
};
171+
static const command_line::arg_descriptor<size_t> arg_batch_max_weight = {
172+
"batch-max-weight"
173+
, "How many megabytes to sync in one batch during chain synchronization, default is 20 max"
174+
, (BATCH_MAX_WEIGHT)
175+
};
171176
static const command_line::arg_descriptor<std::string> arg_check_updates = {
172177
"check-updates"
173178
, "Check for new versions of monero: [disabled|notify|download|update]"
@@ -335,6 +340,7 @@ namespace cryptonote
335340
command_line::add_arg(desc, arg_fast_block_sync);
336341
command_line::add_arg(desc, arg_show_time_stats);
337342
command_line::add_arg(desc, arg_block_sync_size);
343+
command_line::add_arg(desc, arg_batch_max_weight);
338344
command_line::add_arg(desc, arg_check_updates);
339345
command_line::add_arg(desc, arg_no_fluffy_blocks);
340346
command_line::add_arg(desc, arg_test_dbg_lock_sleep);
@@ -691,6 +697,17 @@ namespace cryptonote
691697
if (block_sync_size > BLOCKS_SYNCHRONIZING_MAX_COUNT)
692698
MERROR("Error --block-sync-size cannot be greater than " << BLOCKS_SYNCHRONIZING_MAX_COUNT);
693699

700+
if(block_sync_size)
701+
MWARNING("When --block-sync-size defined, the --batch-max-weight is not going to have any effect.");
702+
703+
batch_max_weight = command_line::get_arg(vm, arg_batch_max_weight);
704+
if (batch_max_weight > BATCH_MAX_ALLOWED_WEIGHT) {
705+
MERROR("Error --batch-max-weight cannot be greater than " << BATCH_MAX_ALLOWED_WEIGHT << " [mB]");
706+
batch_max_weight = BATCH_MAX_ALLOWED_WEIGHT;
707+
}
708+
709+
batch_max_weight *= 1000000; // transfer it to byte.
710+
694711
MGINFO("Loading checkpoints");
695712

696713
// load json & DNS checkpoints, and verify them
@@ -1214,16 +1231,37 @@ namespace cryptonote
12141231
return true;
12151232
}
12161233
//-----------------------------------------------------------------------------------------------
1217-
size_t core::get_block_sync_size(uint64_t height) const
1234+
size_t core::get_block_sync_size(uint64_t height, const uint64_t average_blocksize_of_biggest_batch) const
12181235
{
1219-
static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0;
12201236
size_t res = 0;
12211237
if (block_sync_size > 0)
12221238
res = block_sync_size;
1223-
else if (height >= quick_height)
1224-
res = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
1225-
else
1226-
res = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4;
1239+
else {
1240+
size_t number_of_blocks = BLOCKS_MEDIAN_WINDOW;
1241+
std::vector<uint64_t> last_n_blocks_weights;
1242+
m_blockchain_storage.get_last_n_blocks_weights(last_n_blocks_weights, number_of_blocks);
1243+
uint64_t median_weight = epee::misc_utils::median(last_n_blocks_weights);
1244+
MINFO("Last " << number_of_blocks
1245+
<< " blocks median size is " << median_weight
1246+
<< " bytes and the max average blocksize in the queue is " << average_blocksize_of_biggest_batch << " bytes");
1247+
uint64_t projected_blocksize = (average_blocksize_of_biggest_batch > median_weight) ? average_blocksize_of_biggest_batch : median_weight;
1248+
if ((projected_blocksize * BLOCKS_MEDIAN_WINDOW) < batch_max_weight) {
1249+
res = BLOCKS_MEDIAN_WINDOW;
1250+
MINFO("blocks are tiny, " << projected_blocksize << " bytes, sync " << res << " blocks in next batch");
1251+
}
1252+
else if (projected_blocksize >= batch_max_weight) {
1253+
res = 1;
1254+
MINFO("blocks are projected to surpass " << batch_max_weight << " bytes, syncing just a single block in next batch");
1255+
}
1256+
else if (projected_blocksize > BLOCKS_HUGE_THRESHOLD_SIZE) {
1257+
res = 1;
1258+
MINFO("blocks are huge, sync just a single block in next batch");
1259+
}
1260+
else {
1261+
res = batch_max_weight / projected_blocksize;
1262+
MINFO("projected blocksize is " << projected_blocksize << " bytes, sync " << res << " blocks in next batch");
1263+
}
1264+
}
12271265

12281266
static size_t max_block_size = 0;
12291267
if (max_block_size == 0)

src/cryptonote_core/cryptonote_core.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,9 +798,13 @@ namespace cryptonote
798798
/**
799799
* @brief get the number of blocks to sync in one go
800800
*
801+
* @param height the height that we want to get_block_sync_size for
802+
* @param average_blocksize_of_biggest_batch is the average blocksize of the biggest batch
803+
* we are downloading in current active connections.
804+
*
801805
* @return the number of blocks to sync in one go
802806
*/
803-
size_t get_block_sync_size(uint64_t height) const;
807+
size_t get_block_sync_size(uint64_t height, const uint64_t average_blocksize_of_biggest_batch = 0) const;
804808

805809
/**
806810
* @brief get the sum of coinbase tx amounts between blocks
@@ -1136,6 +1140,7 @@ namespace cryptonote
11361140
bool m_disable_dns_checkpoints;
11371141

11381142
size_t block_sync_size;
1143+
std::uint64_t batch_max_weight;
11391144

11401145
time_t start_time;
11411146

src/cryptonote_protocol/cryptonote_protocol_handler.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "net/levin_base.h"
5151
#include "p2p/net_node_common.h"
5252
#include <boost/circular_buffer.hpp>
53+
#include <atomic>
5354

5455
PUSH_WARNINGS
5556
DISABLE_VS_WARNINGS(4355)
@@ -112,6 +113,15 @@ namespace cryptonote
112113
void log_connections();
113114
std::list<connection_info> get_connections();
114115
const block_queue &get_block_queue() const { return m_block_queue; }
116+
const std::uint64_t max_average_of_blocksize_in_queue() {
117+
std::vector<std::uint64_t> average_blocksize{0};
118+
m_block_queue.foreach([&](const cryptonote::block_queue::span &span) {
119+
average_blocksize.push_back(span.size / span.nblocks);
120+
return true; // we don't care about the return value
121+
});
122+
MINFO("Maximum average of blocksize for current batches : " << *std::max_element(average_blocksize.begin(), average_blocksize.end()));
123+
return *std::max_element(average_blocksize.begin(), average_blocksize.end());
124+
}
115125
void stop();
116126
void on_connection_close(cryptonote_connection_context &context);
117127
void set_max_out_peers(epee::net_utils::zone zone, unsigned int max) { CRITICAL_REGION_LOCAL(m_max_out_peers_lock); m_max_out_peers[zone] = max; }
@@ -191,6 +201,7 @@ namespace cryptonote
191201
uint64_t m_sync_download_chain_size, m_sync_download_objects_size;
192202
size_t m_block_download_max_size;
193203
bool m_sync_pruned_blocks;
204+
std::atomic<size_t> m_bss;
194205

195206
// Values for sync time estimates
196207
boost::posix_time::ptime m_sync_start_time;

src/cryptonote_protocol/cryptonote_protocol_handler.inl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ namespace cryptonote
8787
m_synchronized(offline),
8888
m_ask_for_txpool_complement(true),
8989
m_stopping(false),
90-
m_no_sync(false)
91-
90+
m_no_sync(false),
91+
m_bss(0)
9292
{
9393
if(!m_p2p)
9494
m_p2p = &m_p2p_stub;
@@ -2222,7 +2222,7 @@ skip:
22222222
NOTIFY_REQUEST_GET_OBJECTS::request req;
22232223
bool is_next = false;
22242224
size_t count = 0;
2225-
const size_t count_limit = m_core.get_block_sync_size(m_core.get_current_blockchain_height());
2225+
size_t l_m_bss = m_bss = m_core.get_block_sync_size(m_core.get_current_blockchain_height(), max_average_of_blocksize_in_queue());
22262226
std::pair<uint64_t, uint64_t> span = std::make_pair(0, 0);
22272227
if (force_next_span)
22282228
{
@@ -2272,7 +2272,7 @@ skip:
22722272
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
22732273
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
22742274
bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
2275-
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
2275+
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, l_m_bss, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
22762276
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
22772277
if (span.second > 0)
22782278
{
@@ -2358,7 +2358,7 @@ skip:
23582358
context.m_expect_height = span.first;
23592359
context.m_expect_response = NOTIFY_RESPONSE_GET_OBJECTS::ID;
23602360
MLOG_P2P_MESSAGE("-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size()
2361-
<< "requested blocks count=" << count << " / " << count_limit << " from " << span.first << ", first hash " << req.blocks.front());
2361+
<< "requested blocks count=" << count << " / " << l_m_bss << " from " << span.first << ", first hash " << req.blocks.front());
23622362
//epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
23632363

23642364
MDEBUG("Asking for " << (req.prune ? "pruned" : "full") << " data, start/end "

tests/unit_tests/node_server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class test_core : public cryptonote::i_core_events
7474
bool cleanup_handle_incoming_blocks(bool force_sync = false) { return true; }
7575
bool update_checkpoints(const bool skip_dns = false) { return true; }
7676
uint64_t get_target_blockchain_height() const { return 1; }
77-
size_t get_block_sync_size(uint64_t height) const { return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; }
77+
size_t get_block_sync_size(uint64_t height, const uint64_t average_blocksize_of_biggest_batch = 0) const { return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; }
7878
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, cryptonote::relay_method tx_relay) {}
7979
cryptonote::network_type get_nettype() const { return cryptonote::MAINNET; }
8080
bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob, cryptonote::relay_category tx_category) const { return false; }

0 commit comments

Comments
 (0)