Skip to content

Commit

Permalink
Use concurrent dictionary in NameMultiMap for CE yield cache (dotnet#…
Browse files Browse the repository at this point in the history
  • Loading branch information
vzarytovskii committed Aug 20, 2024
1 parent b1b810f commit 84c5478
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5540,7 +5540,7 @@ let emptyTcEnv g =
eCallerMemberName = None
eLambdaArgInfos = []
eIsControlFlow = false
eCachedImplicitYieldExpressions = HashMultiMap(HashIdentity.Structural) }
eCachedImplicitYieldExpressions = HashMultiMap(HashIdentity.Structural, useConcurrentDictionary = true) }

let CreateInitialTcEnv(g, amap, scopem, assemblyName, ccus) =
(emptyTcEnv g, ccus) ||> List.collectFold (fun env (ccu, autoOpens, internalsVisible) ->
Expand Down
70 changes: 43 additions & 27 deletions src/Compiler/Utilities/HashMultiMap.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,60 @@
namespace Internal.Utilities.Collections

open System.Collections.Generic
open System.Collections.Concurrent

// Each entry in the HashMultiMap dictionary has at least one entry. Under normal usage each entry has _only_
// one entry. So use two hash tables: one for the main entries and one for the overflow.
[<Sealed>]
type internal HashMultiMap<'Key, 'Value>(size: int, comparer: IEqualityComparer<'Key>) =

let firstEntries = Dictionary<_, _>(size, comparer)

let rest = Dictionary<_, _>(3, comparer)

new(comparer: IEqualityComparer<'Key>) = HashMultiMap<'Key, 'Value>(11, comparer)

new(entries: seq<'Key * 'Value>, comparer: IEqualityComparer<'Key>) as x =
new HashMultiMap<'Key, 'Value>(11, comparer)
then entries |> Seq.iter (fun (k, v) -> x.Add(k, v))

member x.GetRest(k) =
type internal HashMultiMap<'Key, 'Value
#if !NO_CHECKNULLS
when 'Key:not null
#endif
>(size: int, comparer: IEqualityComparer<'Key>, ?useConcurrentDictionary: bool) =

let comparer = comparer

let firstEntries: IDictionary<_, _> =
if defaultArg useConcurrentDictionary false then
ConcurrentDictionary<_, _>(comparer)
else
Dictionary<_, _>(size, comparer)

let rest: IDictionary<_, _> =
if defaultArg useConcurrentDictionary false then
ConcurrentDictionary<_, _>(comparer)
else
Dictionary<_, _>(3, comparer)

new(comparer: IEqualityComparer<'Key>, ?useConcurrentDictionary: bool) =
HashMultiMap<'Key, 'Value>(11, comparer, defaultArg useConcurrentDictionary false)

new(entries: seq<'Key * 'Value>, comparer: IEqualityComparer<'Key>, ?useConcurrentDictionary: bool) as this =
HashMultiMap<'Key, 'Value>(11, comparer, defaultArg useConcurrentDictionary false)
then entries |> Seq.iter (fun (k, v) -> this.Add(k, v))

member _.GetRest(k) =
match rest.TryGetValue k with
| true, res -> res
| _ -> []

member x.Add(y, z) =
member this.Add(y, z) =
match firstEntries.TryGetValue y with
| true, res -> rest[y] <- res :: x.GetRest(y)
| true, res -> rest[y] <- res :: this.GetRest(y)
| _ -> ()

firstEntries[y] <- z

member x.Clear() =
member _.Clear() =
firstEntries.Clear()
rest.Clear()

member x.FirstEntries = firstEntries
member _.FirstEntries = firstEntries

member x.Rest = rest
member _.Rest = rest

member x.Copy() =
let res = HashMultiMap<'Key, 'Value>(firstEntries.Count, firstEntries.Comparer)
member _.Copy() =
let res = HashMultiMap<'Key, 'Value>(firstEntries.Count, comparer)

for kvp in firstEntries do
res.FirstEntries.Add(kvp.Key, kvp.Value)
Expand Down Expand Up @@ -86,11 +102,11 @@ type internal HashMultiMap<'Key, 'Value>(size: int, comparer: IEqualityComparer<
for z in rest do
f kvp.Key z

member x.Contains(y) = firstEntries.ContainsKey(y)
member _.Contains(y) = firstEntries.ContainsKey(y)

member x.ContainsKey(y) = firstEntries.ContainsKey(y)
member _.ContainsKey(y) = firstEntries.ContainsKey(y)

member x.Remove(y) =
member _.Remove(y) =
match firstEntries.TryGetValue y with
// NOTE: If not ok then nothing to remove - nop
| true, _res ->
Expand All @@ -108,14 +124,14 @@ type internal HashMultiMap<'Key, 'Value>(size: int, comparer: IEqualityComparer<
| _ -> firstEntries.Remove(y) |> ignore
| _ -> ()

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

member x.TryFind(y) =
member _.TryFind(y) =
match firstEntries.TryGetValue y with
| true, res -> Some res
| _ -> None

member x.Count = firstEntries.Count
member _.Count = firstEntries.Count

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

Expand Down Expand Up @@ -184,6 +200,6 @@ type internal HashMultiMap<'Key, 'Value>(size: int, comparer: IEqualityComparer<
member s.CopyTo(arr, arrIndex) =
s |> Seq.iteri (fun j x -> arr[arrIndex + j] <- x)

member s.IsReadOnly = false
member _.IsReadOnly = false

member s.Count = s.Count
6 changes: 3 additions & 3 deletions src/Compiler/Utilities/HashMultiMap.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ open System.Collections.Generic
[<Sealed>]
type internal HashMultiMap<'Key, 'Value> =
/// Create a new empty mutable HashMultiMap with the given key hash/equality functions.
new: comparer: IEqualityComparer<'Key> -> HashMultiMap<'Key, 'Value>
new: comparer: IEqualityComparer<'Key> * ?useConcurrentDictionary: bool -> HashMultiMap<'Key, 'Value>

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

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

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

0 comments on commit 84c5478

Please sign in to comment.