Split sanitizer and instrumentation checks in to several distinct parts. (#3903)
Previously, valgrind/sanitizers were used interchangeably in tests that had specific behaviors when instrumented. Often these checks were ambiguous or overly conservative in what they were doing. This commit splits these checks in to more specific functions. `is_sanitizer_build' is changed from a bool to a function and is_asan_build and is_tsan_build are separated. The `memory_intensive_instrumentation' function returns true if instrumentation has a significant memory impact which can affect things like large virtual memory allocations as is done with LMDB. The `slow_instrumentation' function returns true if instrumentation significantly impacts performance which can affect unit tests completion times.
This commit is contained in:
parent
9011cef119
commit
7a981fa053
7 changed files with 83 additions and 22 deletions
|
@ -3437,8 +3437,7 @@ TEST (node, aggressive_flooding)
|
|||
auto & wallet1 (*system.wallet (0));
|
||||
wallet1.insert_adhoc (nano::dev::genesis_key.prv);
|
||||
std::vector<std::pair<std::shared_ptr<nano::node>, std::shared_ptr<nano::wallet>>> nodes_wallets;
|
||||
bool const sanitizer_or_valgrind (is_sanitizer_build || nano::running_within_valgrind ());
|
||||
nodes_wallets.resize (!sanitizer_or_valgrind ? 5 : 3);
|
||||
nodes_wallets.resize (!nano::memory_intensive_instrumentation () ? 5 : 3);
|
||||
|
||||
std::generate (nodes_wallets.begin (), nodes_wallets.end (), [&system, node_flags] () {
|
||||
nano::node_config node_config (nano::test::get_available_port (), system.logging);
|
||||
|
@ -3489,12 +3488,12 @@ TEST (node, aggressive_flooding)
|
|||
});
|
||||
};
|
||||
|
||||
ASSERT_TIMELY (!sanitizer_or_valgrind ? 10s : 40s, all_received ());
|
||||
ASSERT_TIMELY (!nano::slow_instrumentation () ? 10s : 40s, all_received ());
|
||||
|
||||
ASSERT_TIMELY (!sanitizer_or_valgrind ? 10s : 40s, node1.ledger.cache.block_count == 1 + 2 * nodes_wallets.size ());
|
||||
ASSERT_TIMELY (!nano::slow_instrumentation () ? 10s : 40s, node1.ledger.cache.block_count == 1 + 2 * nodes_wallets.size ());
|
||||
|
||||
// Wait until the main node sees all representatives
|
||||
ASSERT_TIMELY (!sanitizer_or_valgrind ? 10s : 40s, node1.rep_crawler.principal_representatives ().size () == nodes_wallets.size ());
|
||||
ASSERT_TIMELY (!nano::slow_instrumentation () ? 10s : 40s, node1.rep_crawler.principal_representatives ().size () == nodes_wallets.size ());
|
||||
|
||||
// Generate blocks and ensure they are sent to all representatives
|
||||
nano::state_block_builder builder;
|
||||
|
@ -3520,11 +3519,11 @@ TEST (node, aggressive_flooding)
|
|||
});
|
||||
};
|
||||
|
||||
ASSERT_TIMELY (!sanitizer_or_valgrind ? 5s : 25s, all_have_block (block->hash ()));
|
||||
ASSERT_TIMELY (!nano::slow_instrumentation () ? 5s : 25s, all_have_block (block->hash ()));
|
||||
|
||||
// Do the same for a wallet block
|
||||
auto wallet_block = wallet1.send_sync (nano::dev::genesis_key.pub, nano::dev::genesis_key.pub, 10);
|
||||
ASSERT_TIMELY (!sanitizer_or_valgrind ? 5s : 25s, all_have_block (wallet_block));
|
||||
ASSERT_TIMELY (!nano::slow_instrumentation () ? 5s : 25s, all_have_block (wallet_block));
|
||||
|
||||
// All blocks: genesis + (send+open) for each representative + 2 local blocks
|
||||
// The main node only sees all blocks if other nodes are flooding their PR's open block to all other PRs
|
||||
|
|
|
@ -280,6 +280,21 @@ bool running_within_valgrind ()
|
|||
return (RUNNING_ON_VALGRIND > 0);
|
||||
}
|
||||
|
||||
bool memory_intensive_instrumentation ()
|
||||
{
|
||||
return is_tsan_build () || nano::running_within_valgrind ();
|
||||
}
|
||||
|
||||
bool slow_instrumentation ()
|
||||
{
|
||||
return is_tsan_build () || nano::running_within_valgrind ();
|
||||
}
|
||||
|
||||
bool is_sanitizer_build ()
|
||||
{
|
||||
return is_asan_build () || is_tsan_build ();
|
||||
}
|
||||
|
||||
std::string get_node_toml_config_path (boost::filesystem::path const & data_path)
|
||||
{
|
||||
return (data_path / "config-node.toml").string ();
|
||||
|
|
|
@ -30,18 +30,54 @@ char const * const NANO_PRE_RELEASE_VERSION_STRING = xstr (PRE_RELEASE_VERSION_S
|
|||
|
||||
char const * const BUILD_INFO = xstr (GIT_COMMIT_HASH BOOST_COMPILER) " \"BOOST " xstr (BOOST_VERSION) "\" BUILT " xstr (__DATE__);
|
||||
|
||||
/** Is TSAN/ASAN dev build */
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(thread_sanitizer) || __has_feature(address_sanitizer)
|
||||
bool const is_sanitizer_build = true;
|
||||
#if __has_feature(address_sanitizer)
|
||||
inline bool is_asan_build ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool const is_sanitizer_build = false;
|
||||
inline bool is_asan_build ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// GCC builds
|
||||
#elif defined(__SANITIZE_THREAD__) || defined(__SANITIZE_ADDRESS__)
|
||||
const bool is_sanitizer_build = true;
|
||||
#elif defined(__SANITIZE_ADDRESS__)
|
||||
inline bool is_asan_build ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool const is_sanitizer_build = false;
|
||||
inline bool is_asan_build ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(thread_sanitizer)
|
||||
inline bool is_tsan_build ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
inline bool is_tsan_build ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// GCC builds
|
||||
#elif defined(__SANITIZE_THREAD__)
|
||||
inline bool is_tsan_build ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
inline bool is_tsan_build ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace nano
|
||||
|
@ -315,6 +351,17 @@ std::string get_tls_toml_config_path (boost::filesystem::path const & data_path)
|
|||
/** Checks if we are running inside a valgrind instance */
|
||||
bool running_within_valgrind ();
|
||||
|
||||
/** Checks if we are running with instrumentation that significantly affects memory consumption and can cause large virtual memory allocations to fail
|
||||
Returns true if running within Valgrind or with ThreadSanitizer tooling*/
|
||||
bool memory_intensive_instrumentation ();
|
||||
|
||||
/** Check if we're running with instrumentation that can greatly affect performance
|
||||
Returns true if running within Valgrind or with ThreadSanitizer tooling*/
|
||||
bool slow_instrumentation ();
|
||||
|
||||
/** Checks if we are running with either AddressSanitizer or ThreadSanitizer*/
|
||||
bool is_sanitizer_build ();
|
||||
|
||||
/** Set the active network to the dev network */
|
||||
void force_nano_dev_network ();
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ void nano::mdb_env::init (bool & error_a, boost::filesystem::path const & path_a
|
|||
auto status2 (mdb_env_set_maxdbs (environment, options_a.config.max_databases));
|
||||
release_assert (status2 == 0);
|
||||
auto map_size = options_a.config.map_size;
|
||||
auto max_valgrind_map_size = 16 * 1024 * 1024;
|
||||
if (running_within_valgrind () && map_size > max_valgrind_map_size)
|
||||
auto max_instrumented_map_size = 16 * 1024 * 1024;
|
||||
if (memory_intensive_instrumentation () && map_size > max_instrumented_map_size)
|
||||
{
|
||||
// In order to run LMDB under Valgrind, the maximum map size must be smaller than half your available RAM
|
||||
map_size = max_valgrind_map_size;
|
||||
// In order to run LMDB with some types of memory instrumentation, the maximum map size must be smaller than what is normally used when non-instrumented
|
||||
map_size = max_instrumented_map_size;
|
||||
}
|
||||
auto status3 (mdb_env_set_mapsize (environment, map_size));
|
||||
release_assert (status3 == 0);
|
||||
|
@ -47,7 +47,7 @@ void nano::mdb_env::init (bool & error_a, boost::filesystem::path const & path_a
|
|||
environment_flags |= MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC;
|
||||
}
|
||||
|
||||
if (!running_within_valgrind () && options_a.use_no_mem_init)
|
||||
if (!memory_intensive_instrumentation () && options_a.use_no_mem_init)
|
||||
{
|
||||
environment_flags |= MDB_NOMEMINIT;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
std::chrono::milliseconds block_processor_batch_max_time{ network_params.network.is_dev_network () ? std::chrono::milliseconds (500) : std::chrono::milliseconds (5000) };
|
||||
std::chrono::seconds unchecked_cutoff_time{ std::chrono::seconds (4 * 60 * 60) }; // 4 hours
|
||||
/** Timeout for initiated async operations */
|
||||
std::chrono::seconds tcp_io_timeout{ (network_params.network.is_dev_network () && !is_sanitizer_build) ? std::chrono::seconds (5) : std::chrono::seconds (15) };
|
||||
std::chrono::seconds tcp_io_timeout{ (network_params.network.is_dev_network () && !is_sanitizer_build ()) ? std::chrono::seconds (5) : std::chrono::seconds (15) };
|
||||
std::chrono::nanoseconds pow_sleep_interval{ 0 };
|
||||
std::size_t active_elections_size{ 5000 };
|
||||
std::size_t active_elections_hinted_limit_percentage{ 20 }; // Limit of hinted elections as percentage of active_elections_size
|
||||
|
|
|
@ -129,7 +129,7 @@ private:
|
|||
std::chrono::seconds const cache_cutoff{ nano::telemetry_cache_cutoffs::network_to_time (network_params.network) };
|
||||
|
||||
// The maximum time spent waiting for a response to a telemetry request
|
||||
std::chrono::seconds const response_time_cutoff{ network_params.network.is_dev_network () ? (is_sanitizer_build || nano::running_within_valgrind () ? 6 : 3) : 10 };
|
||||
std::chrono::seconds const response_time_cutoff{ network_params.network.is_dev_network () ? (is_sanitizer_build () || nano::running_within_valgrind () ? 6 : 3) : 10 };
|
||||
|
||||
std::unordered_map<nano::endpoint, std::vector<std::function<void (telemetry_data_response const &)>>> callbacks;
|
||||
|
||||
|
|
|
@ -1653,7 +1653,7 @@ TEST (telemetry, many_nodes)
|
|||
node_flags.disable_initial_telemetry_requests = true;
|
||||
node_flags.disable_request_loop = true;
|
||||
// The telemetry responses can timeout if using a large number of nodes under sanitizers, so lower the number.
|
||||
auto const num_nodes = (is_sanitizer_build || nano::running_within_valgrind ()) ? 4 : 10;
|
||||
auto const num_nodes = nano::memory_intensive_instrumentation () ? 4 : 10;
|
||||
for (auto i = 0; i < num_nodes; ++i)
|
||||
{
|
||||
nano::node_config node_config (nano::test::get_available_port (), system.logging);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue