Skip to content

Commit 1a57ea0

Browse files
author
Bart Koelman
committed
Optimized response rendering time when no sparse fieldset is requested. This relies on the fact that the resource model is frozen after building the resource graph.
| Method | Mean | Error | StdDev | | ------------------------------------ | -------- | ------- | ------- | | SerializeOperationsResponse (before) | 168.6 us | 1.74 us | 1.63 us | | SerializeOperationsResponse (after) | 148.5 us | 1.06 us | 0.99 us | | SerializeResourceResponse (before) | 123.7 us | 1.12 us | 1.05 us | | SerializeResourceResponse (after) | 119.6 us | 1.05 us | 0.98 us | This makes SerializeOperationsResponse 12% faster and SerializeResourceResponse 3% faster. What the benchmark does not show is the performance improvement on subsequent requests, so in practice the gain in higher.
1 parent d45ebdd commit 1a57ea0

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

src/JsonApiDotNetCore/Queries/Internal/SparseFieldSetCache.cs

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Collections.Immutable;
45
using System.Linq;
@@ -12,6 +13,8 @@ namespace JsonApiDotNetCore.Queries.Internal
1213
/// <inheritdoc />
1314
public sealed class SparseFieldSetCache : ISparseFieldSetCache
1415
{
16+
private static readonly ConcurrentDictionary<ResourceType, SparseFieldSetExpression> ViewableFieldSetCache = new();
17+
1518
private readonly IResourceDefinitionAccessor _resourceDefinitionAccessor;
1619
private readonly Lazy<IDictionary<ResourceType, IImmutableSet<ResourceFieldAttribute>>> _lazySourceTable;
1720
private readonly IDictionary<ResourceType, IImmutableSet<ResourceFieldAttribute>> _visitedTable;
@@ -118,27 +121,37 @@ public IImmutableSet<ResourceFieldAttribute> GetSparseFieldSetForSerializer(Reso
118121

119122
if (!_visitedTable.ContainsKey(resourceType))
120123
{
121-
IImmutableSet<ResourceFieldAttribute> inputFields =
122-
_lazySourceTable.Value.TryGetValue(resourceType, out IImmutableSet<ResourceFieldAttribute>? fields)
123-
? fields
124-
: GetResourceFields(resourceType);
124+
SparseFieldSetExpression inputExpression =
125+
_lazySourceTable.Value.TryGetValue(resourceType, out IImmutableSet<ResourceFieldAttribute>? inputFields)
126+
? new SparseFieldSetExpression(inputFields)
127+
: GetCachedViewableFieldSet(resourceType);
125128

126-
var inputExpression = new SparseFieldSetExpression(inputFields);
127129
SparseFieldSetExpression? outputExpression = _resourceDefinitionAccessor.OnApplySparseFieldSet(resourceType, inputExpression);
128130

129-
IImmutableSet<ResourceFieldAttribute> outputFields =
130-
outputExpression == null ? GetResourceFields(resourceType) : inputFields.Intersect(outputExpression.Fields);
131+
IImmutableSet<ResourceFieldAttribute> outputFields = outputExpression == null
132+
? GetCachedViewableFieldSet(resourceType).Fields
133+
: inputExpression.Fields.Intersect(outputExpression.Fields);
131134

132135
_visitedTable[resourceType] = outputFields;
133136
}
134137

135138
return _visitedTable[resourceType];
136139
}
137140

138-
private IImmutableSet<ResourceFieldAttribute> GetResourceFields(ResourceType resourceType)
141+
private static SparseFieldSetExpression GetCachedViewableFieldSet(ResourceType resourceType)
139142
{
140-
ArgumentGuard.NotNull(resourceType, nameof(resourceType));
143+
if (!ViewableFieldSetCache.TryGetValue(resourceType, out SparseFieldSetExpression? fieldSet))
144+
{
145+
IImmutableSet<ResourceFieldAttribute> viewableFields = GetViewableFields(resourceType);
146+
fieldSet = new SparseFieldSetExpression(viewableFields);
147+
ViewableFieldSetCache[resourceType] = fieldSet;
148+
}
141149

150+
return fieldSet;
151+
}
152+
153+
private static IImmutableSet<ResourceFieldAttribute> GetViewableFields(ResourceType resourceType)
154+
{
142155
ImmutableHashSet<ResourceFieldAttribute>.Builder fieldSetBuilder = ImmutableHashSet.CreateBuilder<ResourceFieldAttribute>();
143156

144157
foreach (AttrAttribute attribute in resourceType.Attributes.Where(attr => attr.Capabilities.HasFlag(AttrCapabilities.AllowView)))

0 commit comments

Comments
 (0)