Как fseek () реализован в файловой системе? - PullRequest
17 голосов
/ 13 марта 2010

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

Мне интересно, насколько эффективно вставить данные в середину файла. Предположим, у меня есть файл с данными 1 МБ, а затем я вставляю что-то со смещением 512 КБ. Насколько это эффективно по сравнению с добавлением моих данных в конец файла? Просто чтобы завершить пример, скажем, я хочу вставить 16 КБ данных.

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

Ответы [ 6 ]

5 голосов
/ 13 марта 2010

(отказ от ответственности: я хочу просто добавить несколько подсказок к этой интересной дискуссии) ИМХО, есть некоторые вещи, которые необходимо учитывать:

1) fseek - это не основная системная служба, а библиотечная функция. Чтобы оценить его производительность, мы должны рассмотреть, как реализована библиотека файлового потока. В общем, библиотека файлового ввода-вывода добавляет уровень буферизации в пользовательском пространстве, поэтому производительность fseek может сильно отличаться, если целевая позиция находится внутри или вне текущего буфера. Кроме того, системные службы, которые использует библиотека ввода-вывода, могут сильно различаться. То есть в некоторых системах библиотека широко использует отображение файловой памяти, если это возможно.

2) Как вы сказали, разные файловые системы могут вести себя по-разному. В частности, я ожидаю, что транзакционная файловая система должна сделать что-то очень умное и, возможно, дорогое, чтобы подготовиться к возможному откату прерванной операции записи в середине файла.

3) Современные ОС имеют очень агрессивные алгоритмы кэширования. Вероятно, файл «fseeked» уже присутствует в кеше, поэтому операции становятся намного быстрее. Но они могут сильно ухудшиться, если общая активность файловой системы, вызванная другими процессами, станет важной.

Есть комментарии?

4 голосов
/ 13 марта 2010

Давайте возьмем в качестве примера ext2 FS и ОС Linux.Я не думаю, что будет существенная разница в производительности между вставкой и дополнением.В обоих случаях должны быть прочитаны узел файлов и таблица смещений, соответствующий сектор диска сопоставлен с памятью, данные обновлены, а в какой-то момент позже данные записаны на диск.В этом примере большая разница в производительности - это хорошая временная и пространственная локальность при доступе к частям файла, поскольку это уменьшит количество комбинаций загрузки / сохранения.

Как и в предыдущих ответах, вы можетеУскорьте обе операции, если вы имеете дело с записью данных, которые кратны размеру блока FS, в этом случае вы можете пропустить этап загрузки и просто вставить новые блоки в структуру данных inode файлов.Это не будет практично, так как вам потребуется низкоуровневый доступ к драйверу FS, и его использование будет очень ограничительным и непереносимым.

3 голосов
/ 13 марта 2010

fseek(...) - это библиотечный вызов, а не системный вызов ОС. Это библиотека времени выполнения, которая заботится о фактических издержках, связанных с выполнением системного вызова ОС, технически говоря, fseek косвенно выполняет вызов системы, но на самом деле это не так (это приводит к четкому различию между различия между вызовом библиотеки и системным вызовом). fseek(...) - это стандартная функция ввода-вывода независимо от базовой системы ... однако ... и это большая однако ...

ОС, скорее всего, будет кэшировать файл в памяти своего ядра, то есть прямое смещение к месту на диске, где хранятся 1 и 0, это через уровни ядра ОС, более чем вероятно, самый верхний слой в ядре, который будет иметь моментальный снимок того, из чего состоит файл, то есть данные независимо от того, что он содержит (это не волнует в любом случае, пока «указатели» на структуру диска для это смещение относительно расположения на диске действительно!) ...

Когда происходит fseek(..), косвенно возникает много перегрузок, ядро ​​делегировало задачу чтения с диска, в зависимости от того, насколько фрагментирован файл, теоретически это может быть "повсеместно". «Это может быть значительным накладным расходом с точки зрения необходимости, с точки зрения пользовательской земли, то есть кода C, выполняющего fseek(...), он может разбросать себя повсеместно, чтобы собрать данные в единое целое». непрерывное представление данных "и впредь, вставка в середину файла (помните, что на этом этапе ядру придется корректировать расположение / смещения в фактическом дисковом массиве для данных) будет считаться медленнее, чем добавление к конец файла.

Причина довольно проста, ядро ​​«знает», каким было последнее смещение, и просто стереть маркер EOF и вставить дополнительные данные, за кадром ядру приходится выделять еще один блок памяти для диска. -буфер с откорректированным смещением к месту на диске после маркера EOF после завершения добавления данных.

2 голосов
/ 29 августа 2010

Одно замечание, которое я сделал о fseek в Solaris, заключается в том, что каждый вызов этого метода сбрасывает буфер чтения FILE. Следующее чтение будет всегда читать полный блок (по умолчанию 8K). Поэтому, если у вас много произвольного доступа с небольшими операциями чтения, неплохо бы сделать это без буферизации (setvbuf с NULL буфером) или даже использовать прямые системные вызовы (lseek + read или даже лучше pread, только 1 системный вызов вместо 2). Я полагаю, что это поведение будет аналогичным на других ОС.

1 голос
/ 13 марта 2010

Вставка данных в середину файла менее эффективна, чем добавление в конец, потому что при вставке вам придется перемещать данные после точки вставки, чтобы освободить место для вставляемых данных. Перемещение этих данных потребует чтения их с диска, записи данных для вставки, а затем записи старых данных после вставленных данных. Таким образом, при вставке у вас есть хотя бы одно дополнительное чтение и запись.

1 голос
/ 13 марта 2010

Вы можете эффективно вставлять данные в середину файла, только если размер данных кратен сектору FS, но операционные системы не предоставляют таких функций, поэтому необходимо использовать низкоуровневый интерфейс с драйвером FS.

...