C++ ifstream::read медленный из-за memcpy

Недавно я решил оптимизировать чтение файла, которое я делал, потому что, как все говорят, чтение большого куска данных в буфер и последующая работа с ним быстрее, чем использование большого количества маленьких операций чтения. И мой код, безусловно, теперь намного быстрее, но после некоторого профилирования оказывается, что memcpy занимает много времени.

Суть моего кода такова...

ifstream file("some huge file");
char buffer[0x1000000];
for (yada yada) {
    int size = some arbitrary size usually around a megabyte;
    file.read(buffer, size);
    //Do stuff with buffer
}

Я использую Visual Studio 11, и после профилирования моего кода он говорит ifstream::read()в итоге вызывает xsgetn(), который копирует из внутреннего буфера в мой буфер. Эта операция занимает более 80% времени! На втором месте uflow(), который занимает 10% времени.

Можно ли обойти это копирование? Могу ли я каким-то образом указать ifstreamбуферизовать нужный мне размер прямо в мой буфер? Использует ли C-стиль FILE*такой внутренний буфер?

ОБНОВЛЕНИЕ: Из-за того, что люди посоветовали мне использовать cstdio... Я провел тест.

РЕДАКТИРОВАТЬ: К сожалению, старый код был полон ошибок (он даже не читал весь файл!). Вы можете увидеть это здесь: http://pastebin.com/4dGEQ6S7

Вот мой новый тест:

const int MAX = 0x10000;
char buf[MAX];
string fpath = "largefile";
int main() {
    {
        clock_t start = clock();
        ifstream file(fpath, ios::binary);
        while (!file.eof()) {
            file.read(buf, MAX);
        }
        clock_t end = clock();
        cout << end-start << endl;
    }
    {
        clock_t start = clock();
        FILE* file = fopen(fpath.c_str(), "rb");
        setvbuf(file, NULL, _IOFBF, 1024);
        while (!feof(file)) {
            fread(buf, 0x1, MAX, file);
        }
        fclose(file);
        clock_t end = clock();
        cout << end-start << endl;
    }
    {
        clock_t start = clock();
        HANDLE file = CreateFile(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL, NULL);
        while (true) {
            DWORD used;
            ReadFile(file, buf, MAX, &used, NULL);
            if (used < MAX) break;
        }
        CloseHandle(file);
        clock_t end = clock();
        cout << end-start << endl;
    }
    system("PAUSE");
}

Время:
185
80
78

Ну... похоже, использование fread в стиле C работает быстрее, чем ifstream::read. Кроме того, использование Windows ReadFile дает лишь небольшое преимущество, которое незначительно (я посмотрел на код, и fread в основном является оболочкой для ReadFile). Похоже, я все-таки перейду на фред.

Чувак, как сложно писать бенчмарк, который на самом деле правильно тестирует все это.

ЗАКЛЮЧЕНИЕ: Использование быстрее, чем . Причина, по которой fstream работает медленнее, заключается в том, что потоки С++ имеют собственный внутренний буфер. Это приводит к дополнительному копированию всякий раз, когда вы читаете/записываете, и на это копирование приходится все дополнительное время, затрачиваемое fstream. Еще более шокирующим является то, что дополнительное время, затрачиваемое на чтение файла, больше, чем время, необходимое для фактического чтения файла.

8
задан retep998 26 April 2012 в 05:14
поделиться