Skip to content

Commit 18657b1

Browse files
committed
Replace some Seq calls to increase performance.
1 parent 88d5f18 commit 18657b1

File tree

2 files changed

+24
-34
lines changed

2 files changed

+24
-34
lines changed

tests/ParallelTypeCheckingTests/Code/TrieApproach/DependencyResolution.fs

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,17 @@ let queryTrie (trie: TrieNode) (path: ModuleSegment list) : QueryTrieNodeResult
1313
match path with
1414
| [] -> failwith "path should not be empty"
1515
| [ lastNodeFromPath ] ->
16-
let childResults =
17-
currentNode.Children
18-
|> Seq.tryFind (fun (KeyValue (segment, _childNode)) -> segment = lastNodeFromPath)
19-
20-
match childResults with
21-
| None -> QueryTrieNodeResult.NodeDoesNotExist
22-
| Some (KeyValue (_, childNode)) ->
16+
match currentNode.Children.TryGetValue(lastNodeFromPath) with
17+
| false, _ -> QueryTrieNodeResult.NodeDoesNotExist
18+
| true, childNode ->
2319
if Set.isEmpty childNode.Files then
2420
QueryTrieNodeResult.NodeDoesNotExposeData
2521
else
2622
QueryTrieNodeResult.NodeExposesData(childNode.Files)
2723
| currentPath :: restPath ->
28-
let childResults =
29-
currentNode.Children
30-
|> Seq.tryFind (fun (KeyValue (segment, _childNode)) -> segment = currentPath)
31-
32-
match childResults with
33-
| None -> QueryTrieNodeResult.NodeDoesNotExist
34-
| Some (KeyValue (_, childNode)) -> visit childNode restPath
24+
match currentNode.Children.TryGetValue(currentPath) with
25+
| false, _ -> QueryTrieNodeResult.NodeDoesNotExist
26+
| true, childNode -> visit childNode restPath
3527

3628
visit trie path
3729

@@ -91,7 +83,7 @@ let rec processStateEntry (queryTrie: QueryTrie) (state: FileContentQueryState)
9183
// The extended path could add a new link (in case of a module or namespace with types)
9284
// It might also not add anything at all (in case it the extended path is still a partial one)
9385
(stateAfterFullOpenPath, state.OpenNamespaces)
94-
||> Seq.fold (fun acc openNS -> processOpenPath queryTrie [ yield! openNS; yield! path ] acc)
86+
||> Set.fold (fun acc openNS -> processOpenPath queryTrie [ yield! openNS; yield! path ] acc)
9587

9688
| FileContentEntry.PrefixedIdentifier path ->
9789
match path with
@@ -101,14 +93,14 @@ let rec processStateEntry (queryTrie: QueryTrie) (state: FileContentQueryState)
10193
| _ ->
10294
// path could consist out of multiple segments
10395
(state, [| 1 .. path.Length |])
104-
||> Seq.fold (fun state takeParts ->
96+
||> Array.fold (fun state takeParts ->
10597
let path = List.take takeParts path
10698
// process the name was if it were a FQN
10799
let stateAfterFullIdentifier = processIdentifier queryTrie path state
108100

109101
// Process the name in combination with the existing open namespaces
110102
(stateAfterFullIdentifier, state.OpenNamespaces)
111-
||> Seq.fold (fun acc openNS -> processIdentifier queryTrie [ yield! openNS; yield! path ] acc))
103+
||> Set.fold (fun acc openNS -> processIdentifier queryTrie [ yield! openNS; yield! path ] acc))
112104

113105
| FileContentEntry.NestedModule (nestedContent = nestedContent) ->
114106
// We don't want our current state to be affect by any open statements in the nested module
@@ -133,32 +125,28 @@ let time msg f a =
133125

134126
/// Returns a list of all the files that child nodes contain
135127
let indexesUnderNode (node: TrieNode) : Set<int> =
136-
let rec collect (node: TrieNode) (continuation: int seq -> int seq) : int seq =
137-
let continuations: ((int seq -> int seq) -> int seq) list =
138-
node.Children
139-
|> Seq.map (fun (KeyValue (_, node)) -> collect node)
140-
|> Seq.toList
128+
let rec collect (node: TrieNode) (continuation: int list -> int list) : int list =
129+
let continuations: ((int list -> int list) -> int list) list =
130+
[
131+
for node in node.Children.Values do
132+
yield collect node
133+
]
141134

