Add another round of benchmarks

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-12-11 15:54:57 -08:00
parent 1f2635d24b
commit c53c97cf5f
8 changed files with 210 additions and 14 deletions
+11 -1
View File
@@ -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