F# Утечка памяти при использовании use в rec async
От: vaa  
Дата: 02.04.22 16:52
Оценка:
Экспериментировал тут и наткнулся на странность. Баг или фича?

open System
open type System.Console

type Msg = | GetCount of AsyncReplyChannel<int>

let counter = MailboxProcessor<Msg>.Start(fun mb ->  
     let rec loop s = async {                         
         let! (GetCount repl) = mb.Receive()        
         repl.Reply s   
         return! loop (s + 1)                         
         }
     loop 1)

let useColor color = 
    let old = ForegroundColor
    ForegroundColor <- color
    {new IDisposable with member it.Dispose () = ForegroundColor <- old }

let repeat color =

    let rec loop () = async {        
        let! id = counter.PostAndAsyncReply GetCount
        let x = useColor color in do WriteLine $"{id}"; x.Dispose();// если заменить строку на  'use _ = useColor color in do WriteLine $"{id}"' начинает течь память
        return! loop ()
    } 

    loop ()


for e in  ConsoleColor.GetValues() do
    repeat e |> Async.Start
☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 04.04.2022 11:49 Разраб . Предыдущая версия .
Re: F# Утечка памяти при использовании in
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.04.22 21:10
Оценка: 18 (3)
Здравствуйте, vaa, Вы писали:

vaa>Экспериментировал тут и наткнулся на странность. Баг или фича?


use ломает хвостовую рекурсию так как втыкает finally после return и функция честно держит весь стек. Вот тебе и утекчка.
Вообще детерминированная освобождение + рекурсия + асинхронность — страшный коктейль независимо от языка. В этом случае хорошо работает правило "выберите два".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.