Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет superhuman ([info]superhuman)
@ 2014-06-12 10:07:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
В высокоуровневых ЯП обычно есть функции, чтобы прочесть файл в байт-массив (байт-строку) и, наоборот, сбросить массив в файл. Идея в том, чтобы не париться со всякими буферами хуюферами, и в одну строчку такую задачу решать.

Понадобилось мне нонче iso-шки читать как блобы и переколбашивать их. Выясняется, что на больших файлах эти самые функции не работают! (в трёх ЯП, как минимум) В racket-е (с чего я начал), читается не более 380 мб, записывается не более 700 мб, - причём без всяких эксепшенов.

Потом позырил дотнет - там до .net-4.5 вообще никакие объекты не могли быть больше 2 гб в памяти. Нахуйя мне 32 гб рамы, спрашивается? Ну ладно, в 4.5 они типа поддерживают больше, но индексы в массивах всё равно 32-битного типа, т.е. байт-массив всё равно не может быть больше 2 гб. Ебанись.

Посмотрел байт-строки haskell-а, но там тоже индекс типа 32-битного integer-а. Хотел посмотреть ещё в J, но в онлайне не нашёл соответствующей документации. Хотя и пишут, что эта система "true 64 bit", но доверия уже никому нет. Надо будет попробовать всё же, J и сам по себе интересен.

Короче, вернулся к схеме и хуярю этими самыми чанками / буферами. Так-то работает, и не так много онанизма, в схеме всё-же индексы могут быть большие. Но всё равно, ощущение от этого кодостиля, блядь, что это 70-й год примерно.


(Добавить комментарий)


[info]dorkavla
2014-06-12 17:32 (ссылка)
Хотеть можешь чего угодно, а size_t никому не избежать.
Не говоря о том, что именно подобными вашим попытками buffer overflows с последующими vulnerabilities и образуются.

(Ответить) (Ветвь дискуссии)


[info]phantom
2014-06-12 20:29 (ссылка)
В каком смысле не избежать? Я его избегаю посредством неиспользования C/C++.

Buffer overflows - это проблема низкоуровневых языков, таких как С/С++, опять же.

(Ответить) (Уровень выше)


[info]666
2014-06-12 18:38 (ссылка)
попробуй файл мэппинг

(Ответить) (Ветвь дискуссии)


[info]phantom
2014-06-12 20:34 (ссылка)
Ну, это не подходит, т.к. я хочу загрузить в память сразу всё, а так оно на диске останется, и операции будут фактически операциями с диском.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]666
2014-06-12 21:11 (ссылка)
операции вроде бы в основном с кешем будут, т.е. с памятью

а если подчитать большой файл целиком, получится то же самое - потом окажется, что работал со свопом, а не с памятью,
так что надо выставлять воркинг сет и лочить страницы в памяти, а все эти скриптоязыки наверняка это не делают

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-12 22:04 (ссылка)
Не делают, но у меня выставлен лимит в половину рамы. Т.е. довольно большая уверенность, что всё будет в памяти.

(Ответить) (Уровень выше)


[info]phantom
2014-06-13 00:19 (ссылка)
Собственно, функции-то я написал - my-write, my-read, грубо говоря, и теперь можно в одну строчку грузить/выгружать. Проблема не в том, что я не знаю, как их написать. Проблема в том, что мне их, вообще, пришлось писать.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]666
2014-06-13 03:00 (ссылка)
может дело в том что чтение-запись файла это нетривиальная хуйня, очень по-разному можно реализовать
с учётом одновременности доступа, контроля ошибок, лок-анлок, и тд

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-13 10:07 (ссылка)
Ой. Я тебя умоляю. Проще этого, наверное, хелловорд только.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]666
2014-06-13 15:09 (ссылка)
а ты посмотри как реализовано какое-нибудь стандартное копирование файлов, казалось бы - прочитал да записал, а оно от тыщи строк на си

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-13 22:22 (ссылка)
Ну, посмотрел - cp из coreutils. Ядро-то там десяток-другой строк. Всё остальное - отработка опций командной строки. Немного обработка ошибок и всяких исторических квирков. Плюс рекурсивное копирование директорий. И не тыщи, а три-четыре тысячи, со всем мутью за десятки лет накопленной.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]666
2014-06-13 22:54 (ссылка)
так а что из этих 4к строк должно быть в желаемых стандартных либах на скриптоязыке, а что не должно

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 02:46 (ссылка)
Для меня желательно, чтобы можно было файл загрузить в одну строку и выгрузить в одну строку.

В стандартной либе реализация этого должна быть в пару десятков строк.

