#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");
}