Skip to content

Commit 8fbb00b

Browse files
authored
Merge pull request #381 from fsprojects/repo-assist/perf-toResizeArray-direct-loop-20260408-116ad7cb53aa926e
[Repo Assist] perf: direct loop in toResizeArrayAsync; simplify tryItem loop
2 parents f3f20ee + d9f5026 commit 8fbb00b

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

release-notes.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Release notes:
33

44
1.0.0
55
- adds taskSeqDynamic computation expression and TaskSeqDynamic/TaskSeqDynamicInfo types for dynamic (FSI-compatible) resumable code, fixing issue where taskSeq would raise NotImplementedException in F# Interactive, #246
6+
- perf: toResizeArrayAsync (and therefore toArrayAsync, toListAsync, toResizeArrayAsync, toIListAsync) uses a direct loop instead of going through iter, avoiding a lambda and DU allocation per call
7+
- perf: tryItem uses a simpler loop that skips the redundant inner index check on every iteration
68
- perf: TaskSeq.chunkBy and chunkByAsync reuse the ResizeArray buffer between chunks, reducing allocations on sequences with many chunk boundaries
79
- fixes: TaskSeq.insertAt, insertManyAt, removeAt, removeManyAt, updateAt now raise ArgumentNullException (not NullReferenceException) when given a null source; insertManyAt also validates the values argument
810
- refactor: simplify lengthBy and lengthBeforeMax to use while! and remove the redundant mutable 'go' and initial MoveNextAsync

src/FSharp.Control.TaskSeq/TaskSeqInternal.fs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -532,12 +532,16 @@ module internal TaskSeqInternal =
532532
yield result
533533
}
534534

535-
let toResizeArrayAsync source =
535+
let toResizeArrayAsync (source: TaskSeq<'T>) =
536536
checkNonNull (nameof source) source
537537

538538
task {
539-
let res = ResizeArray()
540-
do! source |> iter (SimpleAction(fun item -> res.Add item))
539+
let res = ResizeArray<'T>()
540+
use e = source.GetAsyncEnumerator CancellationToken.None
541+
542+
while! e.MoveNextAsync() do
543+
res.Add e.Current
544+
541545
return res
542546
}
543547

@@ -915,14 +919,14 @@ module internal TaskSeqInternal =
915919
let! step = e.MoveNextAsync()
916920
go <- step
917921

918-
while go && idx <= index do
919-
if idx = index then
920-
foundItem <- Some e.Current
921-
go <- false
922-
else
923-
let! step = e.MoveNextAsync()
924-
go <- step
925-
idx <- idx + 1
922+
// advance past the first `index` elements, then capture the current element
923+
while go && idx < index do
924+
let! step = e.MoveNextAsync()
925+
go <- step
926+
idx <- idx + 1
927+
928+
if go then
929+
foundItem <- Some e.Current
926930

927931
return foundItem
928932
}

0 commit comments

Comments
 (0)