Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.218.70.93] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Язык не важно какой, важна суть, читаем большой файл (10-50МБ) а может и больше
пример для понятности на "проклятом" всеми чистом C, просьба холиваров на темы C++ лучше, не разводить, тут это не важно. char buf[1024*512]; while (fgets(buf, sizeof(buf), fp) != NULL) { buf[strlen(buf) - 1] = '\0'; // eat the newline fgets() stores printf("%s\n", buf); } Как подбирать оптимальный размер баффера? почему .5мега а не 2 или 10? Данные приходят по сети, обычным HTTP, В сети гуглил толком ничего по сути не нашел, какие варианты |
Сообщ.
#2
,
|
|
|
1. Размер должен быть кратен степени двойки, коли сейчас почти все машины считают в двоичной, да и аппаратная поддержка, скорее всего, этим пользуется.
2. Не надо размер в несколько мегабайт (не больше), т.к. старые машины могут не найти столько памяти, а делать желательно для бо́льшего количества применений. 3. Главное: размер должен быть таков, чтобы время на количество вызовов функций для чтения (с учётом времени на вызов каждой) было незначительно в сравнении с временем чтения данных. Так, для SSD, скажем, желательно делать вызовов поменьше, ибо они данные читают шибче. Впрочем, предел=идеал всё равну будет манить: только 1 вызов. В то же время, если вдруг делаете попытки чтения битых файлов, то запросто может оказаться, что лучше наделать кучу микровызовов (чтобы хоть что-то прочитать), нежели всего один, кой скажет, что неудача,... и адью. |
Сообщ.
#3
,
|
|
|
На самом деле даже для относительно медленных жёстких дисков нет смысла слишком увеличивать размер буфера. Ведь пока буфер заполняется, программа ждёт, и ничего не делает. По крайней мере нет смысла делать его больше, чем дорожка диска (128 кБ). На само деле нет смысла делать его длиннее основной части непрерывных сегментов файла. Из-за этого для обычной последовательной обработки в современных операционных системах для современных же жёстких дисков обычно обходятся буфером размером в 4-64 КБ (Для винды покороче, для линукса подлиннее, обычно 16). Операционная система обнаружив, что программа читает файл последовательно с самого начала, сама считывает файл в кэш диска, и выдаёт порциями. При произвольном доступе имеет смысл делать буфер короче.
Увеличение размера буфера имеет смысл при копировании файлов в пределах одного физического носителя (с механическим доступом). Но, для того, чтобы получить существенный выигрыш, недостаточно задавать буфер в вызовах функций fread/fwrite. Надо задать размер внутреннего буфера файла, используемого низкоуровневыми read/write. |
Сообщ.
#4
,
|
|
|
Славян и amk, вы вроде челы продвинутые, на такие косяки порете!
1) Славян, возьми "среднестатистический" винт 10-й давности, там аппаратный кэш уже порядка 32 Mb! А это значит - "впилил и забыл", остальное дело микросхем. Вывод - "пилить" меньше, только электричество портить! 2) Amk, твое "ведь пока буфер заполняется, программа ждёт, и ничего не делает. По крайней мере нет смысла делать его больше, чем дорожка диска (128 кБ)." - шедевр безалаберности! Ты уж извини ... Про асинхронность помним, не? Отдали винту "порцию", не ждем ответа - работаем дальше. Давай вместе почитаем? Не поймите, плс, меня превратно - я не спец в этом вопросе, и код не "выплюну" на раз-два. Но, концептуально, я - в теме. И чуйка подсказывает, что вы неправы. Очень глубоко, в своих глубинах |
Сообщ.
#5
,
|
|
|
Цитата amk @ Но, для того, чтобы получить существенный выигрыш, недостаточно задавать буфер в вызовах функций fread/fwrite. Надо задать размер внутреннего буфера файла, используемого низкоуровневыми read/write. А как знать какой размер внутреннего буфера файла? У меня java, выглядит это InputStream inputStream = request.getInputStream(); bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); и потом char[] charBuffer = new char[8*1024] while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { } Я его (файл ) парсю в HTTP handler, еще я знаю что это csv. Пока писать на C не могу(слишком много народу, фирма 1500человек, убеждать надо). дать 16 для Лины и 8 для окон, будет нормально? |
Сообщ.
#6
,
|
|
|
sergioK, рекомендую тебе подход - системный!
В ближнем приближении - твоя "система" тупо состоит из двух блоков "ввод" и "вывод". Количество там и там - роли не играет. Важен трансфер на входе и выходе. Берем "вход", ты писал HTTP. Там существенным критерием есть MTU. Но он крошечный - единственный разумный, имхо, момент - делать буффер кратный ему. На счет блоков вывода - я бы смотрел в сторону аппаратных возможностей записи. Уже писал выше - как минимум размера аппаратного кэша. Но есть и третий момент, который забывают очень часто!!! А именно - свободная память для ОС! Если об этом не заботиться - ОС переходит в жесткий режим свопа - а это, в плане производительности, считай - "обнять и плакать"! Таким образом, любые манипуляции с памятью не должны урезать разумные границы работы ОС. Это самое главное!!! Оно - самое самое, и оно - самое главное! Остальное - лайт тюнинг. Таковое мое ИМХО. |
Сообщ.
#7
,
|
|
|
Цитата JoeUser @ Я комментировал пост с вызовом fgets. Там никакой асинхронности в принципе быть не может. Так что вызываем функцию… и ждём.Про асинхронность помним, не? Отдали винту "порцию", не ждем ответа - работаем дальше. Впрочем для fgets выбор размера буфера определяется по-другому. Буфер должен быть больше, чем самая длинная строка в файле. Буфер записи для fputs/fwrite может быть любым. Вообще любым, всё равно данные из него просто переписываются в буфер управления файлом. Буфер записи для write тоже любой, лишь бы был кратен размеру блока системного файлового кэша. Система сама разберётся когда и что писать на диск. Буфер чтения для read тоже должен быть кратен блоку системного кэша. И, повторю, нет смысла делать его больше, чем непрерывная цепочка блоков в файле, никакого выигрыша по быстродействию не будет. С другой стороны нежелательно делать его меньше читаемой за один раз порции данных. Если обработка идёт медленно по сравнению с чтением, то буфер можно вообще сделать примерно равным одной порции. Цитата JoeUser @ Вижу, поскольку "выплёвывание" кода тут вообще дело десятое. Всё зависит от того, какая система и куда идёт запись (откуда идет чтение). С некоторыми устройствами выгоднее вообще работать по-байтно. Не поймите, плс, меня превратно - я не спец в этом вопросе, и код не "выплюну" на раз-два. |
Сообщ.
#8
,
|
|
|
Цитата JoeUser @ Уже писал выше - как минимум размера аппаратного кэша. Но есть и третий момент, который забывают очень часто!!! А именно - свободная память для ОС! несколько гига хватит ? Асинхронность тоже ничего не даст, пока данные необработаны делать нечего, ну поставишь waitSingleThread, все поймут что крутой пацан so what is next? Всем спасибо но это была теория, что делать практически ? Ну я дам возможность размер буфера брать из конфига, и ловить оптимальный вариант методом try && mistakes ? Что конкретно в коде писать ?. |
Сообщ.
#9
,
|
|
|
Цитата amk @ Буфер записи для fputs/fwrite может быть любым. Вообще любым, всё равно данные из него просто переписываются в буфер управления файлом. Буфер записи для write тоже любой, лишь бы был кратен размеру блока системного файлового кэша. Система сама разберётся когда и что писать на диск. Буфер чтения для read тоже должен быть кратен блоку системного кэша. И, повторю, нет смысла делать его больше, чем непрерывная цепочка блоков в файле, никакого выигрыша по быстродействию не будет. я вот опять недавно разбирал старую программу для Виндус , и легко поднял производительность её отрезка с файловыми операциями на порядок (в 10 раз). Там чтение файла 200-300К происходило по-байтно. А если читать блоками 16К-32К (актуальное значение буфера - размер кластера, 4К) производительность выросла в 10 раз. --- Как то раз я написал тест, для исследования зависимости скорости от размеров буфера с блочной операцией fread/fwrite. Основной выигрыш был, когда буфер достигал 4К. Дальше бонус растёт очень медленно, в том случае, если речь идёт о файлах огромных размеров. Просто за счёт уменьшения количества циклов и обращений к fread/fwrite. Добавлено Цитата sergioK @ Всем спасибо но это была теория, что делать практически ? Проведи исследование. Возьми какой-нибудь огромный файл. И измеряй время его чтения, в зависимости от величины буфера. |
Сообщ.
#10
,
|
|
|
Цитата JoeUser @ 2) Amk, твое "ведь пока буфер заполняется, программа ждёт, и ничего не делает. По крайней мере нет смысла делать его больше, чем дорожка диска (128 кБ)." - шедевр безалаберности! Ты уж извини ... Про асинхронность помним, не? Отдали винту "порцию", не ждем ответа - работаем дальше. Давай вместе почитаем? Вообще-то он прав - не нужно делать больше, чем размер кластера. Да и асинхронность тут никаким боком - она не уменьшит время, проходящее с момента запуска начала чтения до его конца. |
Сообщ.
#11
,
|
|
|
Цитата OpenGL @ Вообще-то он прав - не нужно делать больше, чем размер кластера. Да и асинхронность тут никаким боком - она не уменьшит время, проходящее с момента запуска начала чтения до его конца. Она уменьшит количество операций с контроллером винта. А это существенно. |
Сообщ.
#12
,
|
|
|
Цитата JoeUser @ Она уменьшит количество операций с контроллером винта. Дай пруф на существенность что ли. |
Сообщ.
#13
,
|
|
|
Цитата OpenGL @ Дай пруф на существенность что ли. Ну выше же писали уже, мол блочное чтение/запись увеличивает на порядок скорость, нежели посимвольное чтение. Если доверия нет - напиши короткий тест. Я давно это проверял, и помню хорошо. Еще писамши на Virtual Pascal'е. Тут сравнивается заведомо худший вариант с "каким-то", путь удовлетворительным. И разница видна. А вот дальше нужно определиться с понятием "существенно". Это от задачи к задаче, ИМХО. В два раза - это существенно? А на 5% быстрее, существенно? По-моему так: коль ТС заговорил о быстродействии - значит любой лучший результат существенен. Ну как-то так. |
Сообщ.
#14
,
|
|
|
Цитата JoeUser @ Ну выше же писали уже, мол блочное чтение/запись увеличивает на порядок скорость, нежели посимвольное чтение. Давай ты не будешь додумывать то, что я не говорил. О том, что посимвольное чтение медленней буферизованного никто не спорит. Речь о том, что нет смысла делать буфер большой - 64 кб, например, за глаза и уши, а лучше и того меньше. Увеличение его размера не только не приведёт к ускорению, но даже замедлить чтение может. Добавлено Цитата JoeUser @ По-моему так: коль ТС заговорил о быстродействии - значит любой лучший результат существенен. Если жалкие проценты в быстродействии важны, то проще всего сделать размер буфера конфигурируемым, и на конкретной системе уже и выбирать наиболее подходящий размер. |
Сообщ.
#15
,
|
|
|
Цитата OpenGL @ Речь о том, что нет смысла делать буфер большой - 64 кб, например, за глаза и уши, а лучше и того меньше. Возникает резонный вопрос - зачем тогда HDD обеспечивают аппаратным кэшем в 64/32/16/8 MB? |