Vladimir
мб что-то сделают в ноутбуках хорошего, сейчас непонятно
Vladimir
ну вот в будущем и проверим)
Vladimir
а пока только слова
Vladimir
был такой проект глобальный fslab, но он сдулся так и не развившись
Igor
О блин, оказывается Jupiter Notebook прямо в VS Code можно использовать
Hog
ага
Я блин месяц потратил на выкашиванье этой ебаты :( датасатанист вхерачил всюду, где рука достала
Vladimir
он не виноват, года три-четыре назад это было лучшее что есть в дотнете
Vladimir
а потом микрософтовцы его похоронили как сегодня оцелот - просто свою официальную реализацию сделали
Vladimir
если они сделают официальную либу для пульсара, то и наша пойдет по ... , потому что никто не авторитет в дотнете против микрософта)
Ilya
Да, не повезло с комьюнити.
Диана
let loop (inbox: MailboxProcessor<Message>) = let rec loop () = async { match! inbox.Receive() with | Unit -> () | Done tcs -> tcs.SetResult(()) do! loop () } loop ()
Этот код заминирован. Вместо do! loop() нужно писать return! loop() потому что do! плодит дополнительный AsyncActivationContents на каждую итерацию. Это примерно как себя по ноге напильником пилить миллион раз.
Андрей
Вообще смотрю гопак, такая крутая штука, но полузаброшена :(
всмысле полузаброшена? работает - тащи в прод и все
Диана
Вангую, что при правильном подходе расход памяти сократиться на порядок с шарповским медленным мейлбоксом, который внутри на lock'ах сделан наполовину.
Nikolay
61 мб наплодил на 1кк итераций
Nikolay
А если заменить на рекурсию, то 888 байт уже уходит
Nikolay
Но это не сработает, если нужно в теле цикла дождаться результата выполнения асинка
Nikolay
Есть идея правда заинжектить IL напрямую, и сделать джамп
Nikolay
всмысле полузаброшена? работает - тащи в прод и все
Ну вот я наткнулся на эксепшн в простом кейсе
Nikolay
Ишуев там смотрю тоже много, которые давно висят, и никто их не собирается править
Nikolay
Что ему надо?
Nikolay
Не получится
Vladimir
ты невнимательно код айрата смотрел)
Vladimir
let msgCount = 1_000_000 [<Benchmark>] member this.FSharpMb () = let tcs = TaskCompletionSource() let rec loop (inbox: MailboxProcessor<_>) = async { match! inbox.Receive() with | i when i = msgCount -> tcs.SetResult(()) | i when i%10 = 0 -> do! Async.SwitchToThreadPool() return! loop inbox | _ -> return! loop inbox } let processor = MailboxProcessor.Start loop for i=0 to msgCount do processor.Post(i) tcs.Task.Result [<Benchmark>] member this.HopacMb () = let ivar = IVar() let loop (mailbox: Hopac.Mailbox<_>) = job { match! mailbox with | i when i = msgCount -> do! ivar *<= () | i when i%10 = 0 -> do! Job.Scheduler.switchToWorker() return () | _ -> () } |> Job.foreverServer |> start let processor = Hopac.Mailbox() loop processor for i=0 to msgCount do processor *<<+ i |> start run ivar
Vladimir
джобы в гопаке похоже и не планровались быть рекурсивными
Nikolay
Проблема в том, что они и без рекурсии падают
Nikolay
И без рекурсии падают раньше, чем с рекурсией
Vladimir
без рекурсии падают с какой ошибкой?
Nikolay
stack overflow
Nikolay
let tcs = TaskCompletionSource() let loop i = job { let mutable i = 0 while true do if i >= 100_000 then tcs.SetResult() i <- i + 1 } loop 0 |> start tcs.Task.Wait()
Nikolay
Но у меня работает!
У тебя нет цикла!
Nikolay
В жобе
Ayrat
У меня код все равно зациклен
Nikolay
Ну да, но все равно согласисть, что бага
Vladimir
да, если циклы нельзя писать внутри джобов это очень плохо)
Nikolay
Типа если надо читать, например, из сокета то у тебя все плохо
Nikolay
И вообще я хз как тут жыть в фшарпе
Nikolay
Если асинхронный цикл аллокации дикие делает
Vladimir
ну типа вместо цикла в джобе ты должен бесконечно запускать джобу
Ayrat
Если асинхронный цикл аллокации дикие делает
А в сишарпе пробовал асинхронный цикл?
Nikolay
Можно проверить
Ayrat
Есть мнение там мусора на порядок больше
Ayrat
В обычном вангую плохо for each ... await В новом асинхронном стриме должно быть лучше
Ayrat
Я не помню синтаксис нового
Vladimir
В обычном вангую плохо for each ... await В новом асинхронном стриме должно быть лучше
ты прямо скопировал код с примеров как юзать пульсар! https://github.com/fsharplang-ru/pulsar-client-dotnet/blob/develop/examples/CsharpExamples/RealWorld.cs#L32-L35
Ayrat
У вас кстати новые асинк стримы поддерживаются?
Vladimir
не проверял, но по крайней мере тут стэковерфлоу не падает) ни в сишарпной ни в фшарпной версии
Vladimir
У вас кстати новые асинк стримы поддерживаются?
неа, их можно по идее поддержать, но гемора будет.. там же все атрибуты возможные надо поддержать
Ayrat
Для тебя гемор, а для пользователя счастье
Vladimir
не уверен, там надо же эксешпны хэндлить, посмотри пример
Ayrat
не уверен, там надо же эксешпны хэндлить, посмотри пример
Ну всегда можно возвращать стрим резалтов)
Ayrat
Чтобы пользователь сам хендлил
Nikolay
[<Benchmark>] member x.FSharpLoop() = async { let mutable s = 0 let incr = async { s <- s + 1 } while s < x.CountMessages do do! incr } |> Async.StartAsTask
Nikolay
public async Task CSharpLoop(int countMessages) { var s = 0; Task Incr() { s += 1; return Task.CompletedTask; } while (s < countMessages) { await Incr(); } }
Nikolay
Nikolay
[<Benchmark>] member x.FSharpLoop() = let mutable s = 0 let rec incr = async { s <- s + 1 if s < x.CountMessages then return! incr } incr |> Async.StartAsTask
Nikolay
Так получше
Nikolay
Но все еще плохо
Nikolay
Ayrat
Эх, Николай
Nikolay
В 10 раз быстрее, лол
Ayrat
Нихуя ты о сишарпе не знаешь.
Nikolay
Нихуя ты о сишарпе не знаешь.
Хочешь сказать оптимизировал?
Ayrat
Хочешь сказать оптимизировал?
У тебя тут нет ожидания
Ayrat
Все на одном треде
Nikolay
Но
Ayrat
Без свичей, тредпула и стейт машин
Nikolay
Код я написал идентичный
Ayrat
Потому что идентичный это с добавлением как минимум await Task.Yield()