Вот, я смотрю в стандартной либе рэкета, как раз чтение там - 20 строк, включая обработку ошибок.

(Ответить) (Уровень выше)


[info]phantom
2014-06-13 22:29 (ссылка)
И вообще, "тыщи строк" - обычно показатель тривиальности. Вот в методе Рунге-Кутта всего-то < 10 строк, но в каждую вложены десятки, если не тысячи человеко-лет труда.

Или вот ещё проще нетривиальный пример в три строки. Обменяй значения двух (целочисленных) переменных, не прибегая к третьей переменной.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]666
2014-06-13 23:16 (ссылка)
ну так можно сказать, что в первую букву вложен миллиард лет, а copyfile написали всего за 10

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 02:47 (ссылка)
Это неверно, т.к. я приводил конкретно работу над алгоритмом Рунге-Кутта, а не "подготовку" и исторический процесс, приведший к появлению компьютеров, алгоритмов и Рунге-Кутта.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]666
2014-06-14 05:08 (ссылка)
не верно, потому что нет связи между человеко-годами и сложностью результата в строчках

почему тогда тысячи строк = показатель тривиальности?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 12:04 (ссылка)
Ну да, это я загнул, нету такой связи.

(Ответить) (Уровень выше)


[info]phantom
2014-06-14 13:16 (ссылка)
Однако, когда хвалятся, мол, "мы нахуярили 250 млн строк кода", это обычно означает, что там везде копипаста.

(Ответить) (Уровень выше)


[info]ketmar
2014-06-14 16:10 (ссылка)
you are terribly wrong. ты, например, обрабатываешь EINTR после read()? а почему? а ты в курсе, что если у нас какая-нибудь сетевая fs через fuse, то… и так далее. а ошибки close() кто-нибудь вообще обрабатывает?

кстати, приветмир — тоже очень нетривиальная программа. обычный сишный пример с printf() — уже неправильный: опять забыли обработать ошибки i/o.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-14 16:13 (ссылка)
p.s. а вот этот приветмир, кстати, правильный:
import std.stdio;
void main () {
  writeln(`Hello, world`);
}

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 21:14 (ссылка)
С ума сойти, какая нетривиальная программа, хехе.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-14 22:08 (ссылка)
как ни странно. тем не менее, дишный вариант — единственный, который нормально обрабатывает ошибки без дополнительных телодвижений.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 22:48 (ссылка)
А какие, вообще, ошибки имеются в виду? Можно поподробнее? Я ж не системный программист, по сути.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-14 22:58 (ссылка)
ошибки i/o: вообще-то tty может и отсутствовать. или сломаться посреди дороги. printf(), конечно, об этом просигнализирует как минимум несовпададающим количеством выведеных символов и того, сколько надо было вывести, но:
а) почти никто не проверяет результата printf();
б) если там что-то сложнее простой строки, то количество символов не угадаешь.

D в этом плане консервативен, и просто кинет исключение. непойманное исключение ведёт, натурально, к завершению программы с кодом ошибки. я считаю, что подход «для того, чтобы наплевать на ошибку, надо напрягаться больше, нежели для того, чтобы не наплевать» идеологически более правильным.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 23:04 (ссылка)
В смысле надо писать main { return printf("hello world"); } вместо main { printf("hello world"); } ?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-14 23:23 (ссылка)
и это тоже фигня, на самом деле. да ещё и неправильная, потому что printf() возвращает или отрицательное число, или количество выведеных символов, а main() при успехе должен возвращать 0. поэтому для полной корректности надо делать return (printf("hello world\n") == 12 ? EXIT_SUCCESS : EXIT_FAILURE). не забывая о том, что волшебное число 12 следует держать в синхронизации с количеством символов, которые должны быть напечатаны.

да-да, EXIT_FAILURE — это единственный переносимый способ вернуть правильный код "пиздец" из main().

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 00:12 (ссылка)
Ну, такой ебанизм, наверное, только в языках без исключений.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 00:17 (ссылка)
тем не менее, оно есть. и, как оказывается, приветмир — программа вовсе не такая тривиальная. поэтому никогда не надо приводить её в качестве примера «простейшей программы», гыг.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 01:18 (ссылка)
Ну, можно на ассемблере ещё написать её. Тогда ебаться ещё больше надо будет, и что? Я не получаю удовольствия от низкоуровневой ебли.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 01:29 (ссылка)
а тебя никто не спрашивает, низкий уровень всё равно вылезет, хочешь ты того или нет. вот закончится у тебя память — и всё, твоя чудесная программа трапнется, проебав результаты многодневных вычислений, например.

