Более быстрое решение для случайного текста W / R в Python
Мне нужно быстрое решение для случайных w/r текстовых фрагментов в Python. Что я хочу сделать, это так:
- Напишите фрагмент и запишите указатель
- Используйте указатель, чтобы получить фрагмент
Фрагменты имеют произвольную длину, и я предпочитаю не использовать базу данных для их хранения, а только указатели. Просто заменив методы файла Python на функции C (решение 1), это было довольно быстро, и указатели состоят только из "где" и "как долго" фрагмента. После этого я экспериментировал с тем, что мне показалось реальным, что работает с Berkeley DB. Я не знаю, как это назвать, что-то "пейджинговое"?
Дело в том, что этот код определенно работает, в 1,5-2 раза быстрее, чем решение 1, но он не намного быстрее и требует использования указателя из 4 частей. Возможно, это не достойный метод, но есть ли возможность значительно улучшить его?
Ниже приведен код:
from collections import namedtuple
from ctypes import cdll,c_char_p,\
c_void_p,c_size_t,c_long,\
c_int,create_string_buffer
libc = cdll.msvcrt
fopen = libc.fopen
fread = libc.fread
fwrite = libc.fwrite
fseek = libc.fseek
ftell = libc.ftell
fflush = libc.fflush
fclose = libc.fclose
#######################################################
# The following is how to write a snippet into the SnippetBase file
ptr = namedtuple('pointer','blk1, start, nblk, length')
snippet = '''
blk1: the first blk where the snippet is
start: the start of this snippet
nblk: number of blocks this snippet takes
length: length of this snippet
'''
bsize = 4096 # bsize: block size
fh = fopen('.\\SnippetBase.txt','wb')
fseek(fh,0,2)
pos1 = divmod(ftell(fh),bsize)
fwrite(snippet,c_size_t(len(snippet)),1,fh)
fflush(fh)
pos2 = divmod(ftell(fh),bsize)
ptr = ptr(pos1[0],pos1[1],pos2[0]-pos1[0]+1,len(snippet))
fclose(fh)
#######################################################
# The following is how to read the snippet from the SnippetBase file
fh = fopen('.\\SnippetBase.txt','rb')
fseek(fh,c_long(ptr.blk1*bsize),1)
buff = create_string_buffer(ptr.nblk*bsize)
fread(buff,c_size_t(ptr.nblk*bsize),1,fh)
print buffer(buff,ptr.start,ptr.length)
fclose(fh)
1 ответ
Это похоже на жесткий и непереносимый способ оптимизировать одну вещь - выделение памяти, выполняемое оболочками Python. file.read
а также os.read
, Все остальные части легко выполняются с помощью уже существующих функций в стандартной библиотеке Python. Есть даже простой способ выделить буфер чтения / записи в bytearray
, io
Модуль содержит метод readinto
, который присутствует в типах файлов; Я очень подозреваю, что это помогает избежать распределения. Однако в самых популярных операционных системах мы можем пойти еще дальше - используя дисковый буфер ОС напрямую, а не выделять локальную память для нашего процесса. Это сделано с помощью mmap
(но это становится сложно использовать, когда файл слишком велик для вашего адресного пространства). Для нераспределенного метода для чтения данных из файла mmaped просто используйте buffer(mm, offset, size)
,