Nikolay
Окей
Nikolay
Это в Incr?
Ayrat
Да где хочешь, это запускает ожидание и отправляет на тредпул
Ayrat
Фшарп асинк всегда на тредпул уходит во избежание сайд эффектов
Nikolay
Ayrat
Другое дело
Vasily
Николай познает жестокий мир
Nikolay
Это в Incr
Nikolay
Но с циклом фшарп прожорливее
Ayrat
Сишарп запускает асинк на том же треде синхронно, что даёт лучший перф в редких случаях когда вообще нет ожидания и даёт тонну багов с дедлоками в остальном большинстве случаев
Ayrat
В фшарпе можно добиться того же поведения через StartImmediate
Nikolay
А почему такой код:
let rec loop =
async {
match! inbox.Receive() with
| Unit -> ()
| Done tcs -> tcs.SetResult(())
loop |> Async.Start
}
жрет в два раза больше, чем если в конце do! loop?
Nikolay
Опять гопак с stackoverflow падает :C
Nikolay
Nikolay
Но падает если агент один
Ayrat
Ayrat
Фиксить не будут
Ayrat
Если надо сделать рекурсивный вызов, надо через return!
Ayrat
Диана
А почему такой код:
let rec loop =
async {
match! inbox.Receive() with
| Unit -> ()
| Done tcs -> tcs.SetResult(())
loop |> Async.Start
}
жрет в два раза больше, чем если в конце do! loop?
Используй мемори профайл, он тебе откроет реализацию асинка и ты там увидешь, почему. Я вот, не понимаю совершенно, зачем ты так жестко используешь рекурсию в асинках. В асинках не бывает хвостовой рекурсии, потому что все CE это сначала стейтмашина, а потом уже все остальное. Хвостовая реекурсия для стейтмашин не работает, потому что они стейт и должны состояние свое хранить. Когда ты делаешь рекурсию в СЕ, у тебя будет за вызовом тянутся вся та колбаса итераций, которую ты наделал ранее. Здесь или return!, или без рекурсии.
Ayrat
Используй мемори профайл, он тебе откроет реализацию асинка и ты там увидешь, почему. Я вот, не понимаю совершенно, зачем ты так жестко используешь рекурсию в асинках. В асинках не бывает хвостовой рекурсии, потому что все CE это сначала стейтмашина, а потом уже все остальное. Хвостовая реекурсия для стейтмашин не работает, потому что они стейт и должны состояние свое хранить. Когда ты делаешь рекурсию в СЕ, у тебя будет за вызовом тянутся вся та колбаса итераций, которую ты наделал ранее. Здесь или return!, или без рекурсии.
Для этого фшарп асинк делает трамплин и уносит все на хип
Ayrat
Что как бы избавляет от SO, но не защищает от ООМ
Диана
Версия со Async.Start всегда будет жрать больше ресурсов, чем простой do! потому что Async.Start делает новый порождающий контекст, а do! всего лишь лепит континуэшен к стейту.
Диана
Нужно со всем этим осторожнее. В асинках запросто можно в ногу выстрелить. И не забывать что эт стейт, который заканчивается вызовом return(и иногда return!) или не заканчивается...
Vladimir
Ilya
Ну так места под состояние может не хватить.
Vladimir
ну так состояние то не растет на каждой итерации
Vladislav
Vladimir
это вайл луп? или рекурсия?
Диана
Это do! судя по трейсу
Диана
Vladimir
Диана
Ayrat
это из определения трамплина)
Ну не, определение трамплина не в этом. Трамплин может не захватывать кложуры на предыдущее состояние, а может и захватывать
Ayrat
Vladimir
Vladimir
Ayrat
Vladimir
ну так do! же через трамплин не работает как я вижу) а тупо стек растет
Igor
не понял ничего)
я так понял, одно вычисление заканчивается и новое начинается, поэтому в случае return и не растет
Vladimir
аа, ну так это поведение и есть результат оптимизиации ретурна)
Диана
ну ду то и не оптимизируется, оптимизируется return
Суть асинхронщины в фарше в том, что у тебя есть несколько блоков кода, которые билдер периодически подсовывает на выполнение. Как именно он их подсовывает определяет он сам, а do! и все остальные операторы говорят ему о том, как именно нужно бить код на чанки. Эти блоки связывает одно вычесление. Пока ты его не закончил это return'ном этот контекст будет продолжаться. Посмотри на реализацию технологии CE в фарше, потому что асинхронность тут не причем, а причем именно детали реализации СЕ.
Ayrat
Vladimir
Диана
Можно дописать ретурн! к моему тексту, суть не поменяется.
Vladimir
я конечно не очень силен в нутрях асинк CE, но если бы return! не оптимизировался , то мы бы получили SO или OOM на рекурсивном вызове - верно?
Vladimir
но мы его не получаем) какой вывод?
Диана
Nuxs🏴☠️
А в Fable же, когда вызывается update, обновляется вся страница или только нужное кол-во значений?
Диана
Ретурн заканчивает выполнение, и именно поэтому мы ни чего и не получаем.
Ilya
Nuxs🏴☠️
Nuxs🏴☠️
view каждый раз вызывается снова?
Nuxs🏴☠️
и каждый раз всё обновляется полностью?
Ilya
Какой view? Откуда view?
Ilya
Как напишешь, так и будет, короче говоря.
Диана
Диана
Для СЕ будет ситуация такая - пришел некий блок кода. А дальше по логике самой СЕ. В этом то и особенность, что про рекрусию СЕ даже не догадывается.
Vladimir
да, в ретурнФром приходит объект Асинк (который запустит рекурсивный вызов)
Диана
Не запустит, а вернет то, что пришло в оболочке Async<>. Запускать должен внешний код. Но это мелочи. При этом обрежется весь тот стейт, что предшествовал ретурну, потому что нет смысла его хранить, т.к. мы возвращаем результат и он больше не требуется. Это не оптимизация, это нормальное поведение.
Ilya
так там же init, view и update
Не, я так не могу, извини. Сперва ты спрашиваешь про fable, потом про непонятный view, а теперь у тебя ещё и загадочный "там" появился.
Nuxs🏴☠️
Да блин
Диана
Nuxs🏴☠️
Fable же имеет структуру elmish, да?
Ilya
Fable это компилятор F# в js.
Nuxs🏴☠️
Уже в F# чате ответили
Ilya
Вот и хорошо.
Диана
А то у меня телефон виснет, не могу открыть, исходники слишком большие.
Ayrat
да, в ретурнФром приходит объект Асинк (который запустит рекурсивный вызов)
Трамплины работают на двух объектах. Тот кто запускает (в цикле) объект трамплина и соответственно функцию которая возвращает такой объект (типа бывшая рекурсивная).
Если трамплин не содержит ссылок на предыдущий стейт, то трамплин условно "хвостовой", но по отношению к нему это неточное определение. Но утекать память не будет. если же содержит, то будет утекать память.
При этом в обоих случаях трамплин аллоцируется на хипе
Диана
Ayrat