586 Improve typeconverter creation by reusing cached instances
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)