ну да, «я могу повесить обработчик трапа и сохранить промежуточные результаты». или «я могу добыть их из кородампа, который… блядь, я забыл включить». но это уже низкий уровень, презренные материи, до которых чистой математике дела быть не должно.

я, собственно, к тому, что привычка забивать на такие штуки однажды вылезет боком. а если ты думаешь о таком на уровне рефлексов, то, например, ставишь assert()'ы после вызова read(), хотя документация и обещает, что read() отработает нормально.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 04:07 (ссылка)
Ну и хуй с ним. Вылезет - починим. И сколько б ты ни тужился, пытаясь написать bulletproof код с первого захода, всё равно уйдут годы, чтобы он стал зрелым.

Это и в жизни проявляется. Некоторые накупят страховок, например, на скалолазание не ходят или ещё чего. Жизнь в страхе, не жизнь даже, а так, существование. Годы унылой жизни, а потом всё равно в могилу.

И обратно к коду. Нахуй никому не нужен код этот пуленепробиваемый. Нужен результат, а что спутник один из ста из-за бага падает, ну и ладно.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 10:40 (ссылка)
ну, я тут где-то писал про настоящих сварщиков. у настоящих код, который забивает на ошибки, результатом считать не принято. профдеформация. забавно сказывается даже на throwaway utilities, где совершенно автоматически пишешь проверки даже на облажавшийся malloc(), хотя точно знаешь, что утилита одноразовая, и что больше пары килобайт она не выделяет.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 15:24 (ссылка)
Если ты понимаешь, что это психическое отклонение, то ты можешь попытаться его подлечить.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 15:28 (ссылка)
зачем? чтобы стать сварщиком похуже? написания этих проверок автоматические, они не отнимают ресурсов и не требуют почти никакого дополнительного времени. вот ещё, ломать с трудом наработаные рефлексы.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 15:37 (ссылка)
- Вы страдаете от мании величия?
- Что вы, доктор, я ею наслаждаюсь!

(Ответить) (Уровень выше)


[info]ketmar
2014-06-14 16:07 (ссылка)
за вот такое надо бить канделябром до просветления. mmap(), bitches, do you know mmap()?!

(Ответить) (Ветвь дискуссии)


[info]phantom
2014-06-14 22:50 (ссылка)
Mmap не загрузит файл в память. Обращения к как-бы-памяти будут, по сути, обращениями к диску (пока оно не закешируется). А мне надо именно в памяти массив.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-14 22:55 (ссылка)
загрузит ровно то, к чему ты обращался. и да, как раз «закэширует» это, так что при повторном обращении в районе тех же мест будет брать уже из памяти. зачем это делать руками, если ОС отлично справляется с такой задачей сама — мне не ясно.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-14 23:02 (ссылка)
Ну, вот мне хочется за один раз загрузить файл в памят - с гарантией. А не думать, тормозит ли у меня программа из-за кеширования, и вообще, закешировалось оно или ещё нет. Кроме того, для Схемы файл мэппинга нету, по-моему.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-14 23:18 (ссылка)
>Ну, вот мне хочется за один раз загрузить файл в памят - с гарантией.
так этого у тебя всё равно не получится, для кое-какой гарантии придётся писать цикл чтения. с таким же успехом ты можешь mmap()'нуть файл и потом просто пройтись по региону, трогая по байту в страничке.

а лучше этого вовсе не делать, потому что «тормоза» в любом случае будут одинаковые. точнее, при «неделании» потенциально меньше, потому что некоторые страницы ты можешь и не тронуть. если же вдруг какая ошибка вылезет — тебе пришлют SIGBUS, который можно поймать и обработать.

>ля Схемы файл мэппинга нету, по-моему
отличный повод сделать.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 00:20 (ссылка)
Оно должно было получиться. Я полагался на (file->bytes), кто ж знал что оно с багами в стандартной либе. Ну, теперь написал свой (file->bytes).

Работать я буду со всем файлом. Почему же одинаковые тормоза, если я читаю последовательно и сразу, а в mmap там получится фрагментированное (в памяти) кеширование и не сразу?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 00:32 (ссылка)
>Оно должно было получиться
хм. а что говорит об этом документация? а что она говорит о том, что получится, если в процессе чтения придёт сигнал? если ничего, то и либа, и документация — говно.

>Почему же одинаковые тормоза, если я читаю последовательно и сразу, а в mmap там
>получится фрагментированное (в памяти) кеширование и не сразу?

