Если оперативная память не вызывает беспокойства, то читается по очереди быстрее или читает все в ОЗУ и получает к ней доступ? – Python

Если оперативная память не вызывает беспокойства (у меня близко к 200 ГБ на сервере), читается по очереди быстрее или читает все в ОЗУ и получает доступ к ней? Каждая строка будет содержать строку порядка 200-500 символов юникода. Для каждого файла имеется около 2 миллионов строк.

Построчно

import codecs for i in codecs.open('unicodefile','r','utf8'): print i 

Чтение в ОЗУ

 import codecs for i in codecs.open('unicodefile','r','utf8').readlines(): print i 

4 Solutions collect form web for “Если оперативная память не вызывает беспокойства, то читается по очереди быстрее или читает все в ОЗУ и получает к ней доступ? – Python”

Я использовал cProfile в файле слов словаря размером 1 МБ. Я читал один и тот же файл 3 раза. Первый читает весь файл только для того, чтобы даже игровое поле с точки зрения его хранения в кеше. Вот простой код:

 def first_read(): codecs.open(file, 'r', 'utf8').readlines() def line_by_line(): for i in codecs.open(file, 'r', 'utf8'): pass def at_once(): for i in codecs.open(file, 'r', 'utf8').readlines(): pass first_read() cProfile.run('line_by_line()') cProfile.run('at_once()') 

И вот результаты:

Построчно:

  366959 function calls in 1.762 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 1.762 1.762 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 codecs.py:322(__init__) 1 0.000 0.000 0.000 0.000 codecs.py:395(__init__) 14093 0.087 0.000 0.131 0.000 codecs.py:424(read) 57448 0.285 0.000 0.566 0.000 codecs.py:503(readline) 57448 0.444 0.000 1.010 0.000 codecs.py:612(next) 1 0.000 0.000 0.000 0.000 codecs.py:651(__init__) 57448 0.381 0.000 1.390 0.000 codecs.py:681(next) 1 0.000 0.000 0.000 0.000 codecs.py:686(__iter__) 1 0.000 0.000 0.000 0.000 codecs.py:841(open) 1 0.372 0.372 1.762 1.762 test.py:9(line_by_line) 13316 0.011 0.000 0.023 0.000 utf_8.py:15(decode) 1 0.000 0.000 0.000 0.000 {_codecs.lookup} 27385 0.027 0.000 0.027 0.000 {_codecs.utf_8_decode} 98895 0.011 0.000 0.011 0.000 {len} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 13316 0.099 0.000 0.122 0.000 {method 'endswith' of 'unicode' objects} 27 0.000 0.000 0.000 0.000 {method 'join' of 'str' objects} 14069 0.027 0.000 0.027 0.000 {method 'read' of 'file' objects} 13504 0.020 0.000 0.020 0.000 {method 'splitlines' of 'unicode' objects} 1 0.000 0.000 0.000 0.000 {open} 

Все вместе:

  15 function calls in 0.023 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.023 0.023 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 codecs.py:322(__init__) 1 0.000 0.000 0.000 0.000 codecs.py:395(__init__) 1 0.000 0.000 0.003 0.003 codecs.py:424(read) 1 0.000 0.000 0.014 0.014 codecs.py:576(readlines) 1 0.000 0.000 0.000 0.000 codecs.py:651(__init__) 1 0.000 0.000 0.014 0.014 codecs.py:677(readlines) 1 0.000 0.000 0.000 0.000 codecs.py:841(open) 1 0.009 0.009 0.023 0.023 test.py:13(at_once) 1 0.000 0.000 0.000 0.000 {_codecs.lookup} 1 0.003 0.003 0.003 0.003 {_codecs.utf_8_decode} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 1 0.001 0.001 0.001 0.001 {method 'read' of 'file' objects} 1 0.010 0.010 0.010 0.010 {method 'splitlines' of 'unicode' objects} 1 0.000 0.000 0.000 0.000 {open} 

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

Ничто не мешает вам проверить это на вашей машине. Я создал файл с 1M строк каждый и результаты, приуроченные к

 time python something.py > /dev/null 

мы:

Построчно:

 real 0m4.878s user 0m4.860s sys 0m0.008s 

Чтение в ОЗУ:

 real 0m0.981s user 0m0.828s sys 0m0.148s 

Я получил MemoryError при попытке с 2M строк, по 300 символов, но вышеизложенное говорит о том, что чтение в RAM будет быстрее.

Глядя на примерный код, опубликованный OP, я думаю, что есть непонимание того, что делает Python.

То есть:

«Чтение по строкам»

 import codecs for i in codecs.open('unicodefile','r','utf8'): print i 

Вышеприведенное выглядит так, как будто оно читается по строкам. Однако Python интерпретирует это как «как большую часть файла в памяти, а затем обрабатывает каждый как строку». Таким образом, вышесказанное для цикла читает все в памяти.

«Чтение в ОЗУ»

 import codecs for i in codecs.open('unicodefile','r','utf8').readlines(): print i 

Я считаю, что вышеперечисленное практически совпадает с приведенным выше примером «строка за строкой». Т.е., Python читает все это в памяти.

Если бы вы хотели протестировать линейную производительность, вам понадобится «readline ()», а не «readlines ()» или неуказанный цикл, что может означать «readlines ()». Об этом говорится в другом месте на сайте StackOverflow.

Другим аспектом, который следует учитывать, является буферизация файловой системы. Если вы используете один и тот же бит кода для одного и того же файла, тогда вы рискуете сбросом файловой системы, загрязняя результаты. Как вы говорите, у вас есть 200 ГБ оперативной памяти, что более чем достаточно, чтобы достаточно буферизовать файл, чтобы повлиять на результаты запуска.

Для обеспечения чистых результатов теста вам необходимо выполнить следующие действия:

1) скопируйте большой файл из известного источника в новое имя файла. (Файловая система должна быть не файловой системой COW.) 2) очистить кеш файловой системы 3) запустить первый тест с файлом. 4) удалите файл. 5) скопируйте файл из источника в другое новое имя файла. 6) очистить кеш файловой системы. 7) запустить второй тест против нового файла.

Это даст вам более точный тест времени загрузки файлов.

Если вы хотите загрузить весь файл в память сразу, не будет ли filehandle.read (чтение в байтах) потенциально обеспечить более быстрый способ чтения блоков в содержимом файла?

В любом случае, для справки:

http://docs.python.org/2/tutorial/inputoutput.html

лучше построить свою программу с помощью потоковой обработки (строка за строкой), в этом случае вы можете обрабатывать большие объемы данных. В общем, лучше реализовать чтение, которое, например, считывает 100 строк, затем обрабатывает их, затем загружает еще 100 строк. На низкоуровневом уровне вы просто используете большой буфер и читаете исходный файл большими кусками. Если вы загружаете все в память – вы можете получить ошибку памяти, например, @oseiskar

  • Как преобразовать символы Unicode с акцентом в чистый ascii без акцентов?
  • Python: Unicode и ElementTree.parse
  • Python 3.4 вызывает UnicodeEncodeError на сервере Apache2 (Mac), но отлично работает в командной строке
  • удаление emojis из строки в Python
  • Поведение юникода на Python в Google App Engine
  • Проблема китайского Юникода?
  • Как сделать Python split () на языках (например, китайском), которые не используют пробелы в качестве разделителя слов?
  • Отображение символов юникода с использованием python
  • Python - лучший язык программирования в мире.