Skip to content

Commit 6f5a37c

Browse files
authored
Merge pull request #196 from fsprojects/daily-perf-improver/optimize-unfold-async
Daily Perf Improver: Optimize unfoldAsync for better memory efficiency
2 parents 193047e + e5c8839 commit 6f5a37c

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

src/FSharp.Control.AsyncSeq/AsyncSeq.fs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,27 @@ type AsyncSeqOp<'T> () =
291291
[<AutoOpen>]
292292
module AsyncSeqOp =
293293

294+
// Optimized enumerator for unfoldAsync with reduced allocations
295+
[<Sealed>]
296+
type OptimizedUnfoldEnumerator<'S, 'T> (f:'S -> Async<('T * 'S) option>, init:'S) =
297+
let mutable currentState = init
298+
let mutable disposed = false
299+
300+
interface IAsyncEnumerator<'T> with
301+
member __.MoveNext () : Async<'T option> =
302+
if disposed then async.Return None
303+
else async {
304+
let! result = f currentState
305+
match result with
306+
| None ->
307+
return None
308+
| Some (value, nextState) ->
309+
currentState <- nextState
310+
return Some value
311+
}
312+
member __.Dispose () =
313+
disposed <- true
314+
294315
type UnfoldAsyncEnumerator<'S, 'T> (f:'S -> Async<('T * 'S) option>, init:'S) =
295316
inherit AsyncSeqOp<'T> ()
296317
override x.IterAsync g = async {
@@ -337,17 +358,7 @@ module AsyncSeqOp =
337358
new UnfoldAsyncEnumerator<'S, 'U> (h, init) :> _
338359
interface IAsyncEnumerable<'T> with
339360
member __.GetEnumerator () =
340-
let s = ref init
341-
{ new IAsyncEnumerator<'T> with
342-
member __.MoveNext () : Async<'T option> = async {
343-
let! next = f !s
344-
match next with
345-
| None ->
346-
return None
347-
| Some (a,s') ->
348-
s := s'
349-
return Some a }
350-
member __.Dispose () = () }
361+
new OptimizedUnfoldEnumerator<'S, 'T>(f, init) :> IAsyncEnumerator<'T>
351362

352363

353364

0 commit comments

Comments
 (0)