Commit Graph

28 Commits (a2d86a9fa495ed08435bb0393aaf5fae188b68df)

Author SHA1 Message Date
Chris Burel 377da0ed0c Ignore unused benchmark state variables
Signed-off-by: Chris Burel <burelc@amazon.com>
4 years ago
Chris Burel 664403c5de Mark benchmark state variables in for loops as unused in benchmarks
Signed-off-by: Chris Burel <burelc@amazon.com>
4 years ago
Nicholas Van Sickle 42c2243eaa Fix benchmark non-unity build
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle d1bb5a0543 Move DOM delta comparison to its own file, enhance inverting moves
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 5b8176e99b Address some review feedback
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 73f166241e Address review feedback
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle e06b8782cc Add AZ::Dom::Patch, a Generic DOM analog to JSON patch
- Currently supports JSON patch operations (add/remove/replace/copy/move/test)
- `GenerateHierarchicalDeltaPatch` provides a patch generation mechanism that produces forward and inverse patches
- Patch application comes with a `PatchApplicationStrategy` functor that allows customizing behavior for patch failure that may be useful for the prefab system
- Serialization to/from JSON patch by way of `AZ::Dom::Value` is supported

Benchmarks provided, split into three categories on the Dom value benchmark payload (payloads with up to 10k entries populated with strings up to 100 characters in length):
- Patch generation based on a deep copy of the affected data
```
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_DeepCopy/10/5            0.024 ms        0.024 ms        29867 items_per_second=41.5541k/s
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_DeepCopy/10/500          0.024 ms        0.024 ms        29867 items_per_second=41.5541k/s
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_DeepCopy/100/5           0.346 ms        0.345 ms         2036 items_per_second=2.89564k/s
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_DeepCopy/100/500         0.375 ms        0.377 ms         1867 items_per_second=2.65529k/s
DomPatchBenchmark/AzDomPatch_Generate_TopLevelReplace/10/5                   0.003 ms        0.003 ms       203636 items_per_second=289.616k/s
DomPatchBenchmark/AzDomPatch_Generate_TopLevelReplace/10/500                 0.004 ms        0.004 ms       194783 items_per_second=283.321k/s
DomPatchBenchmark/AzDomPatch_Generate_TopLevelReplace/100/5                  0.003 ms        0.003 ms       203636 items_per_second=289.616k/s
DomPatchBenchmark/AzDomPatch_Generate_TopLevelReplace/100/500                0.004 ms        0.004 ms       194783 items_per_second=271.002k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_DeepCopy/10/5                0.023 ms        0.024 ms        29867 items_per_second=42.4775k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_DeepCopy/10/500              0.023 ms        0.023 ms        28000 items_per_second=42.6667k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_DeepCopy/100/5               0.341 ms        0.337 ms         2133 items_per_second=2.96765k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_DeepCopy/100/500             0.365 ms        0.361 ms         1948 items_per_second=2.77049k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_DeepCopy/10/5              0.023 ms        0.023 ms        29867 items_per_second=43.4429k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_DeepCopy/10/500            0.023 ms        0.024 ms        29867 items_per_second=42.4775k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_DeepCopy/100/5             0.330 ms        0.330 ms         2133 items_per_second=3.0336k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_DeepCopy/100/500           0.359 ms        0.360 ms         1867 items_per_second=2.77879k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_DeepCopy/10/5             0.023 ms        0.022 ms        29867 items_per_second=44.4532k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_DeepCopy/10/500           0.023 ms        0.023 ms        32000 items_per_second=43.5745k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_DeepCopy/100/5            0.329 ms        0.330 ms         2133 items_per_second=3.0336k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_DeepCopy/100/500          0.357 ms        0.361 ms         1948 items_per_second=2.77049k/s
```
- Patch generation based on a shallow copy of the affected data (this is faster because when using Dom::Value to copy and mutate, we can bypass expensive array and object comparisons for identical values)
```
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_ShallowCopy/10/5         0.010 ms        0.010 ms        74667 items_per_second=99.556k/s
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_ShallowCopy/10/500       0.010 ms        0.010 ms        74667 items_per_second=97.5242k/s
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_ShallowCopy/100/5        0.079 ms        0.078 ms         8960 items_per_second=12.7431k/s
DomPatchBenchmark/AzDomPatch_Generate_SimpleReplace_ShallowCopy/100/500      0.087 ms        0.087 ms         8960 items_per_second=11.4688k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_ShallowCopy/10/5             0.009 ms        0.009 ms        74667 items_per_second=116.553k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_ShallowCopy/10/500           0.009 ms        0.009 ms        74667 items_per_second=113.778k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_ShallowCopy/100/5            0.072 ms        0.071 ms         8960 items_per_second=13.9863k/s
DomPatchBenchmark/AzDomPatch_Generate_KeyRemove_ShallowCopy/100/500          0.087 ms        0.088 ms         7467 items_per_second=11.3783k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_ShallowCopy/10/5           0.014 ms        0.014 ms        49778 items_per_second=72.4044k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_ShallowCopy/10/500         0.014 ms        0.014 ms        56000 items_per_second=70.2745k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_ShallowCopy/100/5          0.118 ms        0.117 ms         5600 items_per_second=8.53333k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayAppend_ShallowCopy/100/500        0.140 ms        0.141 ms         4978 items_per_second=7.07982k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_ShallowCopy/10/5          0.009 ms        0.009 ms        89600 items_per_second=108.196k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_ShallowCopy/10/500        0.009 ms        0.009 ms        74667 items_per_second=108.607k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_ShallowCopy/100/5         0.068 ms        0.068 ms        11200 items_per_second=14.6286k/s
DomPatchBenchmark/AzDomPatch_Generate_ArrayPrepend_ShallowCopy/100/500       0.082 ms        0.082 ms         8960 items_per_second=12.2009k/s
```
- Patch application
```
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_ShallowCopy/10/5            0.001 ms        0.001 ms       560000 items_per_second=874.146k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_ShallowCopy/10/500          0.001 ms        0.001 ms       560000 items_per_second=874.146k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_ShallowCopy/100/5           0.004 ms        0.004 ms       172308 items_per_second=250.63k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_ShallowCopy/100/500         0.004 ms        0.004 ms       179200 items_per_second=260.655k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_DeepCopy/10/5               0.005 ms        0.005 ms       112000 items_per_second=193.73k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_DeepCopy/10/500             0.005 ms        0.005 ms       112000 items_per_second=193.73k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_DeepCopy/100/5              0.052 ms        0.052 ms        10000 items_per_second=19.3939k/s
DomPatchBenchmark/AzDomPatch_Apply_SimpleReplace_DeepCopy/100/500            0.052 ms        0.052 ms        11200 items_per_second=19.373k/s
DomPatchBenchmark/AzDomPatch_Apply_TopLevelReplace/10/5                      0.001 ms        0.001 ms       640000 items_per_second=910.222k/s
DomPatchBenchmark/AzDomPatch_Apply_TopLevelReplace/10/500                    0.001 ms        0.001 ms       640000 items_per_second=910.222k/s
DomPatchBenchmark/AzDomPatch_Apply_TopLevelReplace/100/5                     0.001 ms        0.001 ms       640000 items_per_second=910.222k/s
DomPatchBenchmark/AzDomPatch_Apply_TopLevelReplace/100/500                   0.001 ms        0.001 ms       640000 items_per_second=910.222k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_ShallowCopy/10/5                0.001 ms        0.001 ms       560000 items_per_second=896k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_ShallowCopy/10/500              0.001 ms        0.001 ms       640000 items_per_second=871.489k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_ShallowCopy/100/5               0.004 ms        0.004 ms       160000 items_per_second=232.727k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_ShallowCopy/100/500             0.004 ms        0.004 ms       165926 items_per_second=235.984k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_DeepCopy/10/5                   0.005 ms        0.005 ms       112000 items_per_second=193.73k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_DeepCopy/10/500                 0.005 ms        0.005 ms       112000 items_per_second=193.73k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_DeepCopy/100/5                  0.053 ms        0.053 ms        10000 items_per_second=18.8235k/s
DomPatchBenchmark/AzDomPatch_Apply_KeyRemove_DeepCopy/100/500                0.051 ms        0.052 ms        10000 items_per_second=19.3939k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_ShallowCopy/10/5              0.001 ms        0.001 ms       497778 items_per_second=692.561k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_ShallowCopy/10/500            0.001 ms        0.001 ms       497778 items_per_second=692.561k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_ShallowCopy/100/5             0.006 ms        0.006 ms       112000 items_per_second=174.829k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_ShallowCopy/100/500           0.006 ms        0.006 ms       100000 items_per_second=177.778k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_DeepCopy/10/5                 0.005 ms        0.005 ms       112000 items_per_second=193.73k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_DeepCopy/10/500               0.005 ms        0.005 ms       100000 items_per_second=188.235k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_DeepCopy/100/5                0.053 ms        0.052 ms        11200 items_per_second=19.373k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayAppend_DeepCopy/100/500              0.052 ms        0.053 ms        11200 items_per_second=18.8632k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_ShallowCopy/10/5             0.001 ms        0.001 ms       560000 items_per_second=874.146k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_ShallowCopy/10/500           0.001 ms        0.001 ms       560000 items_per_second=874.146k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_ShallowCopy/100/5            0.004 ms        0.004 ms       179200 items_per_second=260.655k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_ShallowCopy/100/500          0.004 ms        0.004 ms       179200 items_per_second=260.655k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_DeepCopy/10/5                0.005 ms        0.005 ms       100000 items_per_second=193.939k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_DeepCopy/10/500              0.005 ms        0.005 ms       100000 items_per_second=193.939k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_DeepCopy/100/5               0.052 ms        0.052 ms        11200 items_per_second=19.373k/s
DomPatchBenchmark/AzDomPatch_Apply_ArrayPrepend_DeepCopy/100/500             0.053 ms        0.053 ms        10000 items_per_second=18.8235k/s
```