потому что:
а) на диске файл всё равно лежит фрагментами в большинстве случаев;
б) я уверен, что никаких хинтов ОС при открытии файла ты не давал, и ОС не в курсе, что ты собираешься его просто последовательно прочитать; при таких раскладах mmap() лучше, потому что таки сделает readahead (ну, так сделано, хоть это и не важно, потому что…)
в) …потому что при использовании mmap() ты избавляешься от лишнего буфера, которым является дисковый кэш ОС. надеюсь, не будем спорить о том, что чем меньше промежуточных буферов — тем лучше?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 01:45 (ссылка)
Документация не говорит ничего, но подразумевается, что будет эксепшен. И вообще, это ж не юниксовая библиотека, а кросс-платформенная. Поэтому такие специфичные вопросы и не нужно рассматривать.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 01:55 (ссылка)
такие специфичные вопросы всегда надо рассматривать, особенно в кроссплатформенных библиотеках. потому что если автор пишет под одну платформу, то я склонен считать, что он её более-менее знает. а вот если под несколько — то он запросто может забыть специфику одной из них. тем более, если некоторые специфические ситуации возникают настолько редко, что их за кучу лет можно ни разу не увидеть.

вот в таком случае я буду намного более спокоен, если автор сделает мне одолжение и покажет, что он не забыл о маловероятном событии, которое может произойти на одной из платформ. ибо преобразование сигнала в исключение — операция и сама по себе очень нетривиальная, мало кто может сделать это правильно (хотя тут больше виновата сама концепция сигналов, конечно; bwah, я сам делаю это неправильно почти везде). а если это вообще обработчик сигнала, который исключений не кидает, то всё становится ещё веселей.

так вот: человек, который привык к платформе, где сигналов нет (или просто обычно пишет софт, где сигналы не используются), имеет все шансы эпически облажаться при реализации библиотечной функции. и потому пусть он не ленится, а опишет поведение функции для специфической платформы, где такое таки встречается. и ему спокойней, и пользователям.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 03:55 (ссылка)
Ну, да, вполне.

(Ответить) (Уровень выше)


[info]phantom
2014-06-15 00:26 (ссылка)
В ФП вообще не нужны низкоуровневые интерфейсы к памяти и массиво-подобные объекты.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 00:27 (ссылка)
да, я знаю, линейный поиск рулит, массивы зло. когда у нас будет бесконечно быстрая техника с бесконечной памятью — я первый начну расстреливать тех, кто отходит от принципов ФП.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 01:21 (ссылка)
Мы, похоже, в разных видах спорта выступаем. И один другого не может или не хочет понять. Это и удивительно.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 01:32 (ссылка)
ну да, разница теоретически-научного (математического?) и инженерного подходов. первый делает так, как должно работать на идеальной сфере в вакууме, а второй, злобно матерясь, делает так, чтобы работало на ёбаном бетонном блоке, наполовину погружённом в землю.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 01:39 (ссылка)
Дело в том, что мой-то подход прагматичней некуда. Когда я решу все свои реальные задачи, си-программер только начнёт отрабатывать ошибки, хехе. Получается, я сделаю на несколько порядков больше за то же время.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 01:47 (ссылка)
ну так ты и не настоящий сварщик. я-то вёл речь (хоть это — mea culpa — и неочевидно) о том, что для настоящего сварщика подобный подход создаст проблемы в будущем. потому что он привыкнет забивать на технику безопасности, и однажды его ЕБАНЁТ так, что мало не покажется.

а если нужно периодически по-быстрому приварить хреновину к загогулине, и пофигу, что она через месяц отвалится — то, конечно, без разницы. лишь бы на неё можно было встать и достать с полки коньяк.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 18:29 (ссылка)
К слову, кто такой "сварщик"? Я не первый год в этом бизнесе, как говорят американцы. Но не слышал про сварщиков.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 18:34 (ссылка)
да я же на анекдот про мальчика, который маску сварщика нашёл, намекал.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 18:44 (ссылка)
Нашёл я анекдот, но что-то я его не догоняю.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 18:46 (ссылка)
да не напрягайся ты, нет тут никакого подтекста. просто писать «программист» скучно, а «сварщик» рождает забавные ассоциации. вот и всё.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 19:30 (ссылка)
Там, вообще-то его чуть не выебали, сварщика этого. :)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ketmar
2014-06-15 19:35 (ссылка)
именно поэтому в данном случае «сварщик» — хорошая тонкая шутка. потому что я охуенно тонкий шутник, да.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]phantom
2014-06-15 19:38 (ссылка)
:)

(Ответить) (Уровень выше)


[info]ketmar
2014-06-15 01:32 (ссылка)
p.s. я, если что, ни разу не говорю, что один подход лучше другого.

(Ответить) (Уровень выше)