Повышение производительности ifstream в c

#c

#c

Вопрос:

Прошу прощения, если этот вопрос немного расплывчатый или просто глупый, я все еще очень новичок.

Мне нужно извлечь информацию из файла веб-журнала на c . Манипуляции со строками являются относительными, своевременный доступ к данным — нет. Что я делаю в настоящее время

string str;

ifstream fh("testlog.log",ios::in);

while (getline(fh,str));

Отсюда я получаю полезные данные из строки. Это отлично работает для файла журнала со 100 записями, но занимает целую вечность для файла журнала с более чем миллионом записей. Будем признательны за любую помощь

Комментарии:

1. Просто для тестирования, не могли бы вы попробовать использовать fgets ? Откройте файл с помощью fopen , а затем что-то вроде while(fgets(cstr, 256, fp)) . Расскажите нам, каковы ваши результаты (сколько времени это займет).

2. Вы профилировали, чтобы увидеть, где находится узкое место? Если это диск, то ничто в коде не исправит это само по себе. (Если ваше процессорное время не затмевает время ввода-вывода, вы могли бы использовать многопоточность.)

Ответ №1:

Я действительно подозреваю, что ввод-вывод вредит вам больше, чем ifstream здесь. Вы проверили, действительно ли вы привязаны к процессору? Скорее всего, у вас проблемы с диском и локальностью кэша.

Возможно, в этом случае вы мало что сможете сделать.

Если он привязан к процессору, выполнили ли вы профилирование, чтобы увидеть, куда уходит процессорное время?

Комментарии:

1. Я знаю, что этот вопрос устарел, но давать такие ответы, как «диск» и «местоположение кэша», в качестве вопросов кому-то, кто сказал, что они новичок, без объяснения причин и запроса профилирования, не самый эффективный imo

Ответ №2:

Потратив много часов своего времени, я скомпилировал тот же код в Quincy2005 вместо Microsoft Visual studio. Результат был впечатляющим. Время выполнения уменьшено с 40 минут до 1 минуты. Некоторое улучшение может быть достигнуто в Microsoft Visual Studio путем передачи указателя обработчика файла функции getline. В системе на базе Linux выполнение занимает около 40 секунд. Я проклинал Microsoft добрых 40 минут за то, что она впустую потратила мое время.

Ответ №3:

Вот самый быстрый способ, который я нашел для извлечения файла :

 std::ifstream file("test.txt", std::ios::in | std::ios::end);

std::size_t fileSize = file.tellg();

std::vector<char> buffer(fileSize);

file.seekg(0, std::ios::beg);

file.read(buffer.data(), fileSize);

std::string str(buffer.begin(), buffer.end());
  

Тем не менее, если ваш файл действительно такой большой, я настоятельно рекомендую вам управлять им как потоком…

Комментарии:

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

Ответ №4:

@Ошибки:

вы уверены, что ваш код будет быстрее, чем, скажем:

 std::ifstream in("test.txt");
in.unsetf(std::ios::skipws);
std::string contents;
std::copy(
        std::istream_iterator<char>(in),
        std::istream_iterator<char>(),
        std::back_inserter(contents));
  

Кроме того, OP требует линейного доступа, что было бы удобно сделать:

 std::ifstream in("test.txt");
in.unsetf(std::ios::skipws);
size_t count = std::count_if(
        std::istream_iterator<std::string>(in),
        std::istream_iterator<std::string>(),
        amp;is_interesting);
std::cout << "Interesting log lines: " << count << std::endl;
  

конечно, определите предикат, например

 static bool is_interesting(const std::stringamp; line)
{ 
    return std::string::npos != line.find("FATAL");
}