#python #performance #io #mmap
#python #Производительность #io #mmap
Вопрос:
У меня есть файл бинарного примера объемом 1 ГБ, который я загружаю в память. При запуске бенчмарка на python 3.7 и Windows mmap
сильно проигрывает в производительности readinto
. Следующий код запускает тест. Первая процедура использует simple readinto
для чтения первых N байтов файла в буфер, тогда как вторая процедура использует mmap
просто для извлечения N байтов в память и чтения их тоже.
import numpy as np
import time
import mmap
import os
import matplotlib.pyplot as plt
def mmap_perf():
filepath = "test.bin"
filesize = os.path.getsize(filepath)
MEGABYTES = 10**6
batch_size = 10 * MEGABYTES
mview = memoryview(bytearray(filesize))
batch_sizes = []
load_durations = []
for i_part in range(1, filesize // batch_size):
start_time = time.time()
with open(filepath, "br") as fp:
# start = i_part * batch_size
fp.seek(0)
fp.readinto(mview[0:batch_size * i_part])
duration_readinto = time.time() - start_time
start_time = time.time()
with open(filepath, "br") as fp:
length = (i_part * batch_size // mmap.ALLOCATIONGRANULARITY 1) *
mmap.ALLOCATIONGRANULARITY
with mmap.mmap(fp.fileno(),
offset=0,
length=length,
access=mmap.ACCESS_READ) as mp:
mview[0:i_part * batch_size] = mp[0:i_part * batch_size]
duration_mmap = time.time() - start_time
msg = "{2}MBnreadinto: {0:.4f}nmmap: {1:.4f}"
print(msg.format(duration_readinto, duration_mmap, i_part * batch_size // MEGABYTES))
batch_sizes.append(batch_size * i_part // MEGABYTES)
load_durations.append((duration_readinto, duration_mmap))
load_durations = np.asarray(load_durations)
plt.plot(batch_sizes, load_durations)
plt.show()
График выглядит следующим образом:
Я просто не могу понять, как mmap полностью проигрывает, даже при загрузке небольших пакетов размером всего 10 МБ из файла объемом 1 ГБ.
Комментарии:
1.
mmap
это один из самых дорогих системных вызовов в Linux, и ошибка страницы при доступе к каждой следующей странице также увеличивает травму. Попробуйте использоватьMAP_POPULATE
.2. Вы также можете попробовать использовать огромные страницы и большие блоки. Это может немного помочь. Обратите внимание, что параллельное выполнение ошибок страницы (очистка страницы) обычно выполняется быстрее (по крайней мере, в Linux).
Ответ №1:
При такой нагрузке на последовательное чтение системный вызов readinto through может в значительной степени выиграть от предварительной выборки ОС, в то время как вам, возможно, придется установить MAP_POPULATE для mmap, чтобы получить то же преимущество. Если вы протестируете нагрузку на случайное чтение, вы увидите совершенно другое сравнение.
Комментарии:
1. Спасибо за подсказку. Модуль Python mmap, похоже, явно не содержит флага, но имеет » рекомендации mmap «. Я попытаюсь выяснить, соответствует ли какой-либо из флагов MAP_POPULATE .