Как использовать mmap в python, когда весь файл слишком большой

У меня есть скрипт python, который читает файл по строкам и смотрит, соответствует ли каждая строка регулярному выражению.

Я хотел бы улучшить производительность этого скрипта, используя карту памяти для файла перед поиском. Я просмотрел пример mmap: http://docs.python.org/2/library/mmap.html

Мой вопрос: как я могу mmap файл, когда он слишком большой (15 ГБ) для памяти моей машины (4 ГБ)

Я прочитал файл следующим образом:

fi = open(log_file, 'r', buffering=10*1024*1024) for line in fi: //do somemthong fi.close() 

Поскольку я устанавливаю буфер на 10 МБ, с точки зрения производительности, это то же самое, что и файл mmap размером 10 МБ?

Спасибо.

  • Сопоставьте два списка букв в Python
  • Ошибка ложной синтаксической ошибки PyCharm с использованием черепахи
  • Как запрашивать хранилище данных при использовании ReferenceProperty?
  • Зачем использовать упакованные * args / ** kwargs вместо передачи списка / dict?
  • API приложений (Python) Datastore Precall API
  • Попытка понять вложенные циклы, идентификационную матрицу
  • Python: проверьте, существует ли объект в области
  • Получение имени и расширения загруженного файла с помощью python (движок Google)
  • 2 Solutions collect form web for “Как использовать mmap в python, когда весь файл слишком большой”

    Во-первых, память вашей машины не имеет значения. Это важное значение для адресного пространства вашего процесса. С 32-разрядным Python это будет где-то менее 4 ГБ. С 64-битным Python этого будет более чем достаточно.

    Причиной этого является то, что mmap не связан с отображением файла в физическую память, а в виртуальную память . Файл mmap ped становится как особый файл подкачки для вашей программы. Думать об этом может немного сложно, но ссылки Wikipedia выше должны помочь.

    Итак, первый ответ – «использовать 64-битный Python». Но, очевидно, это может быть неприменимо в вашем случае.

    Очевидной альтернативой является отображение в первом 1 ГБ, поиск, который, отменить его, карту в следующем 1 ГБ и т. Д. Как вы это делаете, указав параметры length и offset методу mmap . Например:

     m = mmap.mmap(f.fileno(), length=1024*1024*1024, offset=1536*1024*1024) 

    Однако регулярное выражение, которое вы ищете, можно найти на полпути в первом 1 ГБ, а второе – во втором. Итак, вам нужно использовать оконную карту в первом 1GB, поиске, unmap, затем карте в частично перекрывающемся 1GB и т. Д.

    Вопрос в том, сколько перекрытий вам нужно? Если вы знаете максимально возможный размер матча, вам не нужно ничего больше. И если вы не знаете … ну, тогда нет никакого способа решить проблему, не разбивая ваше регулярное выражение, если это не очевидно, представьте, как вы могли бы найти совпадение 2 ГБ в одном окне 1 ГБ.

    Отвечая на ваш следующий вопрос:

    Поскольку я устанавливаю буфер на 10 МБ, с точки зрения производительности, это то же самое, что и файл mmap размером 10 МБ?

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

    Если вы хотите, чтобы я догадался: я думаю, что mmap может быть быстрее здесь, но только потому, что (как подразумевал JF Себастьян), цикл и вызов re.match 128K раз чаще, чем ваш код может быть привязан к CPU вместо IO-bound. Но вы можете оптимизировать это без mmap , просто используя read . Итак, mmap будет быстрее, чем read ? Учитывая размеры, я ожидал бы, что производительность mmap будет намного быстрее на старых платформах Unix, примерно на современных платформах Unix, и немного медленнее в Windows. (Вы можете получить большие преимущества производительности от mmap над read или read + lseek если вы используете madvise , но это не имеет значения здесь.) Но на самом деле это просто предположение.

    Наиболее убедительной причиной использования mmap обычно является то, что он проще, чем код, основанный на read , а не тот, что он быстрее. Когда вам нужно использовать оконную обработку даже с mmap , и когда вам не нужно искать read , это менее убедительно, но все же, если вы попытаетесь написать код в обоих направлениях, я бы ожидал, что ваш код mmap завершится немного более читабельным. (Особенно, если вы попытались оптимизировать буферные копии из очевидного решения для read ).

    Я пришел, чтобы попробовать использовать mmap потому что я использовал fileh.readline() в файле размером в десятки ГБ и хотел сделать его быстрее. Утилита Unix strace похоже, показывает, что файл теперь читается в 4kB-фрагментах, и, по крайней мере, вывод из strace кажется мне напечатанным медленно, и я знаю, что разбор файла занимает много часов.

     $ strace -v -f -p 32495 Process 32495 attached read(5, "blah blah blah foo bar xxxxxxxxx"..., 4096) = 4096 read(5, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 read(5, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 read(5, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 ^CProcess 32495 detached $ 

    Этот поток пока единственный, объяснив мне, что я не должен пытаться mmap слишком большого файла. Я не понимаю, почему нет такой вспомогательной функции, как mmap_for_dummies(filename) которая будет делать внутренне os.path.size (имя файла), а затем либо выполняет нормальный open(filename, 'r', buffering=10*1024*1024) или делать mmap.mmap(open(filename).fileno()) . Я, конечно, хочу избегать возиться с раздвижным окном, но если бы функция сделала простое решение, будет ли делать mmap или нет, мне будет достаточно.

    Наконец, мне все еще не ясно, почему некоторые примеры в Интернете упоминают open(filename, 'rb') без объяснения причин (например, https://docs.python.org/2/library/mmap.html ). Если вы часто хотите использовать файл в цикле for с .readline() я не знаю, должен ли я открываться в режиме 'rb' или 'r' (я думаю, что необходимо сохранить '\n' ) ,

    Спасибо за упоминание аргумента buffering=10*1024*1024) , вероятно, более полезно, чем изменение моего кода, чтобы получить некоторую скорость.

    Python - лучший язык программирования в мире.