На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> FileBufferReader , оптимальный размер баффера
    Язык не важно какой, важна суть, читаем большой файл (10-50МБ) а может и больше
    пример для понятности на "проклятом" всеми чистом C,
    просьба холиваров на темы C++ лучше, не разводить, ;) тут это не важно.

    ExpandedWrap disabled
        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, В сети гуглил толком ничего по сути
    не нашел, какие варианты ;)
      1. Размер должен быть кратен степени двойки, коли сейчас почти все машины считают в двоичной, да и аппаратная поддержка, скорее всего, этим пользуется.
      2. Не надо размер в несколько мегабайт (не больше), т.к. старые машины могут не найти столько памяти, а делать желательно для бо́льшего количества применений.
      3. Главное: размер должен быть таков, чтобы время на количество вызовов функций для чтения (с учётом времени на вызов каждой) было незначительно в сравнении с временем чтения данных. Так, для SSD, скажем, желательно делать вызовов поменьше, ибо они данные читают шибче. Впрочем, предел=идеал всё равну будет манить: только 1 вызов. В то же время, если вдруг делаете попытки чтения битых файлов, то запросто может оказаться, что лучше наделать кучу микровызовов (чтобы хоть что-то прочитать), нежели всего один, кой скажет, что неудача,... и адью. :whistle:
        На самом деле даже для относительно медленных жёстких дисков нет смысла слишком увеличивать размер буфера. Ведь пока буфер заполняется, программа ждёт, и ничего не делает. По крайней мере нет смысла делать его больше, чем дорожка диска (128 кБ). На само деле нет смысла делать его длиннее основной части непрерывных сегментов файла. Из-за этого для обычной последовательной обработки в современных операционных системах для современных же жёстких дисков обычно обходятся буфером размером в 4-64 КБ (Для винды покороче, для линукса подлиннее, обычно 16). Операционная система обнаружив, что программа читает файл последовательно с самого начала, сама считывает файл в кэш диска, и выдаёт порциями. При произвольном доступе имеет смысл делать буфер короче.
        Увеличение размера буфера имеет смысл при копировании файлов в пределах одного физического носителя (с механическим доступом).
        Но, для того, чтобы получить существенный выигрыш, недостаточно задавать буфер в вызовах функций fread/fwrite. Надо задать размер внутреннего буфера файла, используемого низкоуровневыми read/write.
          Славян и amk, вы вроде челы продвинутые, на такие косяки порете! :lol:

          1) Славян, возьми "среднестатистический" винт 10-й давности, там аппаратный кэш уже порядка 32 Mb! А это значит - "впилил и забыл", остальное дело микросхем. Вывод - "пилить" меньше, только электричество портить!

          2) Amk, твое "ведь пока буфер заполняется, программа ждёт, и ничего не делает. По крайней мере нет смысла делать его больше, чем дорожка диска (128 кБ)." - шедевр безалаберности! Ты уж извини ... Про асинхронность помним, не? Отдали винту "порцию", не ждем ответа - работаем дальше. Давай вместе почитаем?

          Не поймите, плс, меня превратно - я не спец в этом вопросе, и код не "выплюну" на раз-два. Но, концептуально, я - в теме. И чуйка подсказывает, что вы неправы. Очень глубоко, в своих глубинах :lol:
            Цитата amk @
            Но, для того, чтобы получить существенный выигрыш, недостаточно задавать буфер в вызовах функций fread/fwrite. Надо задать размер внутреннего буфера файла, используемого низкоуровневыми read/write.

            А как знать какой размер внутреннего буфера файла?
            У меня java, выглядит это
            ExpandedWrap disabled
               InputStream inputStream = request.getInputStream();
                            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));


            и потом
            ExpandedWrap disabled
                      char[] charBuffer = new char[8*1024]
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
              }

            Я его (файл ) парсю в HTTP handler, еще я знаю что это csv.
            Пока писать на C не могу(слишком много народу, фирма 1500человек, убеждать надо).
            дать 16 для Лины и 8 для окон, будет нормально?
              sergioK, рекомендую тебе подход - системный!

              В ближнем приближении - твоя "система" тупо состоит из двух блоков "ввод" и "вывод". Количество там и там - роли не играет. Важен трансфер на входе и выходе. Берем "вход", ты писал HTTP. Там существенным критерием есть MTU. Но он крошечный - единственный разумный, имхо, момент - делать буффер кратный ему. На счет блоков вывода - я бы смотрел в сторону аппаратных возможностей записи. Уже писал выше - как минимум размера аппаратного кэша. Но есть и третий момент, который забывают очень часто!!! А именно - свободная память для ОС! Если об этом не заботиться - ОС переходит в жесткий режим свопа - а это, в плане производительности, считай - "обнять и плакать"! Таким образом, любые манипуляции с памятью не должны урезать разумные границы работы ОС. Это самое главное!!! Оно - самое самое, и оно - самое главное! Остальное - лайт тюнинг. Таковое мое ИМХО.
                Цитата JoeUser @
                Про асинхронность помним, не? Отдали винту "порцию", не ждем ответа - работаем дальше.
                Я комментировал пост с вызовом fgets. Там никакой асинхронности в принципе быть не может. Так что вызываем функцию… и ждём.
                Впрочем для fgets выбор размера буфера определяется по-другому. Буфер должен быть больше, чем самая длинная строка в файле.
                Буфер записи для fputs/fwrite может быть любым. Вообще любым, всё равно данные из него просто переписываются в буфер управления файлом.
                Буфер записи для write тоже любой, лишь бы был кратен размеру блока системного файлового кэша. Система сама разберётся когда и что писать на диск.
                Буфер чтения для read тоже должен быть кратен блоку системного кэша. И, повторю, нет смысла делать его больше, чем непрерывная цепочка блоков в файле, никакого выигрыша по быстродействию не будет. С другой стороны нежелательно делать его меньше читаемой за один раз порции данных. Если обработка идёт медленно по сравнению с чтением, то буфер можно вообще сделать примерно равным одной порции.

                Цитата JoeUser @
                Не поймите, плс, меня превратно - я не спец в этом вопросе, и код не "выплюну" на раз-два.
                Вижу, поскольку "выплёвывание" кода тут вообще дело десятое. Всё зависит от того, какая система и куда идёт запись (откуда идет чтение). С некоторыми устройствами выгоднее вообще работать по-байтно.
                  Цитата JoeUser @
                  Уже писал выше - как минимум размера аппаратного кэша. Но есть и третий момент, который забывают очень часто!!! А именно - свободная память для ОС!

                  несколько гига хватит ? Асинхронность тоже ничего не даст, пока данные необработаны
                  делать нечего, ну поставишь waitSingleThread, все поймут что крутой пацан ;) so what is next?


                  Всем спасибо но это была теория, что делать практически ? Ну я дам возможность
                  размер буфера брать из конфига, и ловить оптимальный вариант методом try && mistakes ?
                  Что конкретно в коде писать ?.
                  Сообщение отредактировано: sergioK -
                    Цитата amk @
                    Буфер записи для fputs/fwrite может быть любым. Вообще любым, всё равно данные из него просто переписываются в буфер управления файлом.
                    Буфер записи для write тоже любой, лишь бы был кратен размеру блока системного файлового кэша. Система сама разберётся когда и что писать на диск.
                    Буфер чтения для read тоже должен быть кратен блоку системного кэша. И, повторю, нет смысла делать его больше, чем непрерывная цепочка блоков в файле, никакого выигрыша по быстродействию не будет.

                    я вот опять недавно разбирал старую программу для Виндус , и легко поднял
                    производительность её отрезка с файловыми операциями на порядок (в 10 раз).
                    Там чтение файла 200-300К происходило по-байтно.
                    А если читать блоками 16К-32К (актуальное значение буфера - размер кластера, 4К)
                    производительность выросла в 10 раз.
                    ---
                    Как то раз я написал тест, для исследования зависимости скорости от размеров буфера
                    с блочной операцией fread/fwrite. Основной выигрыш был, когда буфер достигал 4К.
                    Дальше бонус растёт очень медленно, в том случае, если речь идёт о файлах огромных размеров.
                    Просто за счёт уменьшения количества циклов и обращений к fread/fwrite.

                    Добавлено
                    Цитата sergioK @
                    Всем спасибо но это была теория, что делать практически ?

                    Проведи исследование.
                    Возьми какой-нибудь огромный файл.
                    И измеряй время его чтения, в зависимости от величины буфера.
                      Цитата JoeUser @
                      2) Amk, твое "ведь пока буфер заполняется, программа ждёт, и ничего не делает. По крайней мере нет смысла делать его больше, чем дорожка диска (128 кБ)." - шедевр безалаберности! Ты уж извини ... Про асинхронность помним, не? Отдали винту "порцию", не ждем ответа - работаем дальше. Давай вместе почитаем?

                      Вообще-то он прав - не нужно делать больше, чем размер кластера. Да и асинхронность тут никаким боком - она не уменьшит время, проходящее с момента запуска начала чтения до его конца.
                        Цитата OpenGL @
                        Вообще-то он прав - не нужно делать больше, чем размер кластера. Да и асинхронность тут никаким боком - она не уменьшит время, проходящее с момента запуска начала чтения до его конца.

                        Она уменьшит количество операций с контроллером винта. А это существенно.
                          Цитата JoeUser @
                          Она уменьшит количество операций с контроллером винта.

                          Дай пруф на существенность что ли.
                            Цитата OpenGL @
                            Дай пруф на существенность что ли.

                            Ну выше же писали уже, мол блочное чтение/запись увеличивает на порядок скорость, нежели посимвольное чтение. Если доверия нет - напиши короткий тест. Я давно это проверял, и помню хорошо. Еще писамши на Virtual Pascal'е. Тут сравнивается заведомо худший вариант с "каким-то", путь удовлетворительным. И разница видна.

                            А вот дальше нужно определиться с понятием "существенно". Это от задачи к задаче, ИМХО. В два раза - это существенно? А на 5% быстрее, существенно?

                            По-моему так: коль ТС заговорил о быстродействии - значит любой лучший результат существенен. Ну как-то так.
                              Цитата JoeUser @
                              Ну выше же писали уже, мол блочное чтение/запись увеличивает на порядок скорость, нежели посимвольное чтение.

                              Давай ты не будешь додумывать то, что я не говорил. О том, что посимвольное чтение медленней буферизованного никто не спорит. Речь о том, что нет смысла делать буфер большой - 64 кб, например, за глаза и уши, а лучше и того меньше. Увеличение его размера не только не приведёт к ускорению, но даже замедлить чтение может.

                              Добавлено
                              Цитата JoeUser @
                              По-моему так: коль ТС заговорил о быстродействии - значит любой лучший результат существенен.

                              Если жалкие проценты в быстродействии важны, то проще всего сделать размер буфера конфигурируемым, и на конкретной системе уже и выбирать наиболее подходящий размер.
                                Цитата OpenGL @
                                Речь о том, что нет смысла делать буфер большой - 64 кб, например, за глаза и уши, а лучше и того меньше.

                                Возникает резонный вопрос - зачем тогда HDD обеспечивают аппаратным кэшем в 64/32/16/8 MB? :lol:
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0425 ]   [ 17 queries used ]   [ Generated: 16.04.24, 14:42 GMT ]