-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Improve IncludeXmlComments performance (2) #3044
Improve IncludeXmlComments performance (2) #3044
Conversation
Co-authored-by: steven.darby <steven.darby@tribalgroup.com>
21d0a75
to
37bdd9d
Compare
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XPathNavigatorExtensions.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XPathNavigatorExtensions.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XPathNavigatorExtensions.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsDocumentFilter.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsDocumentFilter.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsDocumentHelper.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsDocumentHelper.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsDocumentHelper.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsOperationFilter.cs
Outdated
Show resolved
Hide resolved
src/Swashbuckle.AspNetCore.SwaggerGen/XmlComments/XmlCommentsDocumentHelper.cs
Outdated
Show resolved
Hide resolved
Could you create a BenchmarkDotNet benchmark that replicates what you did and share it as a comment so we can re-run it ourselves? |
Co-authored-by: Martin Costello <martin@martincostello.com>
Co-authored-by: Martin Costello <martin@martincostello.com>
and add SelectChild/GetAttribute extensions for consistency.
I'll look into it. Could take some time though. I'm not really familiar with BenchmarkDotNet yet and I can't share my local test case. |
didn't mean to touch this file.
I created a benchmark in a separate branch here. As expected, the new implementation is a lot Old implementation with small member count (n = 79):
Old implementation with big member count (n = 10.000):
New implementation with any member count:
|
@mus65 thank you for picking this up and improving it, great stuff seeing the benchmarks too |
Thanks @mus65 for doing those benchmarks - I'll take a closer look at them tomorrow 👍 |
Add project for running benchmarks. Adapted from mus65@65bfd97. See domaindrivendev#3044. Co-Authored-By: mus65 <1933789+mus65@users.noreply.github.com>
Thanks again for adding these benchmarks. I've pushed up a version of them in #3050 for us to use going forwards. These are the results I get on my laptop - TL;DR - better by every measure 🥳 N=79Base
This PR
N=10,000Base
This PR
|
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #3044 +/- ##
==========================================
+ Coverage 90.46% 90.53% +0.06%
==========================================
Files 74 76 +2
Lines 2980 3002 +22
Branches 470 479 +9
==========================================
+ Hits 2696 2718 +22
Misses 284 284
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Add project for running benchmarks. Adapted from mus65@65bfd97. See #3044. Co-Authored-By: mus65 <1933789+mus65@users.noreply.github.com>
This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [Swashbuckle.AspNetCore](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore) | `6.7.3` -> `6.8.0` | [![age](https://developer.mend.io/api/mc/badges/age/nuget/Swashbuckle.AspNetCore/6.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/nuget/Swashbuckle.AspNetCore/6.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/nuget/Swashbuckle.AspNetCore/6.7.3/6.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/Swashbuckle.AspNetCore/6.7.3/6.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>domaindrivendev/Swashbuckle.AspNetCore (Swashbuckle.AspNetCore)</summary> ### [`v6.8.0`](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/releases/tag/v6.8.0) ##### What's Changed - Added dependency injection/easy registration for async filters by [@​tofi92](https://redirect.github.com/tofi92) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3030](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3030) - Improve IncludeXmlComments performance (2) by [@​mus65](https://redirect.github.com/mus65) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3044](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3044) - Apply ParameterFilters and RequestBodyFilters for WithOpenApi endpoints by [@​jgarciadelanoceda](https://redirect.github.com/jgarciadelanoceda) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3059](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3059) - Swagger plugins support by [@​jvmlet](https://redirect.github.com/jvmlet) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3056](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3056) - Add benchmarks project by [@​martincostello](https://redirect.github.com/martincostello) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3050](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3050) - Fix NuGet badge by [@​martincostello](https://redirect.github.com/martincostello) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3064](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3064) - SwaggerGen - Improved handling of dictionaries with enum key by [@​flarestudiopl](https://redirect.github.com/flarestudiopl) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3068](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3068) - Fix typo by [@​tom-star119](https://redirect.github.com/tom-star119) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3073](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3073) - Do not fill the RequestBody description with the first parameter of a… by [@​jgarciadelanoceda](https://redirect.github.com/jgarciadelanoceda) in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3076](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3076) ##### New Contributors - [@​tofi92](https://redirect.github.com/tofi92) made their first contribution in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3030](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3030) - [@​mus65](https://redirect.github.com/mus65) made their first contribution in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3044](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3044) - [@​jvmlet](https://redirect.github.com/jvmlet) made their first contribution in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3056](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3056) - [@​flarestudiopl](https://redirect.github.com/flarestudiopl) made their first contribution in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3068](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3068) - [@​tom-star119](https://redirect.github.com/tom-star119) made their first contribution in [https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3073](https://redirect.github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/3073) **Full Changelog**: domaindrivendev/Swashbuckle.AspNetCore@v6.7.3...v6.8.0 </details> --- ### Configuration 📅 **Schedule**: Branch creation - "after 10pm every weekday,every weekend,before 5am every weekday" in timezone Europe/Berlin, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/orso-co/Orso.Arpa.Api). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6ImRldmVsb3AiLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
I have some benchmarks I've been using to compare the benchmarks of Swashbuckle, NSwag and the new .NET 9 ASP.NET Core OpenAPI library, and there's a noticeable really improvement from the ingesting changes from this PR. The first major improvement is from updating to .NET 9 RC1 (martincostello/aspnetcore-openapi@7e5e365), then the second improvement with the big reduction in memory usage is from updating to 6.8.0 (martincostello/aspnetcore-openapi@b4aba65) Thanks again! |
Pull Request
The issue or feature being addressed
Fixes #2164
Details on the issue fix or feature implementation
This is a rebase and enhancement of #2443 (thanks to @stevendarby, added you as co-author).
This significantly improves the performance of the XML comment filters. The original fix #2443 created a dictionary of the members to avoid iterating the whole XPath for every single item.
I made some further improvements by replacing all usages of
Select
andSelectSingleNode
withSelectChildren
(added some helper extensions for this). This completely avoids XPath expressions and the documentation even mentionsSelectChildren
being faster.I made the new constructors internal for now (which is also why I changed
ParameterFilter
toAddParameterFilterInstance
etc.. DI fails otherwise). It felt wrong to me to make these public, but I can make these public if you want.Tests
The existing tests imho already cover this code pretty well. I only added a test case for a bug I noticed in #2443 (there was a
return
instead of acontinue
inXmlCommentsDocumentFilter
).Performance
#2443 already mentions significant improvements (25s -> 4s). With another local test case I have with a 1.5MB XML file, generation time decreases from ~1900ms to ~200ms.
#2443 also mentions some concern about memory consumption, so I made some manual tests with a very big (30MB) XML document file: the XPathDocument itself already loads the document completely into memory which uses about 60 MB. Creating the dictionary creates an additional 40MB. So there is some additional memory consumption, but considering that 30MB is pretty extreme and most files should be < 1MB, the memory increase should be negligible for most applications. In my local test case with a 1.5 MB File, memory consumption after GC.Collect increased by about 1MB.