Зигохистоморфный
о! etalang https://github.com/carymrobbins/intellij-haskforce/releases/tag/v0.3-beta.38
Vladislav
спам
Denis
Глупый вопрос по оптимизации: есть `f cb = someMonadicAction1 >> cb >> someMonadicAction2`, и где-то есть `ff (return ())` - может ли этот `return ()` быть выкинутым компилятором?
кана
Внутри >> может происходить какая-то логика, которую нельзя выкинуть.
Denis
ну, допустим, у нас IO
Denis
А как вообще это проверить можно? GHC может выдавать тонну промежуточной отладочной информации, и в ней не очень-то приятно копаться. Есть ли какой-нибудь относительно простой способ увидеть, что и как оптимизируется?
Denis
"отладочной информации" - в смысле, результатов стадий компилации, которая не очень-то читабельная
Cheese
да, есть несколько стадий компиляции, и почти все они могут сдампить свой результат, каждая в своём формате
Cheese
обычно начинают с -ddump-simpl — так называемый Core
Cheese
вот тут подробно https://takenobu-hs.github.io/downloads/haskell_ghc_illustrated.pdf
Denis
о, спасибо, почитаю
Denis
(ну или мне надо в себе "низкоуровнего сишника" давить:))
Cheese
скорее, подавить операционного семантиста
Cheese
у Хаскелла денотационная семантика убер аллес, то есть компилятор оставляет за собой право как угодно менять твой код при условии сохранения результата
Cheese
правда, на практике он не так уже сильно меняется
Denis
да, я это понимаю, и наверно поэтому каждый раз возникает вопрос эффективности в "критических секциях"..
Cheese
я обычно разбирательство в коде начинаю с -ddump-simpl -dsuppress-all и на этом же заканчиваю, потому что всё становится понятно
Denis
ещё часто Debug.Trace.trace помогает. Кстати, в описанном выше случае, похоже, ничего не отсекается.
Alexander
если там было определение ff и оно заинлайнится и это IO то будет выкинуто, но не представляю как debug.trace-ом это хотелось проверить
Denis
Ну вот например:
main = do
f (putStrLn "!")
f (return $ trace "_1" ())
f (trace "_2" $ return ()) where
f cb = putStrLn "1" >> cb >> putStrLn "2"
выводит _2
Denis
с другой стороны, может ли trace тут влиять на решения оптимизатора?
Leonid 🦇
Ещё как
кана
Вот один костыльный способ проверить: копипастом добавь сотню-две таких пустых операций и посмотри на размер результатирующего бинарника
Cheese
и на скорость ещё можно посмотреть
Cheese
и на разных уровнях оптимизации проверить
Denis
о, без -O2 размер растёт, с -O2 - нет. При этом вариант с trace всё равно срабатывает, что и логично. Спасибо!
Denis
притом с -O2 по``-ddump-simpl` видно, что `f` заинлайнено
Denis
в общем, проблема была лишь в том, что я забыл про параметр -O
Vasiliy
Alexander
нужно на ddump-simpl смотреть и все
Vasiliy
гм... я читал, что компилятор активно пользуется законами при оптимизациях
кана
Хм, а если им не следовать?
кана
Определить >> с каким-нибудь эффектом
Евгений
Ну типа если ты им не следуешь, то ссзб
Vladislav
Заходим в рекламируемые каналы и жмём Report -> Spam. Чем больше будет репортов, тем вероятнее, что мы избавим телегу от спамеров!
Donat
-Почему-то нет такого пункта в меню у меня. Только на мобильном клиенте?-
Нашлось.
Anonymous
Добрый вечер всем. В гугле забанили, ничерта не понимаю.
Поделитесь, пожалуйста, докой/примерами (желательно с описанием того, что пишут...) по Alex/Happy, спасибо!
Aleksei (astynax)
По ним вроде книжка была
Aleksei (astynax)
https://leanpub.com/alexandhappy/read
Anonymous
Спасибо
Vladislav
Заходим в рекламируемые каналы и жмём Report -> Spam. Чем больше будет репортов, тем вероятнее, что мы избавим телегу от спамеров!
Denis
Дня всем доброго! В документации Control.Monad.Trans.Resource крайне рекоммендуют освобождать ресурсы вручную, не дожидаясь авточистки. А чем грозит обратное, с практической стороны? Я пишу backend на servant-е, и, соответственно, нужно выдавать Connection-ы к бд обработчикам запросов из пула, потом их туда возвращая. Пока надумалось только два варианта: внутри каждого обработчика вызывать что-то типа withConnection, либо отдавать Connection обработчикам из-под instance HasServer, и через Control.Monad.Trans.Resource.register его возвращать в пул. Первый вариант несколько некрасив, второй не подразумевает ручного освобождения ресурсов.
Anatolii
можно попробовать что-то вроде https://hackage.haskell.org/package/resource-pool
Denis
а оно сейчас и используется. Вопрос только в том, как возвращать соединение обратно в пул
Alexander
+ к resource-pool
Alexander
оно само, по выходу из withResource
Denis
withConnection через него и работает
Alexander
ну и все
Denis
ну тогда каждый обработчик запроса надо будет в него оборачивать, а это некрасиво совсем
Anatolii
putResource
Anatolii
я не очень уверне что конект к базе надо брать в самом начале запроса
Alexander
зачем каждый оборачивать?
Alexander
если вообще всегда каждый надо, то через mmorph или что-там, сделать чтобы они в ReaderT Connection работали
Denis
в моём случае, 99% api-запросов состоят из одного SQL-запроса
Alexander
тогда только 1 раз при инициализации надо сделать
Alexander
вообще я большой разницы между обернуть и "takeResource" не вижу, в первом случае даже кода меньше
Denis
но всё же, чем плохо надеяться на ..Resource.register?
Denis
ну, отбработчики попроще получаются. Там будет что-то типа Connection -> ApiHandler a, состоящий только из запросов, то бишь вся "кухня" возни с пулами будет скрыта.
Anatolii
а где ты прочел что оно рекомендует отпускать ресуры вручную?
Alexander
resourcet сделано для того, чтобы можно было отпустить ресурсы когда укажешь
Alexander
не то, что рекомендуется, но сделано в основном для этого
Denis
https://hackage.haskell.org/package/resourcet-1.1.9/docs/Control-Monad-Trans-Resource.html: Releasing may be performed before exit via the release function. This is a highly recommended optimization, as it will ensure that scarce resources are freed early. Note that calling release will deregister the action, so that a release action will only ever be called once.
Alexander
отпустит и без
Alexander
по выходу из resourcet
Alexander
в отличии от lazy io и надежды на GC
Alexander
они про это пишут
Denis
тоесть есть шанс ненулевой, что ресурс освободится несколько позже?
Denis
в случае backend-а это может к dos-у привести :)
Alexander
если без resourcet - то да
Alexander
ну как - на следующем GC
Alexander
маловероятно, что ты напишешь такой код, что не навыделяет нужное кол-во памяти, пока скажем все сокеты не займешь, максимум коннектов к базе
Alexander
но формально такая возможность есть
Alexander
опять же если делаешь runResourceT то можешь не бояться за этло
Alexander
оно по выходу из ResourceT все сразу освободит
Anatolii
мне кажется что это преждевременная оптимизация
Denis
ну, runResourceT делается внутри servant-а, на стадии route
Denis
может и преждевременная, но мне почему-то кажется, что это вопрос архитектуры:) Сейчас, на начальной стадии, плохо продумаю, потом страдать буду.
Alexander
там все просто поменять :)