Add another round of benchmarks
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
@@ -61,6 +61,11 @@ namespace AZ::Dom
|
||||
return m_children;
|
||||
}
|
||||
|
||||
Value::Value(AZStd::shared_ptr<AZStd::string> string)
|
||||
: m_value(string)
|
||||
{
|
||||
}
|
||||
|
||||
Value::Value()
|
||||
{
|
||||
}
|
||||
@@ -895,6 +900,11 @@ namespace AZ::Dom
|
||||
m_value = aznumeric_cast<double>(value);
|
||||
}
|
||||
|
||||
void Value::SetString(AZStd::shared_ptr<AZStd::string> string)
|
||||
{
|
||||
m_value = string;
|
||||
}
|
||||
|
||||
AZStd::string_view Value::GetString() const
|
||||
{
|
||||
switch (m_value.index())
|
||||
@@ -992,7 +1002,7 @@ namespace AZ::Dom
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Alternative, AZStd::shared_ptr<AZStd::string>>)
|
||||
{
|
||||
result = visitor.String(*arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent);
|
||||
result = visitor.RefCountedString(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent);
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Alternative, ObjectPtr>)
|
||||
{
|
||||
|
||||
@@ -127,6 +127,7 @@ namespace AZ::Dom
|
||||
Value(const Value&);
|
||||
Value(Value&&) noexcept;
|
||||
Value(AZStd::string_view string, bool copy);
|
||||
Value(AZStd::shared_ptr<AZStd::string> string);
|
||||
|
||||
Value(int32_t value);
|
||||
Value(uint32_t value);
|
||||
@@ -281,6 +282,7 @@ namespace AZ::Dom
|
||||
AZStd::string_view GetString() const;
|
||||
size_t GetStringLength() const;
|
||||
void SetString(AZStd::string_view);
|
||||
void SetString(AZStd::shared_ptr<AZStd::string>);
|
||||
void CopyFromString(AZStd::string_view);
|
||||
|
||||
// opaque type API...
|
||||
|
||||
@@ -68,6 +68,12 @@ namespace AZ::Dom
|
||||
return FinishWrite();
|
||||
}
|
||||
|
||||
Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr<AZStd::string> value, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
CurrentValue().SetString(value);
|
||||
return FinishWrite();
|
||||
}
|
||||
|
||||
Visitor::Result ValueWriter::StartObject()
|
||||
{
|
||||
CurrentValue().SetObject();
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace AZ::Dom
|
||||
Result Double(double value) override;
|
||||
|
||||
Result String(AZStd::string_view value, Lifetime lifetime) override;
|
||||
Result RefCountedString(AZStd::shared_ptr<AZStd::string> value, Lifetime lifetime) override;
|
||||
Result StartObject() override;
|
||||
Result EndObject(AZ::u64 attributeCount) override;
|
||||
Result Key(AZ::Name key) override;
|
||||
|
||||
@@ -105,6 +105,11 @@ namespace AZ::Dom
|
||||
return VisitorSuccess();
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr<AZStd::string> value, Lifetime lifetime)
|
||||
{
|
||||
return String(*value, lifetime);
|
||||
}
|
||||
|
||||
Visitor::Result Visitor::OpaqueValue([[maybe_unused]] const OpaqueType& value, [[maybe_unused]] Lifetime lifetime)
|
||||
{
|
||||
if (!SupportsOpaqueValues())
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/std/any.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
@@ -170,6 +171,7 @@ namespace AZ::Dom
|
||||
//! Operates on a string value. As strings are a reference type.
|
||||
//! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy.
|
||||
virtual Result String(AZStd::string_view value, Lifetime lifetime);
|
||||
virtual Result RefCountedString(AZStd::shared_ptr<AZStd::string> value, Lifetime lifetime);
|
||||
//! Operates on an opaque value. As opaque values are a reference type, storage semantics are provided to
|
||||
//! indicate where the value may be stored persistently or requires a copy.
|
||||
//! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Benchmark
|
||||
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
|
||||
}
|
||||
|
||||
AZStd::string GenerateDomJsonBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength)
|
||||
rapidjson::Document GenerateDomJsonBenchmarkDocument(int64_t entryCount, int64_t stringTemplateLength)
|
||||
{
|
||||
rapidjson::Document document;
|
||||
document.SetObject();
|
||||
@@ -108,6 +108,13 @@ namespace Benchmark
|
||||
document.SetObject();
|
||||
document.AddMember("entries", createObject(), document.GetAllocator());
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
AZStd::string GenerateDomJsonBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength)
|
||||
{
|
||||
rapidjson::Document document = GenerateDomJsonBenchmarkDocument(entryCount, stringTemplateLength);
|
||||
|
||||
AZStd::string serializedJson;
|
||||
auto result = AZ::JsonSerializationUtils::WriteJsonString(document, serializedJson);
|
||||
AZ_Assert(result.IsSuccess(), "Failed to serialize generated JSON");
|
||||
@@ -124,7 +131,7 @@ namespace Benchmark
|
||||
->Args({ 100, 500 }) \
|
||||
->Unit(benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDocumentInPlace)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
|
||||
@@ -146,9 +153,9 @@ namespace Benchmark
|
||||
|
||||
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDocumentInPlace)
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDomValueInPlace)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
|
||||
@@ -170,9 +177,9 @@ namespace Benchmark
|
||||
|
||||
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDomValueInPlace)
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDocument)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToRapidjson)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
|
||||
@@ -190,9 +197,29 @@ namespace Benchmark
|
||||
|
||||
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDocument)
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToRapidjson)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, JsonUtilsDeserializeToDocument)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToAzDomValue)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto result = AZ::Dom::Utils::WriteToValue(
|
||||
[&](AZ::Dom::Visitor& visitor)
|
||||
{
|
||||
return AZ::Dom::Utils::ReadFromString(backend, serializedPayload, AZ::Dom::Lifetime::Temporary, visitor);
|
||||
});
|
||||
|
||||
benchmark::DoNotOptimize(result.GetValue());
|
||||
}
|
||||
|
||||
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToAzDomValue)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonDeserializeToRapidjson)(benchmark::State& state)
|
||||
{
|
||||
AZ::Dom::JsonBackend backend;
|
||||
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
|
||||
@@ -206,9 +233,9 @@ namespace Benchmark
|
||||
|
||||
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, JsonUtilsDeserializeToDocument)
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeserializeToRapidjson)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonPayloadGeneration)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonMakeComplexObject)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
@@ -217,7 +244,44 @@ namespace Benchmark
|
||||
|
||||
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonPayloadGeneration)
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonMakeComplexObject)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonLookupMemberByString)(benchmark::State& state)
|
||||
{
|
||||
rapidjson::Document document(rapidjson::kObjectType);
|
||||
AZStd::vector<AZStd::string> keys;
|
||||
for (int64_t i = 0; i < state.range(0); ++i)
|
||||
{
|
||||
AZStd::string key(AZStd::string::format("key%" PRId64, i));
|
||||
keys.push_back(key);
|
||||
document.AddMember(rapidjson::Value(key.data(), static_cast<rapidjson::SizeType>(key.size()), document.GetAllocator()), rapidjson::Value(i), document.GetAllocator());
|
||||
}
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (const AZStd::string& key : keys)
|
||||
{
|
||||
benchmark::DoNotOptimize(document.FindMember(key.data()));
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * state.range(0));
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomJsonBenchmark, RapidjsonLookupMemberByString)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonDeepCopy)(benchmark::State& state)
|
||||
{
|
||||
rapidjson::Document original = GenerateDomJsonBenchmarkDocument(state.range(0), state.range(1));
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
rapidjson::Document copy;
|
||||
original.Accept(copy);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeepCopy)
|
||||
|
||||
#undef BENCHMARK_REGISTER_JSON
|
||||
} // namespace Benchmark
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <AzCore/DOM/DomValue.h>
|
||||
#include <AzCore/Name/NameDictionary.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace AZ::Dom::Benchmark
|
||||
{
|
||||
@@ -99,7 +100,7 @@ namespace AZ::Dom::Benchmark
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, ValuePayloadGeneration)(benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueMakeComplexObject)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
@@ -108,10 +109,115 @@ namespace AZ::Dom::Benchmark
|
||||
|
||||
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, ValuePayloadGeneration)
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueMakeComplexObject)
|
||||
->Args({ 10, 5 })
|
||||
->Args({ 10, 500 })
|
||||
->Args({ 100, 5 })
|
||||
->Args({ 100, 500 })
|
||||
->Unit(benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueShallowCopy)(benchmark::State& state)
|
||||
{
|
||||
Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
Value copy = original;
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueShallowCopy)
|
||||
->Args({ 10, 5 })
|
||||
->Args({ 10, 500 })
|
||||
->Args({ 100, 5 })
|
||||
->Args({ 100, 500 })
|
||||
->Unit(benchmark::kNanosecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueShallowCopyAndMutate)(benchmark::State& state)
|
||||
{
|
||||
Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
Value copy = original;
|
||||
copy["entries"]["Key0"].PushBack(42);
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueShallowCopyAndMutate)
|
||||
->Args({ 10, 5 })
|
||||
->Args({ 10, 500 })
|
||||
->Args({ 100, 5 })
|
||||
->Args({ 100, 500 })
|
||||
->Unit(benchmark::kNanosecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueDeepCopy)(benchmark::State& state)
|
||||
{
|
||||
Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
Value copy = original.DeepCopy();
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueDeepCopy)
|
||||
->Args({ 10, 5 })
|
||||
->Args({ 10, 500 })
|
||||
->Args({ 100, 5 })
|
||||
->Args({ 100, 500 })
|
||||
->Unit(benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByName)(benchmark::State& state)
|
||||
{
|
||||
Value value(Type::ObjectType);
|
||||
AZStd::vector<AZ::Name> keys;
|
||||
for (int64_t i = 0; i < state.range(0); ++i)
|
||||
{
|
||||
AZ::Name key(AZStd::string::format("key%" PRId64, i));
|
||||
keys.push_back(key);
|
||||
value[key] = i;
|
||||
}
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (const AZ::Name& key : keys)
|
||||
{
|
||||
benchmark::DoNotOptimize(value[key]);
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * state.range(0));
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, LookupMemberByName)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond);
|
||||
|
||||
BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByString)(benchmark::State& state)
|
||||
{
|
||||
Value value(Type::ObjectType);
|
||||
AZStd::vector<AZStd::string> keys;
|
||||
for (int64_t i = 0; i < state.range(0); ++i)
|
||||
{
|
||||
AZStd::string key(AZStd::string::format("key%" PRId64, i));
|
||||
keys.push_back(key);
|
||||
value[key] = i;
|
||||
}
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (const AZStd::string& key : keys)
|
||||
{
|
||||
benchmark::DoNotOptimize(value[key]);
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * state.range(0));
|
||||
}
|
||||
BENCHMARK_REGISTER_F(DomValueBenchmark, LookupMemberByString)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond);
|
||||
|
||||
} // namespace AZ::Dom::Benchmark
|
||||
|
||||
Reference in New Issue
Block a user