парсинг mmap () - редактируемый файл - PullRequest
1 голос
/ 01 марта 2011

Каков наилучший (самый быстрый) способ анализа файла mmap? Он содержит пары данных (строка int), но я не могу предположить количество пробелов / табуляции / новых строк между ними.

Ответы [ 5 ]

4 голосов
/ 01 марта 2011

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

// Effectively this wraps the mmaped block
std::istringstream str;
str.rdbuf()->pubsetbuf(<pointer to start of mmaped block>, <size of mmaped block>);

std::string sv;
std::string iv;

while(str >> sv >> iv)
{
  // do stuff...
}

Я думаю, что это должноработа ...

ПРЕДУПРЕЖДЕНИЕ Это поведение, определяемое реализацией, см. этот ответ для более полного подхода.

2 голосов
/ 01 марта 2011

Анализ пар строк / целых чисел (т.е. foo 50 bar 20 baz 123), разделенных пробелами, должен быть молниеносным в любом случае.Гораздо более важными факторами будет то, что
a) страницы фактически находятся в ОЗУ, что само по себе mmap не гарантирует
b) строки кэша находятся в кэше L1

Хотя mmap уже читаетпо умолчанию при последовательном доступе впереди, доступ к диску составляет десятков миллисекунд , а разбор более 4 Кбайт памяти (в идеале) - десятки микросекунд.
Таким образом, вы не можете ожидать, что средство предварительной выборкичтобы идти в ногу, особенно потому, что он будет выполнять предварительную выборку только тогда, когда будет казаться, что вам потребуется больше (что, даже если предположить, что время поиска равно нулю, практически гарантирует авансовые затраты из-за задержки вращения на механическом диске).
Поэтому, если толькообщий объем данных составляет всего дюжину килобайт (в этом случае вопрос о том, как сделать это как можно быстрее, был бы бессмысленным, в любом случае), имеет смысл подумать (MADV_WILLNEED), прежде чем вы начнете сканирование, поэтому операционная система не будетподождите, чтобы увидеть его эвристику, вызванную вашим шаблоном доступа, но последовательно считывает, что он можетэто прекрати.Пропускная способность диска (последовательно), огромна, когда вы закончите время доступа.Вы все еще наверняка наверстаете упущенное, но гораздо позже.Если ваш набор данных достаточно большой, поэтому он, вероятно, не помещается в ОЗУ, вызов MADV_DONTNEED для данных, которые вы уже видели время от времени, является хорошей идеей.

То же, что верно для ошибок страниц, верно длякеш отсутствует.Загрузка из кэша составляет 1-2 цикла, загрузка из памяти - что-то около 200-500 циклов.
Процессоры имеют автоматическую предварительную выборку для последовательных шаблонов доступа, однако они ограничены.
Во-первых, предварительная выборка никогда не происходит на страницеграница.Это происходит потому, что если бы это было так, то автоматическая предварительная выборка будет регулярно вызывать сбои страниц, что будет очень неприятно.
Во-вторых, предварительная выборка происходит только после двух последовательных пропусков, это должно гарантировать, что предварительная выборка действительно срабатывает только тогда, когда она, вероятно, делаетсмысл.Предварительная выборка смежных строк кэша для каждого случайного чтения была бы глупой, так как она бы бесполезно удаляла ценные строки кэша.
В-третьих, предварительная выборка требует времени, и как только эвристика в триггере ЦП, вы уже гоняетесь за данными, поэтомускорее лучше, чем позже.
К счастью, вы знаете , какие данные вам понадобятся, и вы знаете, что они еще впереди.Следовательно, вы можете дать подсказки предварительной выборки, которые дадут ЦП мощный старт (предварительная выборка, например, на пол килобайта вперед).

2 голосов
/ 01 марта 2011

Если под «лучшим / самым быстрым» вы имеете в виду простейший код, то это один из тех редких случаев, когда устаревший std::istrstream идеально соответствует требованиям; вызовите перегрузку конструктора istrstream::istrstream(char const*, std::streamsize), затем извлеките данные из потока, как и из любого другого std::istream. (Это не будет дублировать основную память, как std::istringstream.)

Если под лучшим / самым быстрым вы подразумеваете лучшее / самое быстрое исполнение, я не думаю, что вы сможете победить повышение . дух . ци или анализатор, написанный от руки, хотя, на мой взгляд, первый вариант будет гораздо проще писать и поддерживать (если не считать кривую обучения в библиотеке, если вы никогда раньше не использовали boost.spirit).

0 голосов
/ 01 марта 2011

Вы можете получить к нему доступ через std::string и использовать std::istringstream для последовательного чтения. Или используйте более удобную библиотеку, например в Qt вы можете использовать QTextStream для QByteArray, созданного из памяти mmaped.

0 голосов
/ 01 марта 2011

В вашем нынешнем виде ваш вопрос слишком неопределенный, чтобы на него можно было ответить.

Тем не менее, если все, что вам нужно сделать, - это извлечь некоторые данные из файла, то, что вы не хотите сделать, - это использовать метод, который изменил бы память в mmap ed. обл.

Редактировать Теперь стало понятнее, когда вы отредактировали вопрос. В качестве отправной точки я бы использовал один указатель char для перебора всего файла mmap ed. Извлечение строк очень просто (точный метод зависит от того, что вам нужно сделать с результатом), и целые числа могут быть извлечены с помощью atoi и др.

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