Various Benchmark Fixes for AzCore (#7611)

Fixed crash in Allocators Benchmark multithreaded test due to the HPHA schema not having proper multithread protection around the `mFreeTree` member in `tree_get_unused_memory` function.
The `mFreeTree intrusive set is able to modified on multiple threads.

Replaced the custom intrusive_list implementation n HPHA schema with AZStd::intrusive_list

Added a `ScopedAllocatorBenchmarkEnvironment` class to provide an RAI mechanism for initializing the SystemAllocator in Benchmark Test

Rermoved the `AzCoreBenchmarkEnvironment` in lieu of the `ScopedAllocatorBenchmarkEnvironment` class

Fixed assert when running Allocator Benchmarks in debug due to mismatch PauseTiming/ResumeTiming in Allocator Benchmark Fixtures

Added `ScopedRegisterBenchmarkEnvironment` RAII class to provide lifetime guarantees on BenchmarkEnvironments registered via the `AZ_UNIT_TEST_HOOK`

Initialized the intrusive_multiset_node members to nullptr in all build configurations instead of only debug as the cost negligible and it is useful for debugging.

fixes LYN-10210

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
lumberyard-employee-dm
2022-02-14 11:08:53 -06:00
committed by GitHub
parent ceb61d143c
commit 6f52fcb9f0
6 changed files with 110 additions and 275 deletions
+28 -14
View File
@@ -164,6 +164,16 @@ namespace AZ
m_envs.push_back(std::move(env));
}
// Remove a registered benchmark from the registry
void RemoveBenchmarkEnvironment(BenchmarkEnvironmentBase* env)
{
auto RemoveBenchmarkFunc = [env](const std::unique_ptr<BenchmarkEnvironmentBase>& envElement)
{
return envElement.get() == env;
};
m_envs.erase(std::remove_if(m_envs.begin(), m_envs.end(), std::move(RemoveBenchmarkFunc)));
}
std::vector<std::unique_ptr<BenchmarkEnvironmentBase>>& GetBenchmarkEnvironments()
{
return m_envs;
@@ -194,21 +204,26 @@ namespace AZ
return *benchmarkEnv;
}
template<typename... Ts>
std::array<BenchmarkEnvironmentBase*, sizeof...(Ts)> RegisterBenchmarkEnvironments()
/*
* An RAII wrapper about registering a BenchmarkEnvironment with the BenchmarkRegistry
* It will unregister the BenchmarkEnvironment with the BenchmarkRegistry on destruction
*/
struct ScopedRegisterBenchmarkEnvironment
{
constexpr size_t EnvironmentCount{ sizeof...(Ts) };
if constexpr (EnvironmentCount)
template<typename T>
ScopedRegisterBenchmarkEnvironment(T& benchmarkEnv)
: m_benchmarkEnv(benchmarkEnv)
{}
~ScopedRegisterBenchmarkEnvironment()
{
std::array<BenchmarkEnvironmentBase*, EnvironmentCount> benchmarkEnvs{ { &RegisterBenchmarkEnvironment<Ts>()... } };
return benchmarkEnvs;
if (auto benchmarkRegistry = AZ::Environment::FindVariable<BenchmarkEnvironmentRegistry>(s_benchmarkEnvironmentName);
benchmarkRegistry != nullptr)
{
benchmarkRegistry->RemoveBenchmarkEnvironment(&m_benchmarkEnv);
}
}
else
{
std::array<BenchmarkEnvironmentBase*, EnvironmentCount> benchmarkEnvs{};
return benchmarkEnvs;
}
}
BenchmarkEnvironmentBase& m_benchmarkEnv;
};
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! listener class to capture and print test output for embedded platforms
@@ -276,7 +291,7 @@ namespace AZ
#define AZ_BENCHMARK_HOOK_ENV(TEST_ENV) \
AZTEST_EXPORT int AzRunBenchmarks(int argc, char** argv) \
{ \
AZ::Test::RegisterBenchmarkEnvironments<TEST_ENV>(); \
AZ::Test::ScopedRegisterBenchmarkEnvironment scopedBenchmarkEnv(AZ::Test::RegisterBenchmarkEnvironment<TEST_ENV>()); \
auto benchmarkEnvRegistry = AZ::Environment::FindVariable<AZ::Test::BenchmarkEnvironmentRegistry>(AZ::Test::s_benchmarkEnvironmentName); \
std::vector<std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>>* benchmarkEnvs = benchmarkEnvRegistry ? &(benchmarkEnvRegistry->GetBenchmarkEnvironments()) : nullptr; \
if (benchmarkEnvs != nullptr) \
@@ -307,7 +322,6 @@ AZTEST_EXPORT int AzRunBenchmarks(int argc, char** argv) \
#define AZ_BENCHMARK_HOOK() \
AZTEST_EXPORT int AzRunBenchmarks(int argc, char** argv) \
{ \
AZ::Test::RegisterBenchmarkEnvironments<>(); \
auto benchmarkEnvRegistry = AZ::Environment::FindVariable<AZ::Test::BenchmarkEnvironmentRegistry>(AZ::Test::s_benchmarkEnvironmentName); \
std::vector<std::unique_ptr<AZ::Test::BenchmarkEnvironmentBase>>* benchmarkEnvs = benchmarkEnvRegistry ? &(benchmarkEnvRegistry->GetBenchmarkEnvironments()) : nullptr; \
if (benchmarkEnvs != nullptr) \