Add benchmarks, some light optimizations like SSO
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
@@ -8,9 +8,10 @@
|
||||
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
|
||||
#include <AzCore/DOM/DomUtils.h>
|
||||
#include <AzCore/DOM/Backends/JSON/JsonBackend.h>
|
||||
#include <AzCore/DOM/Backends/JSON/JsonSerializationUtils.h>
|
||||
#include <AzCore/DOM/DomUtils.h>
|
||||
#include <AzCore/DOM/DomValue.h>
|
||||
#include <AzCore/JSON/document.h>
|
||||
#include <AzCore/Name/NameDictionary.h>
|
||||
#include <AzCore/Serialization/Json/JsonUtils.h>
|
||||
@@ -25,22 +26,26 @@ namespace Benchmark
|
||||
{
|
||||
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
|
||||
AZ::NameDictionary::Create();
|
||||
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Create();
|
||||
}
|
||||
|
||||
void SetUp(::benchmark::State& st) override
|
||||
{
|
||||
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
|
||||
AZ::NameDictionary::Create();
|
||||
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Create();
|
||||
}
|
||||
|
||||
void TearDown(::benchmark::State& st) override
|
||||
{
|
||||
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Destroy();
|
||||
AZ::NameDictionary::Destroy();
|
||||
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& st) override
|
||||
{
|
||||
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Destroy();
|
||||
AZ::NameDictionary::Destroy();
|
||||
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
|
||||
}
|
||||
@@ -143,6 +148,30 @@ namespace Benchmark
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDocumentInPlace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDomValueInPlace)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
AZStd::string payloadCopy = serializedPayload;
|
||||
state.ResumeTiming();
|
||||
|
||||
auto result = AZ::Dom::Utils::WriteToValue(
|
||||
[&](AZ::Dom::Visitor& visitor)
|
||||
{
|
||||
return AZ::Dom::Utils::ReadFromStringInPlace(backend, payloadCopy, visitor);
|
||||
});
|
||||
|
||||
benchmark::DoNotOptimize(result.GetValue());
|
||||
}
|
||||
|
||||
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDomValueInPlace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDocument)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
@@ -179,6 +208,17 @@ namespace Benchmark
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, JsonUtilsDeserializeToDocument)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonPayloadGeneration)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)));
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonPayloadGeneration)
|
||||
|
||||
#undef BENCHMARK_REGISTER_JSON
|
||||
} // namespace Benchmark
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomValue.h>
|
||||
#include <AzCore/Name/NameDictionary.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
|
||||
namespace AZ::Dom::Benchmark
|
||||
{
|
||||
class DomValueBenchmark : public UnitTest::AllocatorsBenchmarkFixture
|
||||
{
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& st) override
|
||||
{
|
||||
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
|
||||
AZ::NameDictionary::Create();
|
||||
AZ::AllocatorInstance<ValueAllocator>::Create();
|
||||
}
|
||||
|
||||
void SetUp(::benchmark::State& st) override
|
||||
{
|
||||
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
|
||||
AZ::NameDictionary::Create();
|
||||
AZ::AllocatorInstance<ValueAllocator>::Create();
|
||||
}
|
||||
|
||||
void TearDown(::benchmark::State& st) override
|
||||
{
|
||||
AZ::AllocatorInstance<ValueAllocator>::Destroy();
|
||||
AZ::NameDictionary::Destroy();
|
||||
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& st) override
|
||||
{
|
||||
AZ::AllocatorInstance<ValueAllocator>::Destroy();
|
||||
AZ::NameDictionary::Destroy();
|
||||
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
|
||||
}
|
||||
|
||||
Value GenerateDomBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength)
|
||||
{
|
||||
Value root(Type::ObjectType);
|
||||
|
||||
AZStd::string entryTemplate;
|
||||
while (entryTemplate.size() < static_cast<size_t>(stringTemplateLength))
|
||||
{
|
||||
entryTemplate += "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ";
|
||||
}
|
||||
entryTemplate.resize(stringTemplateLength);
|
||||
AZStd::string buffer;
|
||||
|
||||
auto createString = [&](int n) -> Value
|
||||
{
|
||||
return Value(AZStd::string::format("#%i %s", n, entryTemplate.c_str()), true);
|
||||
};
|
||||
|
||||
auto createEntry = [&](int n) -> Value
|
||||
{
|
||||
Value entry(Type::ObjectType);
|
||||
entry.AddMember("string", createString(n));
|
||||
entry.AddMember("int", n);
|
||||
entry.AddMember("double", static_cast<double>(n) * 0.5);
|
||||
entry.AddMember("bool", n % 2 == 0);
|
||||
entry.AddMember("null", Value(Type::NullType));
|
||||
return entry;
|
||||
};
|
||||
|
||||
auto createArray = [&]() -> Value
|
||||
{
|
||||
Value array(Type::ArrayType);
|
||||
for (int i = 0; i < entryCount; ++i)
|
||||
{
|
||||
array.PushBack(createEntry(i));
|
||||
}
|
||||
return array;
|
||||
};
|
||||
|
||||
auto createObject = [&]() -> Value
|
||||
{
|
||||
Value object;
|
||||
object.SetObject();
|
||||
for (int i = 0; i < entryCount; ++i)
|
||||
{
|
||||
buffer = AZStd::string::format("Key%i", i);
|
||||
object.AddMember(AZ::Name(buffer), createArray());
|
||||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
root["entries"] = createObject();
|
||||
|
||||
return root;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, ValuePayloadGeneration)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize(GenerateDomBenchmarkPayload(state.range(0), state.range(1)));
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, ValuePayloadGeneration)
|
||||
->Args({ 10, 5 })
|
||||
->Args({ 10, 500 })
|
||||
->Args({ 100, 5 })
|
||||
->Args({ 100, 500 })
|
||||
->Unit(benchmark::kMillisecond);
|
||||
} // namespace AZ::Dom::Benchmark
|
||||
|
||||
@@ -25,12 +25,14 @@ namespace AZ::Dom::Tests
|
||||
{
|
||||
UnitTest::AllocatorsFixture::SetUp();
|
||||
NameDictionary::Create();
|
||||
AZ::AllocatorInstance<ValueAllocator>::Create();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_value = Value();
|
||||
|
||||
AZ::AllocatorInstance<ValueAllocator>::Destroy();
|
||||
NameDictionary::Destroy();
|
||||
UnitTest::AllocatorsFixture::TearDown();
|
||||
}
|
||||
@@ -279,19 +281,24 @@ namespace AZ::Dom::Tests
|
||||
|
||||
TEST_F(DomValueTests, String)
|
||||
{
|
||||
const char* s1 = "reference string long enough to avoid SSO";
|
||||
const char* s2 = "copy string long enough to avoid SSO";
|
||||
|
||||
m_value.SetObject();
|
||||
AZStd::string stringToReference = "foo";
|
||||
AZStd::string stringToReference = s1;
|
||||
m_value["no_copy"] = Value(stringToReference, false);
|
||||
AZStd::string stringToCopy = "bar";
|
||||
AZStd::string stringToCopy = s2;
|
||||
m_value["copy"] = Value(stringToCopy, true);
|
||||
|
||||
EXPECT_EQ(m_value["no_copy"].GetType(), Type::StringType);
|
||||
EXPECT_EQ(m_value["no_copy"].GetString(), stringToReference);
|
||||
EXPECT_EQ(m_value["no_copy"].GetString().data(), stringToReference.data());
|
||||
EXPECT_EQ(m_value["no_copy"].GetString(), s1);
|
||||
stringToReference.at(0) = 'F';
|
||||
EXPECT_NE(m_value["no_copy"].GetString(), s1);
|
||||
|
||||
EXPECT_EQ(m_value["copy"].GetType(), Type::StringType);
|
||||
EXPECT_EQ(m_value["copy"].GetString(), stringToCopy);
|
||||
EXPECT_NE(m_value["copy"].GetString().data(), stringToCopy.data());
|
||||
EXPECT_EQ(m_value["copy"].GetString(), s2);
|
||||
stringToCopy.at(0) = 'F';
|
||||
EXPECT_EQ(m_value["copy"].GetString(), s2);
|
||||
|
||||
PerformValueChecks();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user