Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сколько байт читать (записывать) из файла за один раз?

12K
04 ноября 2006 года
MegaPixelnyi
9 / / 03.01.2006
Открываю файл на чтение/запись, но не знаю размер блока, который нужно считывать за 1 раз. Известно, что чтение маленькими блоками сильно замедляет программу, но не делать же их огромными. Возникает вопрос, какой самый оптимальный вариант и в каких случаях?
8.8K
04 ноября 2006 года
The_Ice
109 / / 04.04.2006
самый оптимальный - это тот, который нужен для решения твоей задачи - можешь, конечно читать весь файл за раз, а потом работать с буфером в оперативе - это в теории должно быть быстрее, но не факт, при этом, что файл не будет слишком большим чтобы не использовать свап, тогда наоборот - нужно читать этот файл порциями - ведь обращением к свапу ничуть не быстрее, чем обращение к обычному файлу, учитывая, что свап по сути то и есть обычный файл... ну и так далее :)
309
04 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
А в какой среде программа пишется? И какой формат файла?
Для загрузки текстовых файлов в Delphi и Builder'е можно использовать TStringList->LoadFile без всяких буферов и открытыя/закрытия файла.

А вообще, оптимальное соотношение чтения/хранения зависит от текущих условий работы алгоритма
261
04 ноября 2006 года
ahilles
1.5K / / 03.11.2005
наиболее оптимальный размер это 8192 байт = 8 КБ
3
04 ноября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=ahilles]наиболее оптимальный размер это 8192 байт = 8 КБ[/QUOTE]
Это почему?

- Петька, приборы?!
- 567!
- Петька, что "567"?!
- А что "приборы", Василий Иванович?
8.4K
04 ноября 2006 года
Dian
91 / / 18.02.2006
Оптимальный - равный размеру кластера диска или кратный ему. 8к обычно туда попадает. На самом деле пофиг - лишнее все равно закешируется системой.
12K
04 ноября 2006 года
MegaPixelnyi
9 / / 03.01.2006
[QUOTE=el scorpio]А в какой среде программа пишется? И какой формат файла?
А вообще, оптимальное соотношение чтения/хранения зависит от текущих условий работы алгоритма[/QUOTE]
В принципе для меня не так важно в какой среде. Приходилось писать и на VB, и на Delphi, и на Паскале. Файл открывался как текстовый. Размер файла измерялся мегабайтами. И здесь волновало только какой размер блока использовать. Теперь суть для мнея ясна.
5.4K
05 ноября 2006 года
Svyatozar
221 / / 11.09.2006
[QUOTE=MegaPixelnyi]В принципе для меня не так важно в какой среде. Приходилось писать и на VB, и на Delphi, и на Паскале. Файл открывался как текстовый. Размер файла измерялся мегабайтами. И здесь волновало только какой размер блока использовать. Теперь суть для мнея ясна.[/QUOTE]
Дык в зависимости от того что ты делаешь с этим файлом после загрузки. Если редактируешь фотографию, то возможно придется целиком загружать. Если перекодируешь кои8 в Утф8 то в зависимости от платформы после какого-то значения размер окна уже не влияет на производительность. Где-то я находил подобный бенчмарк, да его и самому сделать нетрудно...
284
09 ноября 2006 года
michael_is_98
587 / / 25.02.2005
Если посмотрите исходники класса TParser в Дельфи, то там читается блоками по 4 кб
12K
10 ноября 2006 года
MegaPixelnyi
9 / / 03.01.2006
[QUOTE=Svyatozar]Дык в зависимости от того что ты делаешь с этим файлом после загрузки.[/QUOTE]
Если мне файл надо скопировать, по сколько лучше читать? Или по сколько читать при перекодировании wav файла? Или лучше бенчмарк сделать и проверить всё на себе?
284
11 ноября 2006 года
michael_is_98
587 / / 25.02.2005
Ребята, по-моему не так важно по сколько байт читать. Важно создать компонент (класс) или просто обычную процедуру для буферизированного чтения данных, где используется значение переменной, которое определяет по сколько байт считавать данные.
Можно использовать 4 Кб (4096).
5.4K
11 ноября 2006 года
Svyatozar
221 / / 11.09.2006
Попробуй простой копировальщик. Меняй значение BUFSIZE
Код:
#include <stdio.h>

#define BUFSIZE (32)