142135
let finalContinuation indexes =
143-
continuation (
144-
seq {
145-
yield! node.Files
146-
yield! Seq.collect id indexes
147-
}
148-
)
136+
continuation [ yield! node.Files; yield! List.collect id indexes ]
149137

150138
Continuation.sequence continuations finalContinuation
151139

152-
Set.ofSeq (collect node id)
140+
Set.ofList (collect node id)
153141

154142
/// A "ghost" dependency is a link between files that actually should be avoided.
155143
/// The user has a partial namespace or opens a namespace that does not produce anything.
156144
/// In order to still be able to compile the current file, the given namespace should be known to the file.
157145
/// We did not find it via the trie, because there are no files that contribute to this namespace.
158146
let collectGhostDependencies (fileIndex: int) (trie: TrieNode) (queryTrie: QueryTrie) (result: FileContentQueryState) =
159147
// Go over all open namespaces, and assert all those links eventually went anywhere
160-
result.OpenedNamespaces
161-
|> Seq.collect (fun path ->
148+
Set.toArray result.OpenedNamespaces
149+
|> Array.collect (fun path ->
162150
match queryTrie path with
163151
| QueryTrieNodeResult.NodeExposesData _
164152
| QueryTrieNodeResult.NodeDoesNotExist -> Array.empty
@@ -188,7 +176,6 @@ let collectGhostDependencies (fileIndex: int) (trie: TrieNode) (queryTrie: Query
188176
else
189177
// The partial open did eventually lead to a link in a file
190178
Array.empty)
191-
|> Seq.toArray
192179

193180
let mkGraph (files: FileWithAST array) =
194181
// Implementation files backed by signatures should be excluded to construct the trie.
@@ -229,6 +216,7 @@ let mkGraph (files: FileWithAST array) =
229216

230217
// Process all entries of a file and query the trie when required to find the dependent files.
231218
let result =
219+
// Seq is faster than List in this case.
232220
Seq.fold (processStateEntry queryTrie) (FileContentQueryState.Create file.Idx knownFiles) fileContent
233221

234222
// after processing the file we should verify if any of the open statements are found in the trie but do not yield any file link.

tests/ParallelTypeCheckingTests/Code/TrieApproach/TrieMapping.fs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ open System.Collections.Generic
44
open FSharp.Compiler.Syntax
55
open Microsoft.FSharp.Collections
66

7-
let mergeTrieNodes (defaultChildSize: int) (tries: TrieNode seq) =
7+
let mergeTrieNodes (defaultChildSize: int) (tries: TrieNode array) =
88
let rec mergeTrieNodesAux (root: TrieNode) (KeyValue (k, v)) =
99
if root.Children.ContainsKey k then
1010
let node = root.Children.[k]
@@ -22,7 +22,7 @@ let mergeTrieNodes (defaultChildSize: int) (tries: TrieNode seq) =
2222
else
2323
root.Children.Add(k, v)
2424

25-
match Seq.tryExactlyOne tries with
25+
match Array.tryExactlyOne tries with
2626
| Some singleTrie ->
2727
assert (singleTrie.Current = TrieNodeInfo.Root)
2828
singleTrie
@@ -118,6 +118,7 @@ let rec mkTrieNodeFor (file: FileWithAST) : TrieNode =
118118
visit id longId
119119

120120
Some { Current = Root; Children = rootNode })
121+
|> List.toArray
121122
|> mergeTrieNodes contents.Length
122123
| ParsedInput.ImplFile (ParsedImplFileInput (contents = contents)) ->
123124
contents
@@ -189,6 +190,7 @@ let rec mkTrieNodeFor (file: FileWithAST) : TrieNode =
189190
visit id longId
190191

191192
Some { Current = Root; Children = rootNode })
193+
|> List.toArray
192194
|> mergeTrieNodes contents.Length
193195

194196
and mkTrieForSynModuleDecl (fileIndex: int) (decl: SynModuleDecl) : KeyValuePair<string, TrieNode> option =

0 commit comments

Comments
 (0)