кана
проблема такого подхода - файл может быть огромный, причем все символы могут быть '\n'
кана
это займет всю память при даже тупом хранении индексов
Dmitry
Да
Dmitry
Вот за два прохода понятно как сделать...
Anonymous
Должны быть какие-то ограничения по размеру файла и ясность, на что хватает памяти.
Если файл ну оочень большой и памяти совсем мало, то всё как-то невмеренно сложно
кана
да, файл очень большой
и нет, тупо чтение блоками с начала и конца не сильно сложно пишется на императивных языках (ну по крайней мере в моем представлении) и прекрсно работает по памяти (максимум два блока одновременно в памяти, размер блока выбирается любой)
проблема в переносе этого в хаскель (причем в идеоматичный, как в примере использования выше)
Dmitry
Ну если читать можно с конца, то этот способ норм.
кана
да, просто функция readLinesBackward не написана)
кана
в данный момент она определена как reverse <$> readLinesForward чтобы проверить работоспособность идеи
кана
я пытался написать такое но для чтения с начала (при этом пиша код так, чтобы потом можно было легко заменить на чтение с конца) и вот на этом сдался
Dmitry
Ну ты можешь смапить файл в байтстринг, как я выше писал, а потом двигаться от fileSize к нулю в поисках переносов
кана
а то я начал и чет офигел
кана
хм, а чтение конца байстринга не форсит чтение начала?
кана
тогда да, идея норм, завтра попробую
Anonymous
Понятно.
Да, можно читать из 2 потоков: с начала и с конца (см.
http://hackage.haskell.org/package/base-4.10.1.0/docs/System-IO.html#v:LineBuffering)
При чтении находить \n и сохранять позицию \n в файле и # пп
Как только один из потоков доходит до середины файла, он останавливается и ждёт другого.
Можно с MVar
Anonymous
Остановиться посередине можно для того, чтобы не прочитать больше 1 раза.
Хотя если сверять прогресс на каждой строке через MVar, то можно и перейти половину
hSeek с Handle под LineBuffering в помощь
Dmitry
@kana_sama Ну у меня вот так получилось: http://bpaste.net/show/788e16dc69f1
Dmitry
findLinesBackward :: B.ByteString -> [(Int, B.ByteString)]
findLinesBackward origStr = go origStr (B.length origStr) (B.length origStr)
where
go str from to =
case B.unsnoc str of
Nothing -> []
Just (init, '\n') -> (from, substring from to origStr) : go init (from - 1) from
Just (init, last) -> go init (from - 1) to
Dmitry
Только я это писал из расчёта, что в конце файла нет переноса строки, а то иногда редакторы вставляют его.
кана
ого, спасибо
кана
я только добил свой страшный посимвольный считыватель
кана
https://gist.github.com/kana-sama/415a0d3f8a227a70fd69d519644ca8f9
Dmitry
Ну вот мегапреимущество mmap'а в том, что все эти буферы, посимвольное чтение и т.п. берёт на себя ОС, а у тебя просто есть кусок памяти, который соответствует файлу, поэтому не надо вот этого всего. Ну а ByteString на это всё идеально натягивается, ведь ByteString -- это же просто пара (указатель на память, длина строки).
Dmitry
А, ещё смещение. Т.е. всё-таки тройка (указатель, смещение, длина). Ну, не принципиально в данном случае.
кана
кана
количество памяти постепенно растет
кана
на файлке в 7мб (999999 строк) он сожрал аж 800мб
кана
начинал с 10мб
кана
а, ну конечно, у меня там reverse ls
кана
да и массив строится в конце
кана
чего я ожидал, нужно идти спать
Anonymous
Кажется, в память читается весь файл, или нет?
Думал, памяти мало, а файл большой.. 😞
Вот бы ещё уточнить: помещаются ли в память любые 2 строки из файла. Или хотя бы одна.
Alexander
через стриминг ну или любую стриминг либу можно зопилить, кол-во кода правда будет похожее с lazyio
kosc
@qnikst так что в итоге, идёшь на ITGM?
Alexander
он в субботу?
kosc
Да.
кана
Alexander
я записался, но это не точно что иду
Alexander
к субботе виднее будет
Alexander
@kana_sama ещё так можно:
Alexander
https://paste.pound-python.org/show/o6emVGOcjf74bpar671d/
Alexander
(не оптимизировал, не тестил)
Alexander
можно более модульно, но мне лень было
Vasiliy
мб еще как вариант можно на кондуитах сделать это, не знаю есть ли смысл
Alexander
кондуиты не нужны
Alexander
на любой стримовой библиотеке можно
Андрей
чем кондуиты плохи?
Alexander
overengineered
Alexander
вообще нормальные
кана
Alexander
+- одно и тоже везде выйдет
Alexander
вон выше если хочется совсем выпендрться то можно через hReadBuf заделать
Alexander
тогда временные байтостроки выделяться не будут
Андрей
эх рас уж про кондуиты начали говорить
мне показалось или в хаскеле не очень заморачиваются с реактивностью и стримингом
Андрей
показалось мне это после скалы
Андрей
это как-то связанно с ленивостью?
Alexander
ленивость очень много дает от стримов
Alexander
да
Alexander
поэтому более менее заморачиваются только для IO
Alexander
где ещё играет и освобождение ресурсов или хочется использовать фиксированные буфферы и т.п.
Alexander
или как-то ещё явно ограничить время работы с ресурсами, чтобы не размазывать их по программе
Anonymous
Alexander
https://hackage.haskell.org/package/streaming
Alexander
ну тут не принципиально это выражается на всем iteratee, machines, conduit, pipes
Андрей
ок, спасибо за пояснение
Anonymous
Alexander
приятная либа
Alexander
очень простая по сравнению с пайпами и кондуитами и машинками, но толковая
Alexander
если захочется bidirectional streaming то что делать - не знаю
Alexander
как в пайпах и машинках можно
Alexander
правда на работе высказывалось мнение что bidirectional streaming не нужен, но я что-то не поверил
Denis
аргументы какие что не нужен?
Kirill
а есть юзкейсы где сильно нужен?
Denis
вообще да, интересно аргументы в обе стороны послушать
Alexander
не было норм аргументов
Alexander
основная идея была в том, что кейсов где нужен мало и мол можно все их переделать в односторонний
Anatolii
а в manning можно как-то апгрейд ebook в pbook сделатЬ?
Alexander
меня бесят что все эти магазины очень фигово в россию отправляют