Skip to content

Commit ccccab9

Browse files
authored
Use concurrent dictionary in NameMultiMap for CE yield cache (#17565)
1 parent 6b4d1e9 commit ccccab9

File tree

3 files changed

+38
-26
lines changed

3 files changed

+38
-26
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5564,7 +5564,7 @@ let emptyTcEnv g =
55645564
eCallerMemberName = None
55655565
eLambdaArgInfos = []
55665566
eIsControlFlow = false
5567-
eCachedImplicitYieldExpressions = HashMultiMap(HashIdentity.Structural) }
5567+
eCachedImplicitYieldExpressions = HashMultiMap(HashIdentity.Structural, useConcurrentDictionary = true) }
55685568

55695569
let CreateInitialTcEnv(g, amap, scopem, assemblyName, ccus) =
55705570
(emptyTcEnv g, ccus) ||> List.collectFold (fun env (ccu, autoOpens, internalsVisible) ->

src/Compiler/Utilities/HashMultiMap.fs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Internal.Utilities.Collections
44

55
open System.Collections.Generic
6+
open System.Collections.Concurrent
67

78
// Each entry in the HashMultiMap dictionary has at least one entry. Under normal usage each entry has _only_
89
// one entry. So use two hash tables: one for the main entries and one for the overflow.
@@ -11,40 +12,51 @@ type internal HashMultiMap<'Key, 'Value
1112
#if !NO_CHECKNULLS
1213
when 'Key:not null
1314
#endif
14-
>(size: int, comparer: IEqualityComparer<'Key>) =
15+
>(size: int, comparer: IEqualityComparer<'Key>, ?useConcurrentDictionary: bool) =
1516

16-
let firstEntries = Dictionary<_, _>(size, comparer)
17+
let comparer = comparer
1718

18-
let rest = Dictionary<_, _>(3, comparer)
19+
let firstEntries: IDictionary<_, _> =
20+
if defaultArg useConcurrentDictionary false then
21+
ConcurrentDictionary<_, _>(comparer)
22+
else
23+
Dictionary<_, _>(size, comparer)
1924

20-
new(comparer: IEqualityComparer<'Key>) = HashMultiMap<'Key, 'Value>(11, comparer)
25+
let rest: IDictionary<_, _> =
26+
if defaultArg useConcurrentDictionary false then
27+
ConcurrentDictionary<_, _>(comparer)
28+
else
29+
Dictionary<_, _>(3, comparer)
2130

22-
new(entries: seq<'Key * 'Value>, comparer: IEqualityComparer<'Key>) as x =
23-
new HashMultiMap<'Key, 'Value>(11, comparer)
24-
then entries |> Seq.iter (fun (k, v) -> x.Add(k, v))
31+
new(comparer: IEqualityComparer<'Key>, ?useConcurrentDictionary: bool) =
32+
HashMultiMap<'Key, 'Value>(11, comparer, defaultArg useConcurrentDictionary false)
2533

26-
member x.GetRest(k) =
34+
new(entries: seq<'Key * 'Value>, comparer: IEqualityComparer<'Key>, ?useConcurrentDictionary: bool) as this =
35+
HashMultiMap<'Key, 'Value>(11, comparer, defaultArg useConcurrentDictionary false)
36+
then entries |> Seq.iter (fun (k, v) -> this.Add(k, v))
37+
38+
member _.GetRest(k) =
2739
match rest.TryGetValue k with
2840
| true, res -> res
2941
| _ -> []
3042

31-
member x.Add(y, z) =
43+
member this.Add(y, z) =
3244
match firstEntries.TryGetValue y with
33-
| true, res -> rest[y] <- res :: x.GetRest(y)
45+
| true, res -> rest[y] <- res :: this.GetRest(y)
3446
| _ -> ()
3547

3648
firstEntries[y] <- z
3749

38-
member x.Clear() =
50+
member _.Clear() =
3951
firstEntries.Clear()
4052
rest.Clear()
4153

42-
member x.FirstEntries = firstEntries
54+
member _.FirstEntries = firstEntries
4355

44-
member x.Rest = rest
56+
member _.Rest = rest
4557

46-
member x.Copy() =
47-
let res = HashMultiMap<'Key, 'Value>(firstEntries.Count, firstEntries.Comparer)
58+
member _.Copy() =
59+
let res = HashMultiMap<'Key, 'Value>(firstEntries.Count, comparer)
4860

4961
for kvp in firstEntries do
5062
res.FirstEntries.Add(kvp.Key, kvp.Value)
@@ -90,11 +102,11 @@ type internal HashMultiMap<'Key, 'Value
90102
for z in rest do
91103
f kvp.Key z
92104

93-
member x.Contains(y) = firstEntries.ContainsKey(y)
105+
member _.Contains(y) = firstEntries.ContainsKey(y)
94106

95-
member x.ContainsKey(y) = firstEntries.ContainsKey(y)
107+
member _.ContainsKey(y) = firstEntries.ContainsKey(y)
96108

97-
member x.Remove(y) =
109+
member _.Remove(y) =
98110
match firstEntries.TryGetValue y with
99111
// NOTE: If not ok then nothing to remove - nop
100112
| true, _res ->
@@ -112,14 +124,14 @@ type internal HashMultiMap<'Key, 'Value
112124
| _ -> firstEntries.Remove(y) |> ignore
113125
| _ -> ()
114126

115-
member x.Replace(y, z) = firstEntries[y] <- z
127+
member _.Replace(y, z) = firstEntries[y] <- z
116128

117-
member x.TryFind(y) =
129+
member _.TryFind(y) =
118130
match firstEntries.TryGetValue y with
119131
| true, res -> Some res
120132
| _ -> None
121133

122-
member x.Count = firstEntries.Count
134+
member _.Count = firstEntries.Count
123135

124136
interface IEnumerable<KeyValuePair<'Key, 'Value>> with
125137

@@ -188,6 +200,6 @@ type internal HashMultiMap<'Key, 'Value
188200
member s.CopyTo(arr, arrIndex) =
189201
s |> Seq.iteri (fun j x -> arr[arrIndex + j] <- x)
190202

191-
member s.IsReadOnly = false
203+
member _.IsReadOnly = false
192204

193205
member s.Count = s.Count

src/Compiler/Utilities/HashMultiMap.fsi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ type internal HashMultiMap<'Key, 'Value
1313
#endif
1414
> =
1515
/// Create a new empty mutable HashMultiMap with the given key hash/equality functions.
16-
new: comparer: IEqualityComparer<'Key> -> HashMultiMap<'Key, 'Value>
16+
new: comparer: IEqualityComparer<'Key> * ?useConcurrentDictionary: bool -> HashMultiMap<'Key, 'Value>
1717

1818
/// Create a new empty mutable HashMultiMap with an internal bucket array of the given approximate size
1919
/// and with the given key hash/equality functions.
20-
new: size: int * comparer: IEqualityComparer<'Key> -> HashMultiMap<'Key, 'Value>
20+
new: size: int * comparer: IEqualityComparer<'Key> * ?useConcurrentDictionary: bool -> HashMultiMap<'Key, 'Value>
2121

2222
/// Build a map that contains the bindings of the given IEnumerable.
23-
new: entries: seq<'Key * 'Value> * comparer: IEqualityComparer<'Key> -> HashMultiMap<'Key, 'Value>
23+
new: entries: seq<'Key * 'Value> * comparer: IEqualityComparer<'Key> * ?useConcurrentDictionary: bool -> HashMultiMap<'Key, 'Value>
2424

2525
/// Make a shallow copy of the collection.
2626
member Copy: unit -> HashMultiMap<'Key, 'Value>

0 commit comments

Comments
 (0)