Ayrat
понятное дело. я бесконечный цикл тоже не для развлечения пускаю
подтверждаю net461 + hopac 0.4.1 (ресторится нетстандарт версия) + неважно какой tailcall флаг = падает с SO net471 + hopac 0.4.1 (ресторится фулл 471 версия) + неважно какой tailcall флаг = не падает с SO netcoreapp2.1 + hopac 0.4.1 (ресторится нетстандарт версия) + неважно какой tailcall флаг = не падает с SO можно сделать только один вывод. Флаг tailcall ни на что не влияет :D
Ayrat
с флагом интересно
gsomix
А почему он должен влиять?
gsomix
Ок. Разве флаг tailcall — это не про .NET tailcall?
Ayrat
про IL инструкцию, да
Pavel
если я помню правильно разница была в том развернется rec в цикл или просто впендюрится tailcall в IL
Ayrat
кстати @deexpp ещё стата net461 + hopac 0.3.23 (ресторится под net45) = НЕ падает с SO
gsomix
если я помню правильно разница была в том развернется rec в цикл или просто впендюрится tailcall в IL
Была. Плюс, сейчас же JIT умный, он может тоже пытаться оптимизировать.
Ayrat
т.е. проблема случается если net461 с нетстандарт либой скрещивать. ебанина случается, я не знаю где беда, но короче так делать не надо
Vladislav
Вы про это?
Vladislav
<Optimize>true</Optimize> <Tailcalls>true</Tailcalls>
Ayrat
а C# падает
Ayrat
но по моим быстрым тестам, это какое-то плацебо
Dr. Friedrich
Была. Плюс, сейчас же JIT умный, он может тоже пытаться оптимизировать.
JIT давно был умный и пытался оптимизировать, но вряд ли ему под силу разобраться в выхлопе F#-компилятора.
Ayrat
я не пишу FSC, ниибу что эти флаги на самом деле делают. Может быть проблема и не во флагах а в хитрой проблеме net461 + netstandard2.0
Dr. Friedrich
(ну, про инлайн-функции было бы по-другому, но тут у вас их, наверное, нету)
Ayrat
а, Hopac.Core же на C# написан
Ayrat
может в этом дело
Dr. Friedrich
а C# падает
Не всегда. Со старым JIT'ом можно было скомпилить так, что не падало, если зафорсить x64.
Ayrat
Не всегда. Со старым JIT'ом можно было скомпилить так, что не падало, если зафорсить x64.
приведи пример актуального кода на C# который бы не падал с SO на рекурсии
Ayrat
Не могу.
я вот тоже. Поэтому в умный жит не верю
Dr. Friedrich
Только со старым JIT'ом очень давно можно было такого добиться. Начиная с RyuJIT, а то и пораньше, всё сломалось.
Ayrat
короче, среди меня есть подозрение, что тут (в ситуации SO в гопаке) всё сложно. Проще эмпирически не юзать net461 таргет с новой версией гопака (которая таргетит net471 и netstandard2.0), или брать предыдущую версию 0.3.* для net45, или вообще навсегда забить на фул фреймворг и сидеть как человек на netcoreapp
Vladislav
Скорее всего там старый джит тогда
Vladislav
И все
Pavel
Pavel
но это не самое интересное
Ayrat
не понял я как ты отресторил в 4.5 у меня даже опции такой нет
я таргетил 461 в fsproj, версию поставил 0.3.23 и сделал dotnet restore —force
Pavel
приехал кор к этому делу запустился и начал делать вид что работает
Ayrat
0.3.23 таргетит netstandard1.6 и net45 для net461 он выбирает net45 версию, и всё работает
Pavel
но память...
Ayrat
но память...
Это by design
Ayrat
ЩА РАССКАЖУ
Pavel
э нет.. в 4.7.1 такого нет
Ayrat
стримы в гопаке - ПЕРСИСТЕНТНЫЕ
Ayrat
э нет.. в 4.7.1 такого нет
не, оно там может быстро собирать, memory pressure там одинаковый
Ayrat
другое дело что netcoreapp может собирать реже всю эту гору мусора
Ayrat
проверь dotmemory
Ayrat
убедишься
Ayrat
Короче, лично мне не нужна персистентность стримов, поэтому я сделал свои
Ayrat
и они не грузят GC
Ayrat
и вообще збс
Klei
стримы в гопаке - ПЕРСИСТЕНТНЫЕ
Можно подробнее, что есть персистентный и неперсистентный стримы?
Ayrat
Можно подробнее, что есть персистентный и неперсистентный стримы?
это значит что при replay этого стрима он тебе выдаст сразу стрим вычисленных значений без сайдэффектов
Pavel
Pavel
это 4.7.1
Ayrat
а для этого он должен где-то хранить (heap) всю эту гору запомненных значений
Ayrat
короче, он мемоизирует все вычисления сразу же. Я не считаю это хоршим дефолт поведением, но автор считает что это более функционально и чисто. Я считаю что это менее пригодно для работы
Pavel
Pavel
это тоже 4.7.1 но для версии 0.3.23
Ayrat
а, ну мемори лик там какой-то пофиксили в 0.4.1
Ayrat
может даже именно тот на который ты наткнулся)))
Klei
Ядренбатон.
Pavel
поэтому надо фолдить не отходя от кассы :)
Vladislav
сэр у нас пробоина
Ayrat
let stream = [1..10] |> Stream.ofSeq |> Stream.mapJob (timeoutMillis 1000 >>-. ()) stream |> Stream.iter |> run вот эта штука будет ранится первый раз 10 сек, а второй раз моментально, т.к. сайдэффект в виде таймаута уже будет поигнорен (мап уже вычислен в unit и запомнен)
Ayrat
логично что 10 запоменных unit значений будут жить на хипе
Klei
А как в гопаке кошерно реализовать генерацию запросов (конкретно к актору) по таймауту?
Ayrat
поэтому надо фолдить не отходя от кассы :)
поэтому надо пользоваться моими неперсистентными стримами! Планы впилить их в апстрим гопака
Ayrat
С этим я еще не сталкивался, а вот с проблемами по памяти уже.
К сожалению, базовые стримы гопака генерят тонну мусора, т.к. они создают ненужные промисы всё равно даже если стрим моментально фолдится.
Pavel
А как в гопаке кошерно реализовать генерацию запросов (конкретно к актору) по таймауту?
всё началось с такого infiniteStream (fun () -> DateTime.Now) |> Stream.afterEach (timeOutMillis 1000)
Ayrat
т.е. все промежуточные этапы ТОЖЕ запоминаются и уходят на хип и сразу же становятся мусором
Klei
всё началось с такого infiniteStream (fun () -> DateTime.Now) |> Stream.afterEach (timeOutMillis 1000)
Да я вот тоже заюзал стрим как генератор последовательности, а он систему положил выжрав всю память.
Pavel
от мы с утра и выясняли отчего infiniteStream память отжирает
Vasily
В теории можно было бы починить мемоизацией слабых ссылок