@@ -5,12 +5,9 @@ open System
5
5
open System.Collections .Generic
6
6
open System.Collections .Concurrent
7
7
open System.Threading
8
- open System.Threading .Tasks
9
8
open System.Diagnostics
10
9
open System.Diagnostics .Metrics
11
10
12
- open FSharp.Compiler .Diagnostics
13
-
14
11
[<Struct; RequireQualifiedAccess; NoComparison; NoEquality>]
15
12
type CacheOptions =
16
13
{
@@ -54,25 +51,25 @@ type CachedEntity<'Key, 'Value> =
54
51
55
52
override this.ToString () = $" {this.Key}"
56
53
57
- module CacheMetrics =
58
- let meter = new Meter ( " FSharp.Compiler.Cache " )
59
-
54
+ // Currently the Cache itself exposes Metrics.Counters that count raw cache events: hits, misses, evictions etc.
55
+ // This class observes those counters and keeps a snapshot of readings. For now this is used only to print cache stats in debug mode.
56
+ // TODO: We could add some System.Diagnostics.Metrics.Gauge instruments to this class, to get computed stats also exposed as metrics.
60
57
type CacheMetrics ( cacheId ) =
58
+ static let meter = new Meter( " FSharp.Compiler.Cache" )
61
59
62
60
static let instrumentedCaches = ConcurrentDictionary< string, CacheMetrics>()
63
61
64
62
let readings = ConcurrentDictionary< string, int64 ref>()
65
63
66
64
#if DEBUG
67
- let listener =
68
- new MeterListener(
69
- InstrumentPublished =
70
- fun i l ->
71
- if i.Meter = CacheMetrics.meter && i.Description = cacheId then
72
- l.EnableMeasurementEvents( i)
73
- )
65
+ let listener = new MeterListener()
74
66
75
67
do
68
+ listener.InstrumentPublished <-
69
+ fun i l ->
70
+ if i.Meter = meter && i.Description = cacheId then
71
+ l.EnableMeasurementEvents( i)
72
+
76
73
listener.SetMeasurementEventCallback< int64>( fun k v _ _ -> Interlocked.Add( readings.GetOrAdd( k.Name, ref 0 L), v) |> ignore)
77
74
listener.Start()
78
75
@@ -83,6 +80,8 @@ type CacheMetrics(cacheId) =
83
80
84
81
member val CacheId = cacheId
85
82
83
+ static member val Meter = meter
84
+
86
85
member val RecentStats = " -" with get, set
87
86
88
87
member this.TryUpdateStats ( clearCounts ) =
@@ -139,7 +138,7 @@ type EntityPool<'Key, 'Value>(maximumCapacity, cacheId) =
139
138
let mutable created = 0
140
139
141
140
let overCapacity =
142
- CacheMetrics.meter .CreateCounter< int64>( " over-capacity" , " count" , cacheId)
141
+ CacheMetrics.Meter .CreateCounter< int64>( " over-capacity" , " count" , cacheId)
143
142
144
143
member _.Acquire ( key , value ) =
145
144
match pool.TryTake() with
@@ -163,14 +162,14 @@ type Cache<'Key, 'Value when 'Key: not null and 'Key: equality>
163
162
164
163
let instanceId = defaultArg name $" cache-{Interlocked.Increment(&cacheId)}"
165
164
166
- let hits = CacheMetrics.meter .CreateCounter< int64>( " hits" , " count" , instanceId)
167
- let misses = CacheMetrics.meter .CreateCounter< int64>( " misses" , " count" , instanceId)
165
+ let hits = CacheMetrics.Meter .CreateCounter< int64>( " hits" , " count" , instanceId)
166
+ let misses = CacheMetrics.Meter .CreateCounter< int64>( " misses" , " count" , instanceId)
168
167
169
168
let evictions =
170
- CacheMetrics.meter .CreateCounter< int64>( " evictions" , " count" , instanceId)
169
+ CacheMetrics.Meter .CreateCounter< int64>( " evictions" , " count" , instanceId)
171
170
172
171
let evictionFails =
173
- CacheMetrics.meter .CreateCounter< int64>( " eviction-fails" , " count" , instanceId)
172
+ CacheMetrics.Meter .CreateCounter< int64>( " eviction-fails" , " count" , instanceId)
174
173
175
174
let pool = EntityPool< 'Key, 'Value>( capacity, instanceId)
176
175
@@ -199,6 +198,7 @@ type Cache<'Key, 'Value when 'Key: not null and 'Key: equality>
199
198
evictionQueue.Remove( node)
200
199
evictionQueue.AddLast( node)
201
200
201
+ // If items count exceeds this, evictions ensue.
202
202
let targetCount =
203
203
options.MaximumCapacity
204
204
- int ( float options.MaximumCapacity * float options.PercentageToEvict / 100.0 )
@@ -264,14 +264,6 @@ type Cache<'Key, 'Value when 'Key: not null and 'Key: equality>
264
264
pool.Reclaim( cachedEntity)
265
265
false
266
266
267
- member this.GetOrCreate ( key : 'Key , valueFactory : 'Key -> 'Value ) =
268
- match this.TryGetValue( key) with
269
- | true , value -> value
270
- | _ ->
271
- let value = valueFactory key
272
- this.TryAdd( key, value) |> ignore
273
- value
274
-
275
267
interface IDisposable with
276
268
member this.Dispose () =
277
269
store.Clear()
0 commit comments