Падение производительности с fputs после записи более 2,5 ГБ.Зачем? - PullRequest
8 голосов
/ 10 ноября 2011

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

#include "stdio.h"
#include "ctime"

int main()
{
    int i;
    const int linecount = 50000000;
    //Test Line with 184 byte
    const char* dummyline = "THIS IS A LONG TEST LINE JUST TO SHOW THAT THE WRITER IS GUILTY OF GETTING SLOW AFTER A CERTAIN AMOUNT OF DATA THAT HAS BEEN WRITTEN. hkgjhkdsfjhgk jhksjdhfkjh skdjfhk jshdkfjhksjdhf\r\n";
    clock_t start = clock();
    clock_t last = start;

    FILE* fp1 = fopen("D:\\largeTestFile.txt", "w");
    for(i=0; i<linecount; i++){
        fputs(dummyline, fp1);
        if(i%100000==0){
            printf("%i Lines written.\r", i);
            if(i%1000000 == 0){
                clock_t ms = clock()-last;
                printf("Writting of %i Lines took %i ms\n", i, ms);
                last = clock();
            }
        }
    }
    printf("%i Lines written.\n", i);
    fclose(fp1);
    clock_t ms = clock()-start;
    printf("Writting of %i Lines took %i ms\n", i, ms);

}

Когда вы запустите программу, вы увидите явное падение производительности после примерно 14-15 млн. Строк, что составляет около 2,5 ГБ данных.Запись занимает в 3 раза больше времени, чем раньше.Порог в 2 ГБ указывает на 64-битную проблему, но я не нашел ничего об этом в сети.Я также проверил, есть ли разница между двоичным и символьным режимом (например, "wb" и "w"), но нет.Я также попытался предварительно выделить размер файла (чтобы избежать фрагментации файла), выполнив поиск ожидаемого конца и записав нулевой размер, но это также мало что дало.

Я использую 64-битную машину Windows 7, но яЯ также проверил его на 64-битной машине с Windows Server 2008 R1.В настоящее время я тестирую файловую систему NTFS с более чем 200 ГБ свободного места.Моя система имеет 16 ГБ оперативной памяти, так что это тоже не должно быть проблемой.Тестовая программа использует только около 700 КБ.Ошибки страниц, о которых я подозревал ранее, также очень малы (~ 400 ошибок страниц за все время выполнения).

Я знаю, что для таких больших данных функция fwrite () подойдет для этой задачи лучше, но прив тот момент, когда меня интересует, есть ли другой обходной путь и почему это происходит.Любая помощь будет принята с благодарностью.

1 Ответ

9 голосов
/ 10 ноября 2011

Основная причина всего этого - кеш диска Windows.Затем ваша программа съедает для этого всю оперативную память, затем начинается обмен, и, таким образом, происходит замедление.Для борьбы с ними вам необходимо:

1) Открыть файл в режиме фиксации, используя флаг c:

FILE* fp1 = fopen("D:\\largeTestFile.txt", "wc");

2) Периодически записывать буфер на диск с помощью функции flush:

if(i%1000000 == 0)
{
    // write content to disk
    fflush(fp1);

    clock_t ms = clock()-last;
    printf("Writting of %i Lines took %i ms\n", i, ms);
    last = clock();
}

Таким образом, вы будете использовать разумное количество дискового кэша.Скорость будет в основном ограничена скоростью вашего жесткого диска.

...