firely-cql-sdk icon indicating copy to clipboard operation
firely-cql-sdk copied to clipboard

586 Improve typeconverter creation by reusing cached instances

Open baseTwo opened this issue 1 year ago • 0 comments

Fix for

  • #586

Better reuse of TypeConverter when calling FhirTypeConverter.Create(..). Also, if different LRU cache sizes are specified, they are cached per sized too. The caching for the LRU cache and the Fhir TypeConverter will be referenced via a weak reference, so that if they go out of memory scope, they will be freed.

Renamed FhirModelBindingSetup to FhirCqlContextOptions, since it is only used when creating a FhirCqlContext.

There were no usages for ModelBindingSetup, so that was removed.

Unit test FhirCqlContextCreateTests added to test the reuse of type converters and the LRU caches when creating a new FhirCqlContext

Note: For the future it would be better to consider creating types inside a ServiceProvider that can better manage lifetime of instances

Benchmarks

New Benchmarks project added to solution. It is evident that adding reuse caching to TypeConverters lowers memory usage and increases performance

// * Summary *

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.2152)
13th Gen Intel Core i9-13980HX, 1 CPU, 32 logical and 24 physical cores
.NET SDK 9.0.100-preview.7.24407.12
  [Host]            : .NET 8.0.10 (8.0.1024.46610), X64 RyuJIT AVX2 [AttachedDebugger]
  ShortRun-.NET 8.0 : .NET 8.0.10 (8.0.1024.46610), X64 RyuJIT AVX2
  ShortRun-.NET 9.0 : .NET 9.0.0 (9.0.24.40507), X64 RyuJIT AVX2

IterationCount=3  LaunchCount=1  WarmupCount=3

| Method                                                                               | Job               | Runtime  | EnableTypeConverterReuse | Mean     | Error     | StdDev   | Ratio | RatioSD | Gen0    | Gen1    | Allocated | Alloc Ratio |
|------------------------------------------------------------------------------------- |------------------ |--------- |------------------------- |---------:|----------:|---------:|------:|--------:|--------:|--------:|----------:|------------:|
| 'Creating CqlContext with no cache for FhirTypeConverter'                            | ShortRun-.NET 8.0 | .NET 8.0 | False                    | 815.5 us |  87.64 us |  4.80 us |  1.00 |    0.01 | 35.1563 | 11.7188 | 633.36 KB |        1.00 |
| 'Creating CqlContext with default cache size 10000 for FhirTypeConverter'            | ShortRun-.NET 8.0 | .NET 8.0 | False                    | 807.7 us | 153.25 us |  8.40 us |  0.99 |    0.01 | 35.1563 | 11.7188 | 633.36 KB |        1.00 |
| 'Creating CqlContext with random cache size for FhirTypeConverter between 10 and 50' | ShortRun-.NET 8.0 | .NET 8.0 | False                    | 807.4 us | 129.60 us |  7.10 us |  0.99 |    0.01 | 35.1563 | 11.7188 | 633.46 KB |        1.00 |
|                                                                                      |                   |          |                          |          |           |          |       |         |         |         |           |             |
| 'Creating CqlContext with no cache for FhirTypeConverter'                            | ShortRun-.NET 9.0 | .NET 9.0 | False                    | 803.8 us |  68.16 us |  3.74 us |  1.00 |    0.01 | 37.1094 | 11.7188 | 662.74 KB |        1.00 |
| 'Creating CqlContext with default cache size 10000 for FhirTypeConverter'            | ShortRun-.NET 9.0 | .NET 9.0 | False                    | 806.9 us | 351.86 us | 19.29 us |  1.00 |    0.02 | 37.1094 | 11.7188 | 662.74 KB |        1.00 |
| 'Creating CqlContext with random cache size for FhirTypeConverter between 10 and 50' | ShortRun-.NET 9.0 | .NET 9.0 | False                    | 801.3 us | 118.74 us |  6.51 us |  1.00 |    0.01 | 37.1094 | 11.7188 | 662.84 KB |        1.00 |
|                                                                                      |                   |          |                          |          |           |          |       |         |         |         |           |             |
| 'Creating CqlContext with no cache for FhirTypeConverter'                            | ShortRun-.NET 8.0 | .NET 8.0 | True                     | 149.9 us |  12.26 us |  0.67 us |  1.00 |    0.01 |  4.6387 |  0.4883 |  85.61 KB |        1.00 |
| 'Creating CqlContext with default cache size 10000 for FhirTypeConverter'            | ShortRun-.NET 8.0 | .NET 8.0 | True                     | 147.7 us |  20.34 us |  1.12 us |  0.99 |    0.01 |  4.6387 |  0.4883 |  85.61 KB |        1.00 |
| 'Creating CqlContext with random cache size for FhirTypeConverter between 10 and 50' | ShortRun-.NET 8.0 | .NET 8.0 | True                     | 536.8 us | 211.15 us | 11.57 us |  3.58 |    0.07 | 23.4375 |  7.8125 | 418.62 KB |        4.89 |
|                                                                                      |                   |          |                          |          |           |          |       |         |         |         |           |             |
| 'Creating CqlContext with no cache for FhirTypeConverter'                            | ShortRun-.NET 9.0 | .NET 9.0 | True                     | 163.6 us |  51.67 us |  2.83 us |  1.00 |    0.02 |  6.3477 |  1.2207 | 114.22 KB |        1.00 |
| 'Creating CqlContext with default cache size 10000 for FhirTypeConverter'            | ShortRun-.NET 9.0 | .NET 9.0 | True                     | 166.1 us |  46.00 us |  2.52 us |  1.01 |    0.02 |  6.3477 |  1.2207 | 114.22 KB |        1.00 |
| 'Creating CqlContext with random cache size for FhirTypeConverter between 10 and 50' | ShortRun-.NET 9.0 | .NET 9.0 | True                     | 550.9 us | 175.49 us |  9.62 us |  3.37 |    0.07 | 25.3906 |  9.7656 | 457.92 KB |        4.01 |

// * Warnings *
Environment
  Summary -> Benchmark was executed with attached debugger

// * Legends *
  EnableTypeConverterReuse : Value of the 'EnableTypeConverterReuse' parameter
  Mean                     : Arithmetic mean of all measurements
  Error                    : Half of 99.9% confidence interval
  StdDev                   : Standard deviation of all measurements
  Ratio                    : Mean of the ratio distribution ([Current]/[Baseline])
  RatioSD                  : Standard deviation of the ratio distribution ([Current]/[Baseline])
  Gen0                     : GC Generation 0 collects per 1000 operations
  Gen1                     : GC Generation 1 collects per 1000 operations
  Allocated                : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
  Alloc Ratio              : Allocated memory ratio distribution ([Current]/[Baseline])
  1 us                     : 1 Microsecond (0.000001 sec)

baseTwo avatar Oct 11 '24 09:10 baseTwo