LINUX.ORG.RU

Быстрое считывание произвольной части большого файла

 


1

2

Представим что у нас есть файл размером * 100500 оперативной памяти, находится он на HDD в ext4 фс. Обычное считывание со смещением на N будет происходить так: открываем файл, читаем, считаем прочитанное по байту, если прочитанное равно началу смещения, то помещаем [N:] в буфер и считаем пока прочитанное не станет равно концу смещения [:N].

Допустим у нас есть файл-индекс по полю Name, где записан указатель на начало и конец смещения.

Правильно ли я понимаю процесс считывания?

Правильно ли я понимаю схему выборки?

Какие есть способы хакинга чтобы прочитать N байт из большого файла, где N произвольно или ближе к концу файла?

Немного сумбурно, буду признателен за любые ответы и ссылки. Спасибо.

★★★★

Последнее исправление: dnb (всего исправлений: 1)

«считать начиная со смещения» это не считать весь файл до смещения, это сразу перейти к смещению и начать считывать

quester ★★
()
Ответ на: комментарий от quester

Я не очень умный, можно немного расширить ответ? Я предполагаю что считывание со смещением это двойная буферизация. Верно ли это?

mmap

А не является ли это той же самой двойной буферизацией?

dnb ★★★★
() автор топика
Ответ на: комментарий от anonymous

Согласен, каша в голове. Я имел ввиду что первый буфер это то место, куда мы непрерывно читаем файл, а второй буфер уже отсчитывает смещение.

open + seek + read.

Можно немного шире или ссылку?

dnb ★★★★
() автор топика
Ответ на: комментарий от dnb

open - открываем файл, seek - переходим к нужному смещению (мгновенно), read - читаем нужное количество байт. Всё.

anonymous
()

Спасибо, парни) Seek вроде то, что нужно.

dnb ★★★★
() автор топика

А при чем тут базы данных?

mersinvald ★★★★★
()
Ответ на: комментарий от Zenom

Весь вопрос в том, сколько нам нужно прочитать.

Если меньше странички, то mmap невыгоден.

Польза от mmap проявляется на чтении нескольких страниц.

Но удобство и переносимость у read() лучше чем у mmap().

vel ★★★★★
()
Ответ на: комментарий от vel

Весь вопрос в том, сколько нам нужно прочитать.

Если произвольное значение? Оно указано в файл-индексе.

dnb ★★★★
() автор топика
Последнее исправление: dnb (всего исправлений: 1)
Ответ на: комментарий от dnb

Если это произвольное значение не превышает объема доступной физической памяти - то не проблема.

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

для х86 размер страницы 4к

vel ★★★★★
()
Ответ на: комментарий от vel

Я образно. Тут важно чтобы смещение было именно произвольной длины, может и 6 килобайт, а может и 29.73 мегабайт. Размер страницы в чем измеряется (4к)?

dnb ★★★★
() автор топика
Ответ на: комментарий от dnb

Смещение произвольное, но кратное размеру страницы

Размер страницы определяется через getpagesize()

Если тебе нужно получить данные N[5000:9999], то грубо говоря нужно сделать

mmap(NULL,5904,PROT_READ,MAP_PRIVATE, fd, 4096) + 904

при условии, что страничка 4096 байт.

vel ★★★★★
()
Ответ на: комментарий от dnb

Если произвольное значение? Оно указано в файл-индексе.

На шпиндельных дисках seek() может быть не такой уж и быстрый. Физически seek-и бывают разные, короткие и длинные, в дальнее место диска. Вот здесь есть некоторые цифры https://en.wikipedia.org/wiki/Hard_disk_drive_performance_characteristics

Обычно операционная система делает так называемый read-ahead, т.е. предполагается что данные после позиционирования будут читаться линейно, можно немного прочитать лишнего и подержать в кэше. Это поведение настраивается.

Если файл не очень большой и нужно читать и писать короткие (меньше нескольких килобайт) данные в разные места, mmap()* с большой вероятностью будет эффективнее чем позиционироваться и читать вручную

UPD: * mmap() на весь файл, конечно

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Zenom

будет. следует из практики. от 10 до 25% быстрее при чтении больших объёмов данных на разных носителях. и особенно эффективно, если надо бегать по всему файлу и чтение часто попадает в некоторый регион, который можно весь держать в памяти. для мелких файлов его не применяют.

даже бенчмарк есть в интернетах: https://eklausmeier.wordpress.com/2016/02/03/performance-comparison-mmap-vers...

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от Iron_Bug

Ну, можно попробовать open+fadvise+read с одной стороны, и open+mmap+mad vise с другой. Практика показывает, что скорости примерно одинаковые, и понятно почему

Dennis7
()
Ответ на: комментарий от dnb

можно немного расширить ответ?

из вашего вопроса я понял что вы думаете так: есть у нас файл размером 10 гигабайт, нам нужно считать 10 байт начиная со смещения 5 гигабайт и для этого нам сначала нужно прочитать 5 гигабайт, отбросить их и потом уже прочитать нужные нам 10 байт. так вот это не так. используйте seek или map и считывыйте 10 байт мгновенно с любого смещения. Под «мгновенно» имеется ввиду что скорость чтения никак не зависит от смещения.

quester ★★
()
Ответ на: комментарий от quester

Да, спасибо, я это уже понял из предыдущих комментариев форумчан) Осталось понять как строить такие же быстрые индексы к полям.

dnb ★★★★
() автор топика
Ответ на: комментарий от quester

Некую упрощенную версию, где отсутствуют все мощности sql в угоду скорости и сжатию.

dnb ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.