Skip to content

Commit fe37d6a

Browse files
committed
Improve change tracking performance
| Method | Mean | Error | StdDev | Ratio | Gen0 | Allocated | Alloc Ratio | |---------------- |---------:|----------:|----------:|------:|-------:|----------:|------------:| | TrackChanges | 3.741 us | 0.0122 us | 0.0114 us | 1.00 | 0.0229 | 6.41 KB | 1.00 | | NewTrackChanges | 1.359 us | 0.0070 us | 0.0066 us | 0.36 | 0.0095 | 2.62 KB | 0.41 | using BenchmarkDotNet.Attributes; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; using Microsoft.Extensions.Logging.Abstractions; namespace Benchmarks.ChangeTracking; // ReSharper disable once ClassCanBeSealed.Global [MarkdownExporter] [MemoryDiagnoser] public class ChangeTrackerBenchmarks { private readonly JsonApiRequest _request; private readonly TargetedFields _targetedFields; public ChangeTrackerBenchmarks() { IJsonApiOptions options = new JsonApiOptions(); IResourceGraph resourceGraph = new ResourceGraphBuilder(options, NullLoggerFactory.Instance).Add<ExampleResource, long>().Build(); ResourceType resourceType = resourceGraph.GetResourceType<ExampleResource>(); _request = new JsonApiRequest { PrimaryResourceType = resourceType, IsCollection = true }; _targetedFields = new TargetedFields(); foreach (AttrAttribute attribute in resourceType.Attributes) { _targetedFields.Attributes.Add(attribute); } } [Benchmark(Baseline = true)] public void TrackChanges() { var changeTracker = new ResourceChangeTracker<ExampleResource>(_request, _targetedFields); var resource = new ExampleResource { Id = 1, Attr1 = "some", Attr2 = "more", Attr3 = "other", Attr4 = false, Attr5 = 123, Attr6 = default, Attr7 = default, Attr8 = default, Attr9 = DayOfWeek.Sunday }; changeTracker.SetInitiallyStoredAttributeValues(resource); resource = new ExampleResource { Id = 1, Attr1 = "new", Attr2 = "change", Attr3 = "this", Attr4 = true, Attr5 = 456, Attr6 = default, Attr7 = default, Attr8 = default, Attr9 = DayOfWeek.Saturday }; changeTracker.SetFinallyStoredAttributeValues(resource); changeTracker.HasImplicitChanges(); } [Benchmark] public void NewTrackChanges() { var changeTracker = new NewResourceChangeTracker<ExampleResource>(_request, _targetedFields); var resource = new ExampleResource { Id = 1, Attr1 = "some", Attr2 = "more", Attr3 = "other", Attr4 = false, Attr5 = 123, Attr6 = default, Attr7 = default, Attr8 = default, Attr9 = DayOfWeek.Sunday }; changeTracker.SetInitiallyStoredAttributeValues(resource); resource = new ExampleResource { Id = 1, Attr1 = "new", Attr2 = "change", Attr3 = "this", Attr4 = true, Attr5 = 456, Attr6 = default, Attr7 = default, Attr8 = default, Attr9 = DayOfWeek.Saturday }; changeTracker.SetFinallyStoredAttributeValues(resource); changeTracker.HasImplicitChanges(); } private sealed class ExampleResource : Identifiable<long> { [Attr] public string? Attr1 { get; set; } [Attr] public string? Attr2 { get; set; } [Attr] public string? Attr3 { get; set; } [Attr] public bool Attr4 { get; set; } [Attr] public int Attr5 { get; set; } [Attr] public DateTime Attr6 { get; set; } [Attr] public DateTimeOffset Attr7 { get; set; } [Attr] public TimeSpan Attr8 { get; set; } [Attr] public DayOfWeek Attr9 { get; set; } } }
1 parent 653d52a commit fe37d6a

File tree

1 file changed

+12
-14
lines changed

1 file changed

+12
-14
lines changed

src/JsonApiDotNetCore/Resources/ResourceChangeTracker.cs

+12-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Text.Json;
21
using JetBrains.Annotations;
32
using JsonApiDotNetCore.Middleware;
43
using JsonApiDotNetCore.Resources.Annotations;
@@ -13,9 +12,9 @@ public sealed class ResourceChangeTracker<TResource> : IResourceChangeTracker<TR
1312
private readonly IJsonApiRequest _request;
1413
private readonly ITargetedFields _targetedFields;
1514

16-
private IDictionary<string, string>? _initiallyStoredAttributeValues;
17-
private IDictionary<string, string>? _requestAttributeValues;
18-
private IDictionary<string, string>? _finallyStoredAttributeValues;
15+
private IDictionary<string, object?>? _initiallyStoredAttributeValues;
16+
private IDictionary<string, object?>? _requestAttributeValues;
17+
private IDictionary<string, object?>? _finallyStoredAttributeValues;
1918

2019
public ResourceChangeTracker(IJsonApiRequest request, ITargetedFields targetedFields)
2120
{
@@ -50,15 +49,14 @@ public void SetFinallyStoredAttributeValues(TResource resource)
5049
_finallyStoredAttributeValues = CreateAttributeDictionary(resource, _request.PrimaryResourceType!.Attributes);
5150
}
5251

53-
private IDictionary<string, string> CreateAttributeDictionary(TResource resource, IEnumerable<AttrAttribute> attributes)
52+
private IDictionary<string, object?> CreateAttributeDictionary(TResource resource, IEnumerable<AttrAttribute> attributes)
5453
{
55-
var result = new Dictionary<string, string>();
54+
var result = new Dictionary<string, object?>();
5655

5756
foreach (AttrAttribute attribute in attributes)
5857
{
5958
object? value = attribute.GetValue(resource);
60-
string json = JsonSerializer.Serialize(value);
61-
result.Add(attribute.PublicName, json);
59+
result.Add(attribute.PublicName, value);
6260
}
6361

6462
return result;
@@ -71,21 +69,21 @@ public bool HasImplicitChanges()
7169
{
7270
foreach (string key in _initiallyStoredAttributeValues.Keys)
7371
{
74-
if (_requestAttributeValues.TryGetValue(key, out string? requestValue))
72+
if (_requestAttributeValues.TryGetValue(key, out object? requestValue))
7573
{
76-
string actualValue = _finallyStoredAttributeValues[key];
74+
object? actualValue = _finallyStoredAttributeValues[key];
7775

78-
if (requestValue != actualValue)
76+
if (!Equals(requestValue, actualValue))
7977
{
8078
return true;
8179
}
8280
}
8381
else
8482
{
85-
string initiallyStoredValue = _initiallyStoredAttributeValues[key];
86-
string finallyStoredValue = _finallyStoredAttributeValues[key];
83+
object? initiallyStoredValue = _initiallyStoredAttributeValues[key];
84+
object? finallyStoredValue = _finallyStoredAttributeValues[key];
8785

88-
if (initiallyStoredValue != finallyStoredValue)
86+
if (!Equals(initiallyStoredValue, finallyStoredValue))
8987
{
9088
return true;
9189
}

0 commit comments

Comments
 (0)