Unleash / unleash-client-dotnet

Unleash client SDK for .NET
Apache License 2.0
81 stars 39 forks source link

Reduce allocations when creating a new UnleashContext #178

Closed nathanmascitelli closed 10 months ago

nathanmascitelli commented 10 months ago

Description

In looking at our application which uses the dotnet Unleash client we found that a large amount of memory was being allocated by the client when checking if a flag was enabled: image image

Looking at the callstack it can be seen that these allocations come from creating dictionaries when cloning the provided UnleashContext.

There are three optimizations that can be made:

  1. Don't use Linq.ToDictionary. Under the hood this will create an empty dictionary and add items to it one by one, causing excess allocations as the dictionary internals grow. Instead create a new dictionary providing the old one as a source, this will create a fresh dictionary with the correct size right off the bat.
  2. Dont assign a dictionary to Properties in UnleashContext or Builder unless we need to. In all cases we override the empty dictionary anyway so there is no point.
  3. Don't use Builder in the hot code path. Its an unnessissary indrection and allocation.

My proposed changes address all three points.

Type of change

Please delete options that are not relevant.

How Has This Been Tested?

Using BenchmarkerDotnet I tested calling UnleashContext.ApplyStaticFields before and after my changes, the results: Method Mean Error StdDev Ratio Gen0 Allocated Alloc Ratio
Current 69.40 ns 0.312 ns 0.244 ns 1.00 0.0331 416 B 1.00
ProposedChanges 33.50 ns 0.512 ns 0.629 ns 0.49 0.0134 168 B 0.40
daveleek commented 10 months ago

Hello @nathanmascitelli, this is great! Thank you for this contribution, we'll take a look. You're reporting very intriguing numbers on memory usage, especially for 326 toggles. Would you be able to share a little more information about your feature flags usage/stats?

We'd love to hear more of what you think you can share about your constraints, parameters, and segments usage in your feature flags, average RPS numbers, feature toggle evaluations per request, and also, if you're able to; size of Unleash .NET backup file, maybe in an email?

nathanmascitelli commented 10 months ago

@daveleek sure, what email can I contact you at?

daveleek commented 10 months ago

Hi @nathanmascitelli it's david@getunleash.io

nathanmascitelli commented 10 months ago

Thanks @daveleek. I did send you an email with the details you asked for.