На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> FileBufferReader , оптимальный размер баффера
    Цитата JoeUser @
    зачем тогда HDD обеспечивают аппаратным кэшем в 64/32/16/8 MB?
    Во-первых, при записи можно не ждать, когда установятся головки и под них подойдёт нужный блок, а записать данные в кэш и отчитаться, что операция выполнена. Реальную же запись выполнить, когда будет время.
    Во-вторых, если после этого сразу начнётся чтение, можно придержать данные в кэше, прочитать нужные данные, а потом уже выбирать время для записи.
    Можно накопить данные, и потом записать их в порядке, минимизирующем дёргание головок.
    Специально для тех, кто не понимает разницу между высокоуровневым чтением из программного буфера и низкоуровневым с диска (встречал и такое), и пытающимся читать данные с диска по одному байту, можно не гонять головку к нужному блоку, а выдавать его прямо из памяти, уменьшив замедление работы с 1000 раз и более всего до 10.
    Поскольку файлы хранятся на диске по-кластерно, а некоторые даже иногда подвергают диск дефрагментации, можно прочитать дорожку до конца в кэш, и заняться другими делами, по запросам выдавая уже прочитанные блоки.
    Ну и последнее, многие не знают, но на современных дисках размер блока уже довольно давно не равен 512 байт (у меня в компе размер блока равен 4096 - 8 логических блоков, определяется при сбоях). Более того, реальные кластеры часто пересекают границы физических блоков на диске, и даже переходят с дорожки на дорожку. Чтобы сделать вид, что блок по-прежнему равен 512 байт. Приходится при чтении разбивать физические блоки на логические в кэше, а при записи собирать их обратно.
      OpenGL, т.е. если диск может принять в свой кэш 64MБ, то все равно нужно забивать его мелкими порциями по 64КБ - и это будет по фэншую? А вот если установим свой программный кэш, к примеру в 16МБ, то получим (можем получить) просадку по скорости? :blink:
        Цитата OpenGL @
        Если жалкие проценты в быстродействии важны, то проще всего сделать размер буфера конфигурируемым, и на конкретной системе уже и выбирать наиболее подходящий размер.

        Жалкие проценты никого не волнуют, но размер буфера конфигурируемым я сделал,
        Дальше задача саппорта, буду делать stress test с файлами 20-25Мега на неделе,
        выложу, благодарю за хинты, Я пока stand by.
          JoeUser
          Цитата JoeUser @
          то все равно нужно забивать его мелкими порциями по 64КБ - и это будет по фэншую?

          Когда я ставил эксперименты то оптимальным на чтение было 256КБ на запись 8МБ.

          Цитата JoeUser @
          А вот если установим свой программный кэш, к примеру в 16МБ, то получим (можем получить) просадку по скорости?

          Да проседает на проценты.
          Сообщение отредактировано: Pavia -
            Цитата JoeUser @
            Цитата OpenGL @
            Речь о том, что нет смысла делать буфер большой - 64 кб, например, за глаза и уши, а лучше и того меньше.

            Возникает резонный вопрос - зачем тогда HDD обеспечивают аппаратным кэшем в 64/32/16/8 MB? :lol:

            А было время, когда этого не было.
            В этом случае, ЦП должен был сам, программно, управлять
            диском в реальном времени. Что не очень удобно, а в ситемах
            типа Виндус крайне не выгодно.
            (А я такие опыты производил в ситеме CPM/80. Писал процедуру
            форматирования дискеток)
            Поэтому в дивайсы стали устанавливать весьма интеллектуальные
            контроллеры, а связь с внешним миром организовали через
            общую память. Для того, чтобы максимальным образом
            разгрузить центральный процессор.
            -----
            Похожая эволюция затрагивает практически любые дивайсы.
            Например, сетевые карты. Видео-карты.
            Сообщение отредактировано: ЫукпШ -
              Цитата JoeUser @
              OpenGL, т.е. если диск может принять в свой кэш 64MБ, то все равно нужно забивать его мелкими порциями по 64КБ - и это будет по фэншую? А вот если установим свой программный кэш, к примеру в 16МБ, то получим (можем получить) просадку по скорости?

              Я когда-то экспериментировал, то получал, что начиная с некоторого совсем небольшого размера размер буфера перестаёт ускорять чтение-запись.
                Странно это все, очень странно! :-?

                Написал прогу на Си для тестирования различных вариантов буферизированной записи. Тестирование проводил на "живой ОС Win 10x64", т.е. не на виртуальной машине. Сама система крутится на материнском RAID-0 (fake RAID). Запись проводил на дополнительно подключенный HDD c SATA 6Gb/s на интерфейс компа SATA III, и потом другой HDD по USB 3.0. Комп на базе Intel Core i7-3770K, 3.5GHz, 8GB RAM. Для более реальных, как мне показалось, условий - писал в два конкурирующих за I/O (вернее за запись) потока.

                Вот код:

                ExpandedWrap disabled
                  #include <stdio.h>
                  #include <stdlib.h>
                  #include <time.h>
                  #include <pthread.h>
                  #include <unistd.h>
                   
                  #define BUFF_LEN_ONE 256*1024
                  #define BUFF_LEN_TWO 1*1024*1024
                   
                  void* Write256KB(void* buff) {
                    FILE *fd;
                    struct timespec start, stop;
                    clock_gettime (CLOCK_REALTIME, &start);
                    if ((fd = fopen("F:/one.bin", "wb")) == NULL) {
                      perror("Cannot open file one.bin");
                      return NULL;
                    };
                    setvbuf(fd, (char *)buff, _IOFBF, BUFF_LEN_ONE);
                    for (long int i=0; i<128*1024*1024; ++i) fputs("0123456789ABCDEF",fd);
                    fflush(fd); /** в принципе не надо **/
                    fclose(fd);
                    clock_gettime (CLOCK_REALTIME, &stop);
                    printf ("Delta One: %lu.%lu sec\n",stop.tv_sec - start.tv_sec,stop.tv_nsec - start.tv_nsec);
                    return NULL;
                  }
                   
                  void* Write32MB(void* buff) {
                    FILE *fd;
                    struct timespec start, stop;
                    clock_gettime (CLOCK_REALTIME, &start);
                    if ((fd = fopen("F:/two.bin", "wb")) == NULL) {
                      perror("Cannot open file two.bin");
                      return NULL;
                    };
                    setvbuf(fd, (char *)buff, _IOFBF, BUFF_LEN_TWO);
                    for (long int i=0; i<128*1024*1024; ++i) fputs("0123456789ABCDEF",fd);
                    fflush(fd); /** в принципе не надо **/
                    fclose(fd);
                    clock_gettime (CLOCK_REALTIME, &stop);
                    printf ("Delta Two: %lu.%lu sec\n",stop.tv_sec - start.tv_sec,stop.tv_nsec - start.tv_nsec);
                    return NULL;
                  }
                   
                   
                  int main() {
                   
                    pthread_t one, two;
                    void *buff_one, *buff_two;
                   
                    buff_one = malloc(BUFF_LEN_ONE);
                    buff_two = malloc(BUFF_LEN_TWO);
                   
                    if (pthread_create(&one, NULL, Write256KB, buff_one) != 0) perror("Pthread_create-1 fails");
                    if (pthread_create(&two, NULL, Write32MB, buff_two) != 0) perror("Pthread_create-2 fails");
                    if (pthread_join(one,NULL) != 0) perror("Pthread_join-1 fails");
                    if (pthread_join(two,NULL) != 0) perror("Pthread_join-2 fails");
                   
                    return 0;
                  }


                Может с кодом че не так? Но результаты получились странные.
                Свел их в таблицы для наглядности:

                Прикреплённая картинка
                Прикреплённая картинка
                Прикреплённая картинка
                Прикреплённая картинка


                Выводы:

                1) Для программы с более одним потоком - операционная система рулит как хочет
                2) Для потоков желательно не использовать буфера равных размеров - общее быстродействие программы ухудшается
                3) Самый последний тест с равными размерами буферов для USB 3.0 удивляет

                Критикуйте. Что не так написал или где неправильный вывод сделал.

                Добавлено
                ЗЫ: Каждый из тестов запускал по несколько прогонов, тупо чтобы убедиться, что цифры "не пляшут". Как писал выше, с последним тестом с равными буферами для HDD USB - устойчивая разница. Везде разброс между запусками - доли секунды.
                  JoeUser
                  1)У вас процессор отрабатывает за 10 секунд пересылку в буфер ОС. Win7 и далее используют всю свободную память под дисковый кэш.
                  А далее виндоус медленно записывает на диск.
                  Так что с тем что винда, как хочет так и рулит согласен.
                  2)
                  Цитата JoeUser @
                  общее быстродействие программы ухудшается

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

                  В чём смысл двух потоков? Почему не 4 или 5?

                  3) Чем удивляет?
                  Судя повсему в обоих таблицам скорость 1 и 2 перепутаны с 1 и 2 буфером.
                  Кстати у вас вывод printf("Delta One: не синхротронный и там буквы да и цифры должны плясать чёрти как.
                  Сообщение отредактировано: Pavia -
                    Цитата Pavia @
                    )У вас процессор отрабатывает за 10 секунд пересылку в буфер ОС. Win7 и далее используют всю свободную память под дисковый кэш. А далее виндоус медленно записывает на диск.

                    Нет. На на пару тестах, во время их работы, я открывал ProcessExplorer и смотрел загрузку проца нитями - была на протяжении всей записи, но от 1% до 5% максимум.
                    Цитата Pavia @
                    Вы табличку неправильно нарисовали. У вас же не скорость в ней, а время. Поэтому не ухудшается, а улучшается.
                    Во-вторых график надо строить не столбчатый, а трёх мерный с вариацией размеров буферов иначе тренд непонятен.

                    Да нет, все верно - пара столбцов под один вариант буфферов, следующая пара - под другой, и т.д. - лучший вариант меньший. Помимо того "серая" линия показывает "общее время программы" (иными словами максимально-бОльшее время работы одного из потоков). Аналогично - меньшее время = лучший результат.
                    Цитата Pavia @
                    Судя повсему в обоих таблицам скорость 1 и 2 перепутаны с 1 и 2 буфером.

                    Ничего не перепутано! Я времена снимал с "Delta ...:". Да, в некоторых случаях второй поток (второй, бОльший буфер) успевал отписываться первым, т.к. завершал раньше. Я все это учитывал.
                    Цитата Pavia @
                    В чём смысл двух потоков? Почему не 4 или 5?

                    Смысл в том, чтобы каждый из потоков работал не в "тепличных" условиях, а в условиях конкуренции. Два мне показалось для обеспечения конкуренции достаточным.
                    Цитата Pavia @
                    Кстати у вас вывод printf("Delta One: не синхротронный и там буквы да и цифры должны плясать чёрти как.

                    В моем тесте такого в 99.9% быть не может - т.к. разница между выводами на много больше скорости вывода на консоль, более того - саму еще буферезированную. Кстати - код я привел, можно у себя проверить. Я собирал с помощью gcc version 5.3.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project).
                      JoeUser
                      Цитата JoeUser @
                      Смысл в том, чтобы каждый из потоков работал не в "тепличных" условиях, а в условиях конкуренции. Два мне показалось для обеспечения конкуренции достаточным.

                      Жесткий запроектированы на временное разделение для 4 потоков. Поэтому 2-х недостаточно.
                      Во-вторых я не понимаю чего вы ожидаете увидеть?

                      Цитата JoeUser @
                      Нет. На на пару тестах, во время их работы, я открывал ProcessExplorer и смотрел загрузку проца нитями - была на протяжении всей записи, но от 1% до 5% максимум.

                      Дело в том, что ProcessExplorer считает данные блоки как Free. Просто запустите несколько процессов 32-битных или 64 битных которые съедят всю свободную память и данамика записи изменится у вас правда она не отображается. Но на скорость это тоже повлияет.


                      Цитата JoeUser @
                      Да нет, все верно

                      Так я не про то, что верно не верно. А про-то что вводит в заблуждение. Как на картинах intel vs amd.
                      Скрытый текст
                      user posted image
                        Цитата Pavia @
                        Дело в том, что ProcessExplorer считает данные блоки как Free.

                        Я раскрывал свойство запущенной программы, открывал вкладку Threads и смотрел сколько CPU в % отъедает каждая работающая нить.
                        Какие такие блоки???

                        Цитата Pavia @
                        А про-то что вводит в заблуждение.

                        Ну да, хотя давно уже пора запомнить, больше - не значит лучше :lol:

                        Цитата Pavia @
                        Жесткий запроектированы на временное разделение для 4 потоков. Поэтому 2-х недостаточно.

                        Кто и кем запроектирован для 4-х потоков и почему 2 недостаточно?

                        Цитата Pavia @
                        Во-вторых я не понимаю чего вы ожидаете увидеть?

                        Какой из потоков с соответствующим размером буфера умудриться свои данные записать быстрее. Потом подумалось об общем быстродействии - что также немаловажно.
                          Цитата JoeUser @
                          Цитата Pavia @
                          Жесткий запроектированы на временное разделение для 4 потоков. Поэтому 2-х недостаточно.

                          Кто и кем запроектирован для 4-х потоков и почему 2 недостаточно?

                          Потоков лучше всего столько, сколько ядер на машине.
                            Цитата sergioK @
                            Потоков лучше всего столько, сколько ядер на машине.

                            Это когда ядра есть чем занять по вычислениям.
                              Чуток подправил для одновременного запуска на разных объёмах буферов. За неимением POSIX-а переиначил потоки и время на плюсовые std:: аналоги. Тестил на SATAшных терабайтниках.
                              Регулар:
                              ExpandedWrap disabled
                                Using 262144 and 1048576 len buffers:   delta two: 22.642 sec | delta one: 24.108 sec
                                Using 262144 and 16777216 len buffers:  delta one: 13.658 sec | delta two: 23.652 sec
                                Using 262144 and 536870912 len buffers: delta one: 10.679 sec | delta two: 33.190 sec
                                Using 262144 and 524288 len buffers:    delta one: 23.556 sec | delta two: 24.215 sec
                                Using 262144 and 262144 len buffers:    delta one: 24.640 sec | delta two: 24.889 sec
                                Using 16777216 and 16777216 len buffers:delta one: 24.022 sec | delta two: 24.270 sec

                              Энкриптед:
                              ExpandedWrap disabled
                                Using 262144 and 1048576 len buffers:   delta two: 24.068 sec | delta one: 24.511 sec
                                Using 262144 and 16777216 len buffers:  delta one: 13.193 sec | delta two: 22.704 sec
                                Using 262144 and 536870912 len buffers: delta one: 10.568 sec | delta two: 32.802 sec
                                Using 262144 and 524288 len buffers:    delta one: 24.850 sec | delta two: 25.351 sec
                                Using 262144 and 262144 len buffers:    delta one: 23.470 sec | delta two: 23.867 sec
                                Using 16777216 and 16777216 len buffers:delta one: 23.279 sec | delta two: 23.809 sec

                              Сомпрессед:
                              ExpandedWrap disabled
                                Using 262144 and 1048576 len buffers:   delta two: 30.661 sec | delta one: 34.824 sec
                                Using 262144 and 16777216 len buffers:  delta two: 20.858 sec | delta one: 46.974 sec
                                Using 262144 and 536870912 len buffers: delta one: 40.822 sec | delta two: 53.165 sec
                                Using 262144 and 524288 len buffers:    delta one: 45.717 sec | delta two: 59.511 sec
                                Using 262144 and 262144 len buffers:    delta two: 58.195 sec | delta one: 63.441 sec
                                Using 16777216 and 16777216 len buffers:delta two: 30.491 sec | delta one: 31.853 sec
                              Понятно, что время на упакованных файликах будет очень разниться в зависимости от их контента.
                              Не понимаю, об чём сыр-бор. Понятно же, что результат будет зависеть от конкретики, и синтетические тесты ровным счётом ничего не покажут. Для полноты экспериментов нужно ещё пробовать флажочки из WinAPI.
                              Для фана регулар на 4Г флэшке (NTFS):
                              ExpandedWrap disabled
                                Using 262144 and 1048576 len buffers:   delta two: 95.395 sec | delta one: 152.316 sec
                                Using 262144 and 16777216 len buffers:  delta two: 118.955 sec| delta one: 182.474 sec
                                Using 262144 and 536870912 len buffers: delta two: 155.706 sec| delta one: 157.165 sec
                                Using 262144 and 524288 len buffers:    delta two: 378.902 sec| delta one: 415.027 sec
                                Using 262144 and 262144 len buffers:    delta one: 258.895 sec| delta two: 259.765 sec
                                Using 16777216 and 16777216 len buffers:delta two: 87.787 sec | delta one: 152.773 sec
                              Пришлось уменьшить размер файлов вдвое, иначе не вмещались. Флешка оптимизирована на производительность, так что запись кешировалась. Полный алес по времени. Видимо, понимая медленность устройства, винда пыталась кешировать, пока был резон хавать память под кеш, но потом-таки сдалась.
                                Qraizer, сенкс, что не поленился :) Интересно, цифры конечно разные, но соотношения цифр на разных вариантах буферов - вполне похожи как в моем эксперименте.

                                1) Первый эксперимент - кэш в 1 мег выигрывает у кэша в 256к
                                2) Второй эксперимент с кэшем в 256к и 16 мегами - дает максимальную общую производительность проги
                                3) Последний эксперимент - что творит венда с записью на USB с обоими кэшами по 16 мег, только ей известно

                                Цитата Qraizer @
                                Понятно же, что результат будет зависеть от конкретики, и синтетические тесты ровным счётом ничего не покажут.

                                Согласен. Безапелляционные утверждения о конкретном значении программного кэша (пресловутые 256к) - наводят туман! :)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0860 ]   [ 19 queries used ]   [ Generated: 29.03.24, 08:00 GMT ]