@@ -172,11 +172,11 @@ Cache size = *N* / 10 (so we can cache 10% of the total set). ConcurrentLru has
172
172
173
173
| Method | Mean | Error | StdDev | Ratio | RatioSD |
174
174
| ------------------- | ---------:| --------:| --------:| ------:| --------:|
175
- | ClassicLru | 157.3 ns | 1.67 ns | 1.48 ns | 1.00 | 0.00 |
176
- | FastConcurrentLru | 165.4 ns | 1.17 ns | 1.04 ns | 1.05 | 0.01 |
177
- | ConcurrentLru | 176 .1 ns | 1.22 ns | 1.08 ns | 1.12 | 0.01 |
178
- | FastConcurrentTLru | 247.9 ns | 3.58 ns | 2.80 ns | 1.58 | 0.02 |
179
- | ConcurrentTLru | 259.0 ns | 3.61 ns | 3.20 ns | 1.65 | 0.03 |
175
+ | ClassicLru | 175.7 ns | 2.75 ns | 2.43 ns | 1.00 | 0.00 |
176
+ | FastConcurrentLru | 180.2 ns | 2.55 ns | 2.26 ns | 1.03 | 0.02 |
177
+ | ConcurrentLru | 189 .1 ns | 3.14 ns | 2.94 ns | 1.08 | 0.03 |
178
+ | FastConcurrentTLru | 261.4 ns | 4.53 ns | 4.01 ns | 1.49 | 0.04 |
179
+ | ConcurrentTLru | 266.1 ns | 3.96 ns | 3.51 ns | 1.51 | 0.03 |
180
180
181
181
### Raw Lookup speed
182
182
@@ -188,16 +188,16 @@ In this test the same items are fetched repeatedly, no items are evicted. Repres
188
188
189
189
FastConcurrentLru does not allocate and is approximately 10x faster than System.Runtime.Caching.MemoryCache or the newer Microsoft.Extensions.Caching.Memory.MemoryCache.
190
190
191
- | Method | Mean | Error | StdDev | Ratio | Gen 0 | Allocated |
192
- | ---------------------- | ----------:| ---------:| ---------:| ------:| -------:| ----------:|
193
- | ConcurrentDictionary | 16.88 ns | 0.276 ns | 0.245 ns | 1.00 | - | - |
194
- | FastConcurrentLru | 23.27 ns | 0.491 ns | 0.565 ns | 1.38 | - | - |
195
- | ConcurrentLru | 26.77 ns | 0.512 ns | 0.666 ns | 1.60 | - | - |
196
- | FastConcurrentTLru | 54.35 ns | 0.650 ns | 0.576 ns | 3.22 | - | - |
197
- | ConcurrentTLru | 60.10 ns | 1.024 ns | 1.501 ns | 3.53 | - | - |
198
- | ClassicLru | 68.04 ns | 1.400 ns | 2.221 ns | 4.12 | - | - |
199
- | RuntimeMemoryCache | 280.16 ns | 5.607 ns | 7.486 ns | 16.59 | 0.0153 | 32 B |
200
- | ExtensionsMemoryCache | 342.72 ns | 3.729 ns | 3.114 ns | 20.29 | 0.0114 | 24 B |
191
+ | Method | Mean | Error | StdDev | Ratio | Gen 0 | Allocated |
192
+ | ------------------------- | ----------:| ---------:| ---------:| ------:| -------:| ----------:|
193
+ | ConcurrentDictionary | 16.76 ns | 0.322 ns | 0.285 ns | 1.00 | - | - |
194
+ | FastConcurrentLru | 18.94 ns | 0.249 ns | 0.220 ns | 1.13 | - | - |
195
+ | ConcurrentLru | 21.46 ns | 0.204 ns | 0.191 ns | 1.28 | - | - |
196
+ | FastConcurrentTLru | 41.57 ns | 0.450 ns | 0.376 ns | 2.48 | - | - |
197
+ | ConcurrentTLru | 43.95 ns | 0.588 ns | 0.521 ns | 2.62 | - | - |
198
+ | ClassicLru | 67.62 ns | 0.901 ns | 0.799 ns | 4.03 | - | - |
199
+ | RuntimeMemoryCacheGet | 279.70 ns | 3.825 ns | 3.578 ns | 16.70 | 0.0153 | 32 B |
200
+ | ExtensionsMemoryCacheGet | 341.67 ns | 6.617 ns | 6.499 ns | 20.35 | 0.0114 | 24 B |
201
201
202
202
203
203
## ConcurrentLru Throughput
@@ -222,23 +222,32 @@ public bool TryGet(K key, out V value)
222
222
I item ;
223
223
if (dictionary .TryGetValue (key , out item ))
224
224
{
225
- if (this .policy .ShouldDiscard (item )) // 1
226
- {
227
- this .Move (item , ItemDestination .Remove );
228
- value = default (V );
229
- return false ;
230
- }
231
-
232
- value = item .Value ;
233
- this .policy .Touch (item );
234
- this .hitCounter .IncrementHit (); // 2
235
- return true ;
225
+ return GetOrDiscard (item , out value );
236
226
}
237
227
238
228
value = default (V );
239
- this .hitCounter .IncrementMiss (); // 2
229
+ this .hitCounter .IncrementMiss ();
240
230
return false ;
241
231
}
232
+
233
+ // AggressiveInlining forces the JIT to inline policy.ShouldDiscard(). For LRU policy
234
+ // the first branch is completely eliminated due to JIT time constant propogation.
235
+ [MethodImpl (MethodImplOptions .AggressiveInlining )]
236
+ private bool GetOrDiscard (I item , out V value )
237
+ {
238
+ if (this .policy .ShouldDiscard (item )) // 1
239
+ {
240
+ this .Move (item , ItemDestination .Remove );
241
+ this .hitCounter .IncrementMiss (); // 2
242
+ value = default (V );
243
+ return false ;
244
+ }
245
+
246
+ value = item .Value ;
247
+ this .policy .Touch (item ); // 1
248
+ this .hitCounter .IncrementHit (); // 2
249
+ return true ;
250
+ }
242
251
```
243
252
244
253
### FastConcurrentLru (LruPolicy & NullHitCounter)
0 commit comments