At a glance, patch generation using `GenerateHierarchicalDeltaPatch` is slower than applying its created patches, but not prohibitively so. Ideally patches shouldn't be recreated unnecessarily, but especially when diffing `Value`s that have been copied and then mutated, a generate + apply operation similar to what prefabs currently do is reasonably fast.

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 32e2ba754b
Add Dom::Path class for representing positions in a Dom (#7008)
* Add Dom::Path class for representing positions in a Dom

This also adds Value support for doing a path-based lookup.

The serialized representation is presently compliant with the JSON-pointer spec but the implementation supports Node types and may be later expanded if we require additional functionality (e.g. XPath style conditional querying).

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle cfd721bce1
A bit of Generic DOM tidying/fixup (#6914)
* A bit of Generic DOM tidying/fixup

- Refactor out a test fixture for all DOM tests / benchmarks
- Optimize `GetType` implementation to not use `AZStd::variant::visit` (benchmark included to A/B the implementations)
- Tag a few more mutating Value functions with "Mutable" to avoid astonishing copy-on-writes

Benchmark results for GetType implementation:
```
DomValueBenchmark/AzDomValueGetType_UsingVariantIndex              18.2 ns         18.0 ns     40727273 items_per_second=443.667M/s
DomValueBenchmark/AzDomValueGetType_UsingVariantVisit              32.2 ns         32.2 ns     21333333 items_per_second=248.242M/s
```

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle e7f573d22a Make Value ctor explicit
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle acc6248ec9 Move deep comparison / copy to utils
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 41c0fb2b02 Address some review feedback
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 37330c43a9 Address some more Generic Dom Value perf feedback
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle bbd00adade Address some AZ::Dom::Value feedback
- Use a vector for shared string storage (to avoid the double heap allocation for AZStd::string)
- Use a shared heap allocated any for opaque types (instead of an unsafe ref)
- Add a string comparison key lookup benchmark to measure the impact of Name

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 8da04f15d3 Add some Value documentation
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle d9ac3c2120 Tidy up Type enum
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle cc120c772c Add RapidjsonCopyAndMutate to compare w/ shallow copy
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle c53c97cf5f Add another round of benchmarks
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 1af39a5c5c Add benchmarks, some light optimizations like SSO
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 947951b6c7 Add copy on write tests
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 15e0bb1693 Add tests, fix missing bool in Accept and operator[] insert
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle a2d474cc4f Add some intial tests
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 6cf805256b Make backend write API string-based
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 8165f54c05 Use temporary lifetimes for test
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 4dbce4275b Refactor the interface after some chatting with @amazon-employee-dm
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle a9c05372d5 API tweaks
- Use ref types
- Support using rapidjson::Value in lieu of rapidjson::Document
- Use the existing JSON comparison util function in tests

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle 5dbe9e387b Address some review feedback, remove DomBackendRegistry
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago
Nicholas Van Sickle e9a57380bb Generic DOM: Add DomBackend abstraction and JSON support
This change adds a `DomBackend` interface and a `DomBackendRegistry` for backend discovery (currently not hooked up to anything) alongside a JSON backend implementation.

The JSON backend comes with a small suite of unit and performance tests. The unit tests validate generic DOM conversion to and from serialized JSON and rapidjson::Document objects (the support for which lives in `JsonSerializationUtils.h`).

The performance tests show a throughput decrease compared to directly using the rapidjson serializer when mirroring our current pattern of copying strings from the serialized JSON representation, but with the coming in-memory store we have the opportunity to keep the buffer in memory and deserialize in-situ using rapidjson's API, which is consistently at least 100MiB/s faster on my machine (Ryzen Threadripper 3970X). The first parameter is the nested object complexity (N*N, objects with N keys comprised of arrays with N values) and the second parameter is the base size of the strings within each entry of this object.
```
----------------------------------------------------------------------------------------------------------------------
Benchmark                                                            Time             CPU   Iterations UserCounters...
----------------------------------------------------------------------------------------------------------------------
DomJsonBenchmark/DomDeserializeToDocumentInPlace/10/5            0.050 ms        0.050 ms        10000 bytes_per_second=355.816M/s
DomJsonBenchmark/DomDeserializeToDocumentInPlace/10/50           0.057 ms        0.057 ms        11200 bytes_per_second=386.064M/s
DomJsonBenchmark/DomDeserializeToDocumentInPlace/100/5            4.77 ms         4.88 ms          112 bytes_per_second=364.046M/s
DomJsonBenchmark/DomDeserializeToDocumentInPlace/100/500          11.6 ms         11.7 ms           64 bytes_per_second=554.518M/s
DomJsonBenchmark/DomDeserializeToDocumentWithCopies/10/5         0.084 ms        0.084 ms         7467 bytes_per_second=212.55M/s
DomJsonBenchmark/DomDeserializeToDocumentWithCopies/10/50        0.099 ms        0.100 ms         6400 bytes_per_second=220.608M/s
DomJsonBenchmark/DomDeserializeToDocumentWithCopies/100/5         8.22 ms         8.16 ms           90 bytes_per_second=217.847M/s
DomJsonBenchmark/DomDeserializeToDocumentWithCopies/100/500       23.2 ms         22.9 ms           30 bytes_per_second=283.56M/s
DomJsonBenchmark/JsonUtilsDeserializeToDocument/10/5             0.070 ms        0.070 ms        11200 bytes_per_second=255.049M/s
DomJsonBenchmark/JsonUtilsDeserializeToDocument/10/50            0.086 ms        0.087 ms         8960 bytes_per_second=253.258M/s
DomJsonBenchmark/JsonUtilsDeserializeToDocument/100/5             6.86 ms         6.84 ms          112 bytes_per_second=260.033M/s
DomJsonBenchmark/JsonUtilsDeserializeToDocument/100/500           22.8 ms         22.9 ms           32 bytes_per_second=283.158M/s
```

For `AZ::DOM::Document`, the current plan is to offer helper methods that can load from a file path or string using a given backend that can take advantage of in-place parsing by internally storing the serialized buffer.

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
4 years ago