int main(int argc, char **argv) {
    char buf[BUFSIZE];
    FILE *fi, *fo;
    int errorlevel = 1;
    size_t bytes_read;
    if(argc < 3) {
        printf("file copy. usage:\n%s infile outfile\n", argv[0]);
        goto done;
    }

    if(!(fi = fopen(argv[1], "r"))) {
        printf("cannot open input file: %s\n", argv[1]);
        goto done;
    }

    if(!(fo = fopen(argv[2], "w+"))) {
        printf("cannot open output file: %s\n", argv[2]);
        goto closefi;
    }

    for(; ; ) {
        bytes_read = fread(buf, 1, BUFSIZE, fi);
        fwrite(buf, 1, bytes_read, fo);
        if(bytes_read != BUFSIZE && feof(fi)) {
            break;
        }
    }
    fclose(fo);
closefi:
    fclose(fi);
    errorlevel = 0;
done:
    return errorlevel;
}
63
21 ноября 2006 года
Zorkus
2.6K / / 04.11.2006
Читать надо максимально возможными кусками, которые допускаются реализуемым алгоритмом, архитектурой проги и т.п. Потому что
1) каждое обращение к винту его изнашивает. И, скажем, на рабочем компе такое приводит к износу быстро.
2) каждое обращение к винту - перемещение головок, время.
21K
22 ноября 2006 года
Overmind
10 / / 21.11.2006
В подавляющем большинстве случаев оптиальный размер блока для чтения - это единица структурного представления во входном файле. Если это wav - то единицей логичнее всего, по моему, выбрать сэмпл, если bmp - пиксель.

Что же касается тех нечастых случаев, когда решаеая задача не навязывает структурную единицу для чтения...
Приведенный выше листинг Svyatozar-а был несколько модифицирован.
Код:
#include <stdio.h>
#include <windows.h>

#define BUFSIZE (2)

