Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perf-improvement: CreateEtag method #1081

Merged

Conversation

ElizabethOkerio
Copy link
Contributor

@ElizabethOkerio ElizabethOkerio commented Nov 1, 2023

The CreateEtag method creates an ETag for a given entity. This method is called for every resource and seems to take-up a lot of CPU time even in cases where ETags are not being created.

c1

This is how the CreateEtag method looks like:

 public virtual string CreateETag(ResourceContext resourceContext)
 {
     if (resourceContext == null)
     {
         throw Error.ArgumentNull(nameof(resourceContext));
     }

     if (resourceContext.Request != null)
     {
         IEdmModel model = resourceContext.EdmModel;
         IEdmNavigationSource navigationSource = resourceContext.NavigationSource;

         IEnumerable<IEdmStructuralProperty> concurrencyProperties;
         if (model != null && navigationSource != null)
         {
             concurrencyProperties = model.GetConcurrencyProperties(navigationSource).OrderBy(c => c.Name);
         }
         else
         {
             concurrencyProperties = Enumerable.Empty<IEdmStructuralProperty>();
         }

         IDictionary<string, object> properties = new Dictionary<string, object>();
         foreach (IEdmStructuralProperty etagProperty in concurrencyProperties)
         {
             properties.Add(etagProperty.Name, resourceContext.GetPropertyValue(etagProperty.Name));
         }

         return resourceContext.Request.CreateETag(properties, resourceContext.TimeZone);
     }

     return null;
 }

We call return resourceContext.Request.CreateETag(properties, resourceContext.TimeZone) every time even when the properties are null. This call involves getting the ETag handler from the DI container which seems to take up some CPU time.. Adding a check to only call this method when the concurrency properties are not null seems to improve CPU usage a bit.

c2

Comparing the before and after CPU usage, you can see an improvement in CPU usage of about 1.37%

@ElizabethOkerio ElizabethOkerio changed the title perf-improve create etags method Perf-improvement: CreateEtags method Nov 1, 2023
@ElizabethOkerio ElizabethOkerio changed the title Perf-improvement: CreateEtags method Perf-improvement: CreateEtag method Nov 1, 2023
@gathogojr
Copy link
Contributor

@ElizabethOkerio In your pull request description you state:

Having another cache in Microsoft.AspNetCore.OData to avoid calling this method: model.GetAnnotationValue(model); every time seems to have a slight improvement on CPU usage.

Where is the change for the other cache?

@ElizabethOkerio
Copy link
Contributor Author

@gathogojr I decided to leave it out since there is on-going work to improve the VersioningDictionary from the Edm lib.

@habbes
Copy link
Contributor

habbes commented Nov 9, 2023

@ElizabethOkerio could you share the CPU usage for the new changes.

@ElizabethOkerio ElizabethOkerio merged commit d94daad into OData:main Nov 9, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants