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

Improve the Decorate method performance for cases where we have a huge… #151

Merged
merged 1 commit into from
Jan 28, 2022

Conversation

Mariachi1231
Copy link

Improve the Decorate method performance for cases where we have a huge amount of services to decorate. In TryDecorateDescriptors, we have N collection travers, where N - is amount of descriptors found for serviceType. For a huge amount of descriptors and a huge amount of types to decorate, we can have performance degradation at the moment of container initialization. These changes are meant to avoid it by memorization of descriptor position.

@khellang
Copy link
Owner

khellang commented Sep 6, 2021

Thanks for this @Mariachi1231! 🙏🏻 Just curious, how huge are we talking? There's definitely more performance to be gained for decoration 😅

@Mariachi1231
Copy link
Author

Thanks for this @Mariachi1231! 🙏🏻 Just curious, how huge are we talking? There's definitely more performance to be gained for decoration 😅

Hi, that's thanks to your convenient set of extensions of IServiceCollection. Regarding performance, I added an optimistic benchmark, you can find it in my fork. Results on my workstation are next:

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19042.1165 (20H2/October2020Update)
Intel Core i7-7700 CPU 3.60GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET SDK=6.0.100-preview.7.21379.14
  [Host]     : .NET Core 3.1.18 (CoreCLR 4.700.21.35901, CoreFX 4.700.21.36305), X64 RyuJIT
  Job-UFPBGU : .NET Core 3.1.18 (CoreCLR 4.700.21.35901, CoreFX 4.700.21.36305), X64 RyuJIT

InvocationCount=10  LaunchCount=1  UnrollFactor=1  
Method TotalDescriptors TotalDecorable Mean Error StdDev Median Min Max Ratio RatioSD Allocated
TryDecorate_worst_case 1000 3 52.79 μs 3.912 μs 11.350 μs 49.26 μs 40.15 μs 85.38 μs 1.00 0.00 2 KB
TryDecorateOld_worst_case 1000 3 66.63 μs 2.215 μs 6.101 μs 67.17 μs 56.90 μs 84.36 μs 1.29 0.22 2 KB
TryDecorate_worst_case 1000 30 52.89 μs 0.816 μs 0.940 μs 52.77 μs 51.36 μs 55.24 μs 1.00 0.00 7 KB
TryDecorateOld_worst_case 1000 30 163.36 μs 7.059 μs 19.324 μs 159.19 μs 122.00 μs 219.89 μs 3.29 0.30 7 KB
TryDecorate_worst_case 1000 300 93.65 μs 4.974 μs 14.271 μs 95.18 μs 63.31 μs 133.24 μs 1.00 0.00 59 KB
TryDecorateOld_worst_case 1000 300 971.55 μs 28.577 μs 83.811 μs 971.50 μs 756.50 μs 1,180.46 μs 10.65 1.99 53 KB
TryDecorate_worst_case 1000 800 156.42 μs 12.315 μs 35.924 μs 166.26 μs 111.67 μs 259.39 μs 1.00 0.00 149 KB
TryDecorateOld_worst_case 1000 800 1,696.13 μs 33.876 μs 82.460 μs 1,706.78 μs 1,467.23 μs 1,860.15 μs 10.58 2.36 135 KB
TryDecorate_worst_case 10000 3 321.00 μs 32.240 μs 95.060 μs 269.83 μs 235.15 μs 593.21 μs 1.00 0.00 2 KB
TryDecorateOld_worst_case 10000 3 506.09 μs 29.729 μs 85.775 μs 518.54 μs 388.89 μs 724.00 μs 1.64 0.36 2 KB
TryDecorate_worst_case 10000 30 349.41 μs 31.908 μs 94.082 μs 343.81 μs 241.42 μs 606.89 μs 1.00 0.00 7 KB
TryDecorateOld_worst_case 10000 30 1,458.38 μs 44.367 μs 130.816 μs 1,412.01 μs 1,269.57 μs 1,793.13 μs 4.41 0.98 7 KB
TryDecorate_worst_case 10000 300 361.36 μs 35.543 μs 104.242 μs 296.89 μs 262.54 μs 623.25 μs 1.00 0.00 59 KB
TryDecorateOld_worst_case 10000 300 10,949.34 μs 214.899 μs 201.016 μs 11,012.30 μs 10,642.51 μs 11,400.92 μs 21.28 2.24 53 KB
TryDecorate_worst_case 10000 800 438.69 μs 40.516 μs 119.461 μs 400.35 μs 312.90 μs 749.00 μs 1.00 0.00 149 KB
TryDecorateOld_worst_case 10000 800 27,022.49 μs 448.536 μs 397.615 μs 26,946.15 μs 26,535.08 μs 28,029.69 μs 44.42 3.26 135 KB

In general, with such changes, performance will be better with more decorating services. Let's consider regular CQRS based applications with usages of wrappers, for an application with, for instance, 100 queries. Usually, queries are wrapped in a couple of decorators. For example, we can have a logger decorator, params validation decorator, metrics decorator and this means that we already have 300 executions of IndexOf through the total amount of descriptors in the IServiceCollection. With changes, instead, we will have just a single iteration instead of 300 executions of IndexOf through all descriptors for a single wrapped type.

@khellang khellang merged commit 1a549b6 into khellang:master Jan 28, 2022
@khellang khellang added this to the v4.0.0 milestone Jan 28, 2022
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.

None yet

2 participants