Разбор текста из CMemFile построчно - PullRequest
1 голос
/ 31 мая 2011

Я получил огромный текстовый файл, загруженный в объект CMemFile, и хотел бы проанализировать его построчно (разделенный символами новой строки).
Первоначально это zip-файл на диске, и я разархивирую его в память, чтобы проанализировать его, поэтому CMemFile.

Один из рабочих способов читать построчно: m_file - это умный указатель на CMemFile):

    CArchive archive(m_file.get(), CArchive::load);

    CString line;

    while(archive.ReadString(line))
    {
        ProcessLine(string(line));
    }

Поскольку это занимает много времени, я попытался написать свою собственную программу:

    const UINT READSIZE = 1024;
    const char NEWLINE = '\n';
    char readBuffer[READSIZE];
    UINT bytesRead = 0;
    char *posNewline = NULL;

    const char* itEnd = readBuffer + READSIZE;
    ULONGLONG currentPosition = 0;
    ULONGLONG newlinePositionInBuffer = 0;

    do
    {
        currentPosition = m_file->GetPosition();

        bytesRead = m_file->Read(&readBuffer, READSIZE);        

        if(bytesRead == 0) break; // EOF

        posNewline = std::find(readBuffer, readBuffer + bytesRead, NEWLINE);

        if(posNewline != itEnd)
        {
            // found newline
            ProcessLine(string(readBuffer, posNewline));
            newlinePositionInBuffer = posNewline - readBuffer + 1; // +1 to skip \r
            m_file->Seek(currentPosition + newlinePositionInBuffer, CFile::begin);
        }
    } while(true);

Измерение производительности показало, что оба метода занимают примерно одно и то же время ...

Можете ли вы вспомнить какие-либо улучшения производительности или более быстрый способ анализа?

Спасибо за любой совет

Ответы [ 4 ]

2 голосов
/ 31 мая 2011

Несколько замечаний и комментариев, которые могут быть полезны:

  • Профилирование - это единственный способ точно знать, что делает код и сколько времени это занимает.Часто узкое место не очевидно из самого кода.Один из основных методов заключается в определении времени загрузки, распаковки и разбора по отдельности.
  • Фактическая загрузка файла с диска, а в вашем случае распаковка может на самом деле занять значительно больше времени, чем анализ, особенно если ваша функция ProcessFile() не nop.Если ваш анализ занимает всего 1% от общего времени, то вы никогда не получите много от попыток оптимизировать этот 1%.Это то, что вам скажет профилирование вашего кода.
  • Общий способ оптимизации алгоритма загрузки / разбора - посмотреть, сколько раз конкретный байт читается / анализируется.Минимальный и, возможно, самый быстрый алгоритм должен считывать и анализировать каждый байт только один раз.Глядя на ваши алгоритмы, кажется, что каждый байт копируется полдюжины раз и потенциально анализирует аналогичное число.Уменьшение этих чисел может помочь сократить общее время алгоритма, хотя относительное усиление может быть не очень общим.
1 голос
/ 01 июня 2011

Использование профилировщика показало, что 75% времени процесса было потрачено впустую в этой строке кода:

 ProcessLine(string(readBuffer, posNewline));

Главным образом создание временной строки вызвало большие накладные расходы (много ресурсов). Сама функция ProcessLine не содержит кода. Изменив декларацию с:

void ProcessLine(const std::string &);

до:

inline void ProcessLine(const char*, const char*);

использованное время процесса было сокращено в пять раз.

0 голосов
/ 31 мая 2011

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

Если ваш файл был

   foo
   bar
   etc

Скажите, что в строке 10 средних байт. Вы прочтете 10 строк ... и снова прочитаете 9 строк.

0 голосов
/ 31 мая 2011

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

Это позволяет одновременно работать параллельно, а также приводит к меньшим затратам памяти, поскольку вы работаете с блоками, а не со всем распакованным файлом (что приведет к уменьшению количества сбоев страниц и переходов в виртуальную память).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...