int main(int argc, char **argv) {

    bool APIOK = true;

    long time1, time2;

    HINSTANCE hModule=NULL;
    typedef  BOOL (_cdecl MESS)(UINT);
    MESS* me=NULL;
    hModule=::LoadLibrary(\"kernel32.dll\");
    me=(MESS*)::GetProcAddress((HMODULE)hModule,\"GetTickCount\");


    UINT type = 1;
    if ( APIOK )
        time1 = (*me)(type);

    char buf[BUFSIZE];
    FILE *fi, *fo;
    int errorlevel = 1;
    size_t bytes_read;
    if(argc < 3) {
        printf(\"file copy. usage:n%s infile outfile\\n\", argv[0]);
        goto done;
    }

    if(!(fi = fopen(argv[1], \"r\"))) {
        printf(\"cannot open input file: %s\\n\", argv[1]);
        goto done;
    }

    if(!(fo = fopen(argv[2], \"w+))) {
        printf(\"cannot open output file: %s\\n\", argv[2]);
        goto closefi;
    }

    for(; ; ) {
        bytes_read = fread(buf, 1, BUFSIZE, fi);
        fwrite(buf, 1, bytes_read, fo);
        if(bytes_read != BUFSIZE && feof(fi)) {
            break;
        }
    }
    fclose(fo);
closefi:
    fclose(fi);
    errorlevel = 0;
done:
    time2 = (*me)(type);
    printf (\"exec time: %d\\n\", time2 - time1);
    return errorlevel;
}


Здесь в начале и в конце выполнения програмы вызывается функция API функция GetTickCount, которая возвращает время, прошедшее с момента старта системы в милисекундах. Затем в выводится их разность, т.е. время выполнения цикла копирования.
Вот результаты
(2.exe - скопилировано для BUFFSIZE = 2, 1024.exe для BUFFSIZE = 1024)

запуск 2.exe - exec time: 42515
запуск 2.exe - exec time: 29844
запуск 2.exe - exec time: 29188
запуск 2.exe - exec time: 38234
запуск 2.exe - exec time: 34141
запуск 2.exe - exec time: 36157

запуск 1024.exe - exec time: 22109
запуск 1024.exe - exec time: 50469
запуск 1024.exe - exec time: 57484
запуск 1024.exe - exec time: 61266
запуск 1024.exe - exec time: 62828

запуск 2.exe - exec time: 55672
запуск 2.exe - exec time: 27578

запуск 1024.exe - exec time: 30609

Файл ок. 200 мб. Таким образом, не вижу четкой зависиости между размером буфера, и временем обработки.
284
22 ноября 2006 года
michael_is_98
587 / / 25.02.2005
Это происходит из-за того, что в C Run Time Library буферизация выполняется как самими функциями, так и самой ОС. (см. книгу Сергея Деревяго во вложении)

Читайте данные по столько байт, сколько нужно для обработки. Главное - чтобы размер буфера был под контролем и не достигал огромной величины (не содержал 200 Мб в оперативной памяти).
286
22 ноября 2006 года
misha_turist
572 / / 28.11.2005
А имеет смысл увеличивать производительность за счет изменения размера буфера (не важно в какую сторону).

Не получится ли, что подстраивание под "наиболее быстрый" размер буфера чтения/записи будет ресурсов и времени тратить больше, чем вся эта чудо экономия?????
284
22 ноября 2006 года
michael_is_98
587 / / 25.02.2005
1) Смысла нет.
2) Нет не получится.

Весь смысл в буферизации как раз и состоит в том, чтобы увеличить производительность при ограниченных аппаратных возможностях. Аппаратные возможности не могут быть сколь угодно большими, плюс размеры файлов могут быть разными...
Имея компонент для буферизированного чтения/записи данных можно не беспокоиться, сколько в такой-то машине ОЗУ, хватит ли ее для чтения файла такого-то размера.
Ты знаешь, сколько ОЗУ требуется для буфера (понятно что это несколько килобайт) и уже ни размер файла, ни размер ОЗУ не важен.
Это очень важно для создания программ, которые будут работать на машинах с различными аппаратными возможностями.
Для создания такого компонента нужно идти от задачи (возможно для задачи копирования файла лучше использовать функции Win32).

Идея буферизации широкого используется и в программах записи CD,DVD и в тех же процессорах, у которых есть свои буфера для хранения данных/команд. Если применяешь обработку какого-то текста, который хранится в файле, то здесь также лучше использовать буферизированное чтение/запись.

У меня, например, реализован лексер, который читает лексемы из файла. Файл может содержать сотни Мб текста, но реально программа будет читать его порциями - по аналогии с TParser из Delphi. Другое дело, что реально проще считать весь файл и затем его обработать :)
63
22 ноября 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: michael_is_98

1) Смысла нет.
2) Нет не получится.
Весь смысл в буферизации как раз и состоит в том, чтобы увеличить производительность при ограниченных аппаратных возможностях. Аппаратные возможности не могут быть сколь угодно большими, плюс размеры файлов могут быть разными...


А ты учитываешь среди аппаратных ограничений HDD?В ведь от скорости работы дисковой подсистемы многое зависит. Если, как ты говоришь, файл содержит сотни метров данных, которые по нему еще фрагментарно расбросаны..
Иногда это может быть более критичным, чем ОЗУ, мне кажется:)

284
23 ноября 2006 года
michael_is_98
587 / / 25.02.2005
Зачем тебе это знать? На уровне ОС буферизация уже реализована, реализована она и на аппаратном уровне (есть буферы в HDD)...
Тебе нужно лишь продумать буферизацию на уровне своей задачи.И сделать выделение области памяти независимым от размера файла, который будет читаться. Если всегда знаешь, что файл занимает 4 Кб - обходись без буфера. Если у тебя файл может быть большой и очень большой и тебе нужно его весь прочитать и обработать в соответствие со своей задачей - используй буферизированное чтение. Выбери размер буфера равным размеру кластера (4Кб) и все...
63
23 ноября 2006 года
Zorkus
2.6K / / 04.11.2006
Цитата: michael_is_98
Выбери размер буфера равным размеру кластера (4Кб) и все...


А почему не, скажем, 4 мб? если файл занимает 20?

284
23 ноября 2006 года
michael_is_98
587 / / 25.02.2005
Можешь выделить и 4Мб, если переменная (структура,массив) из твего файла занимает столько.
Иди от задачи.
Я использовал буфер 4Кб, потому что размера такого буфера вполне хватит чтобы выделить лексему (ключевое слово,идентификатор,литерал,операцию или пунктуатор) из входного потока.
286
23 ноября 2006 года
misha_turist
572 / / 28.11.2005
Давайте для начала определимся, к чему мы ведём дискуссию...

Если мы хотим определить некий "универсально-оптимальный" размер буфера чтения/записи, так он для каждой задачи и для каждого оборудования свой...
Если мы хотим определить нужен ли буффер как таковой, то нужен, если чтение должно быть либо быстрое, либо ведётся обработка (т.е. чтение, запись, перечтение, перезапись и т.д.) одних и техже данных (файлов, частей файлов и т.д.)

P.S. И вам не кажется, что создатель темы куда пропал....)))))))))
286
23 ноября 2006 года
misha_turist
572 / / 28.11.2005
А вообщето буферезация делается и без нас с вами, так что сильно мудрить на эту тему не стоит, не эффективно.
16K
23 ноября 2006 года
ivanhoeivanhoe
20 / / 01.11.2006
сомневаюсь по этому поводу. Щас винты все с внутренним кэшированием. что 8 кил -что 8 мег получишь с одной сред скоростью.
Я бы небольшие файлы читал бы не более 255 байт.Если компилятор поддерж MMX, SSe, SSe2 - то для больших массивов имеет смысл задействовать и большими буферами читать. А так не больше 64 кил
на ПС машине - ограничение архитектуры. Ещё и важен размер кэша на процессоре ...
286
23 ноября 2006 года
misha_turist
572 / / 28.11.2005
Цитата: ivanhoeivanhoe
сомневаюсь по этому поводу. Щас винты все с внутренним кэшированием. что 8 кил -что 8 мег получишь с одной сред скоростью.
Я бы небольшие файлы читал бы не более 255 байт.Если компилятор поддерж MMX, SSe, SSe2 - то для больших массивов имеет смысл задействовать и большими буферами читать. А так не больше 64 кил
на ПС машине - ограничение архитектуры. Ещё и важен размер кэша на процессоре ...


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

63
23 ноября 2006 года
Zorkus
2.6K / / 04.11.2006
Вопрос в том, что частые обращения к жесткому диску вредны. И время на порядок больше нужно. А буфер лежит спокойно в оперативке, и хлеба не просит:).
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог