Address some more Generic Dom Value perf feedback

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
monroegm-disable-blank-issue-2
Nicholas Van Sickle 4 years ago
parent 1da99eaea0
commit 37330c43a9

@ -373,10 +373,6 @@ namespace AZ::Dom::Json
bool RapidJsonReadHandler::Key(const char* str, rapidjson::SizeType length, [[maybe_unused]] bool copy)
{
AZStd::string_view key = AZStd::string_view(str, length);
if (!m_visitor->SupportsRawKeys())
{
m_visitor->Key(AZ::Name(key));
}
const Lifetime lifetime = !copy ? m_stringLifetime : Lifetime::Temporary;
return CheckResult(m_visitor->RawKey(key, lifetime));
}

@ -17,13 +17,15 @@ namespace AZ::Dom
template<class T>
AZStd::shared_ptr<T>& CheckCopyOnWrite(AZStd::shared_ptr<T>& refCountedPointer)
{
if (refCountedPointer.use_count() > 1)
if (refCountedPointer.use_count() == 1)
{
AZStd::shared_ptr<T> newPointer = AZStd::allocate_shared<T>(StdValueAllocator());
*newPointer = *refCountedPointer;
refCountedPointer = AZStd::move(newPointer);
return refCountedPointer;
}
else
{
refCountedPointer = AZStd::allocate_shared<T>(StdValueAllocator(), *refCountedPointer);
return refCountedPointer;
}
return refCountedPointer;
}
namespace Internal
@ -72,7 +74,7 @@ namespace AZ::Dom
}
Node::Node(AZ::Name name)
: m_name(name)
: m_name(AZStd::move(name))
{
}
@ -83,7 +85,7 @@ namespace AZ::Dom
void Node::SetName(AZ::Name name)
{
m_name = name;
m_name = AZStd::move(name);
}
Object::ContainerType& Node::GetProperties()
@ -106,8 +108,8 @@ namespace AZ::Dom
return m_children;
}
Value::Value(AZStd::shared_ptr<const AZStd::string> string)
: m_value(string)
Value::Value(SharedStringType sharedString)
: m_value(AZStd::move(sharedString))
{
}
@ -122,18 +124,19 @@ namespace AZ::Dom
Value::Value(Value&& value) noexcept
{
operator=(value);
memcpy(this, &value, sizeof(Value));
memset(&value, 0, sizeof(Value));
}
Value::Value(AZStd::string_view string, bool copy)
Value::Value(AZStd::string_view stringView, bool copy)
{
if (copy)
{
CopyFromString(string);
CopyFromString(stringView);
}
else
{
SetString(string);
SetString(stringView);
}
}
@ -227,7 +230,9 @@ namespace AZ::Dom
Value& Value::operator=(Value&& other) noexcept
{
m_value.swap(other.m_value);
SetNull();
memcpy(this, &other, sizeof(Value));
memset(&other, 0, sizeof(Value));
return *this;
}
@ -265,7 +270,10 @@ namespace AZ::Dom
void Value::Swap(Value& other) noexcept
{
m_value.swap(other.m_value);
AZStd::aligned_storage_for_t<Value> temp;
memcpy(&temp, this, sizeof(Value));
memcpy(this, &other, sizeof(Value));
memcpy(&other, &temp, sizeof(Value));
}
Type Dom::Value::GetType() const
@ -583,7 +591,7 @@ namespace AZ::Dom
}
else
{
object.emplace_back(name, value);
object.emplace_back(AZStd::move(name), value);
}
return *this;
}
@ -602,7 +610,7 @@ namespace AZ::Dom
}
else
{
object.emplace_back(name, value);
object.emplace_back(AZStd::move(name), value);
}
return *this;
}
@ -636,15 +644,12 @@ namespace AZ::Dom
Object::Iterator Value::RemoveMember(Object::Iterator pos)
{
Object::ContainerType& object = GetObjectInternal();
Object::Iterator nextIndex = object.end();
auto lastEntry = object.end() - 1;
if (pos != lastEntry)
if (!object.empty())
{
AZStd::swap(*pos, *lastEntry);
nextIndex = pos;
AZStd::swap(*pos, object.back());
object.pop_back();
}
object.resize(object.size() - 1);
return nextIndex;
return object.end();
}
Object::Iterator Value::EraseMember(Object::ConstIterator pos)
@ -785,7 +790,7 @@ namespace AZ::Dom
void Value::SetNode(AZ::Name name)
{
m_value = AZStd::allocate_shared<Node>(StdValueAllocator(), name);
m_value = AZStd::allocate_shared<Node>(StdValueAllocator(), AZStd::move(name));
}
void Value::SetNode(AZStd::string_view name)
@ -800,7 +805,7 @@ namespace AZ::Dom
void Value::SetNodeName(AZ::Name name)
{
GetNodeInternal().SetName(name);
GetNodeInternal().SetName(AZStd::move(name));
}
void Value::SetNodeName(AZStd::string_view name)

@ -190,8 +190,8 @@ namespace AZ::Dom
Value();
Value(const Value&);
Value(Value&&) noexcept;
Value(AZStd::string_view string, bool copy);
Value(AZStd::shared_ptr<const AZStd::string> string);
Value(AZStd::string_view stringView, bool copy);
Value(SharedStringType sharedString);
Value(int32_t value);
Value(uint32_t value);

@ -82,6 +82,16 @@ namespace AZ::Dom
return VisitorSuccess();
}
template <class T, class A>
void MoveVectorMemory(AZStd::vector<T, A>& dest, AZStd::vector<T, A>& source)
{
dest.resize_no_construct(source.size());
const size_t size = sizeof(T) * source.size();
memcpy(dest.data(), source.data(), size);
memset(source.data(), 0, size);
source.resize(0);
}
Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount)
{
const char* endMethodName;
@ -138,22 +148,12 @@ namespace AZ::Dom
}
if (buffer.m_attributes.size() > 0)
{
container.MemberReserve(buffer.m_attributes.size());
for (AZStd::pair<AZ::Name, Value>& entry : buffer.m_attributes)
{
container.AddMember(AZStd::move(entry.first), AZStd::move(entry.second));
}
buffer.m_attributes.clear();
MoveVectorMemory(container.GetMutableObject(), buffer.m_attributes);
}
if(buffer.m_elements.size() > 0)
{
container.Reserve(buffer.m_elements.size());
for (Value& entry : buffer.m_elements)
{
container.PushBack(AZStd::move(entry));
}
buffer.m_elements.clear();
MoveVectorMemory(container.GetMutableArray(), buffer.m_elements);
}
m_entryStack.pop();
@ -180,7 +180,7 @@ namespace AZ::Dom
{
AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object");
AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array");
m_entryStack.top().m_key = key;
m_entryStack.top().m_key = AZStd::move(key);
return VisitorSuccess();
}

@ -120,6 +120,16 @@ namespace Benchmark
AZ_Assert(result.IsSuccess(), "Failed to serialize generated JSON");
return serializedJson;
}
template <class T>
void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state)
{
{
T instance = AZStd::move(value);
state.PauseTiming();
}
state.ResumeTiming();
}
};
// Helper macro for registering JSON benchmarks
@ -148,7 +158,7 @@ namespace Benchmark
return AZ::Dom::Utils::ReadFromStringInPlace(backend, payloadCopy, visitor);
});
benchmark::DoNotOptimize(result.GetValue());
TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state);
}
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
@ -172,7 +182,7 @@ namespace Benchmark
return AZ::Dom::Utils::ReadFromStringInPlace(backend, payloadCopy, visitor);
});
benchmark::DoNotOptimize(result.GetValue());
TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state);
}
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
@ -192,7 +202,7 @@ namespace Benchmark
return AZ::Dom::Utils::ReadFromString(backend, serializedPayload, AZ::Dom::Lifetime::Temporary, visitor);
});
benchmark::DoNotOptimize(result.GetValue());
TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state);
}
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
@ -212,7 +222,7 @@ namespace Benchmark
return AZ::Dom::Utils::ReadFromString(backend, serializedPayload, AZ::Dom::Lifetime::Temporary, visitor);
});
benchmark::DoNotOptimize(result.GetValue());
TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state);
}
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
@ -228,7 +238,7 @@ namespace Benchmark
{
auto result = AZ::JsonSerializationUtils::ReadJsonString(serializedPayload);
benchmark::DoNotOptimize(result.GetValue());
TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state);
}
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
@ -239,7 +249,7 @@ namespace Benchmark
{
for (auto _ : state)
{
benchmark::DoNotOptimize(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)));
TakeAndDiscardWithoutTimingDtor(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)), state);
}
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
@ -277,7 +287,7 @@ namespace Benchmark
{
rapidjson::Document copy;
copy.CopyFrom(original, copy.GetAllocator(), true);
benchmark::DoNotOptimize(copy);
TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state);
}
state.SetItemsProcessed(state.iterations());
@ -294,7 +304,7 @@ namespace Benchmark
rapidjson::Document copy;
copy.CopyFrom(original, copy.GetAllocator(), true);
copy["entries"]["Key0"].PushBack(42, copy.GetAllocator());
benchmark::DoNotOptimize(copy);
TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state);
}
state.SetItemsProcessed(state.iterations());

@ -98,13 +98,23 @@ namespace AZ::Dom::Benchmark
return root;
}
template<class T>
void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state)
{
{
T instance = AZStd::move(value);
state.PauseTiming();
}
state.ResumeTiming();
}
};
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueMakeComplexObject)(benchmark::State& state)
{
for (auto _ : state)
{
benchmark::DoNotOptimize(GenerateDomBenchmarkPayload(state.range(0), state.range(1)));
TakeAndDiscardWithoutTimingDtor(GenerateDomBenchmarkPayload(state.range(0), state.range(1)), state);
}
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
@ -143,7 +153,7 @@ namespace AZ::Dom::Benchmark
{
Value copy = original;
copy["entries"]["Key0"].PushBack(42);
benchmark::DoNotOptimize(copy);
TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state);
}
state.SetItemsProcessed(state.iterations());
@ -162,7 +172,7 @@ namespace AZ::Dom::Benchmark
for (auto _ : state)
{
Value copy = original.DeepCopy();
benchmark::DoNotOptimize(copy);
TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state);
}
state.SetItemsProcessed(state.iterations());

Loading…
Cancel
Save