Производительность при вызове определенных функций POSIX -по сравнению с прямыми вызовами ядра Linux

how do I move the Fedora partition to before the boot ext4 partition and resize it?

Ответ может быть неожиданным. :Вам не обязательно этого делать.

Поскольку вы используете LVM и не стремитесь расширить не -раздел LVM (, то есть /boot), вам не нужно расширять существующий PV. Вместо этого вы можете создать новый раздел из нераспределенного пространства, использовать pvcreate, чтобы сделать его вторым PV LVM, затем vgextendдо добавить его в существующую группу томов .

При использовании LVM ваша группа томов может состоять из одного или нескольких физических томов на одном или нескольких дисках; LVM на это наплевать. Все PV в одной VG будут работать вместе как единый пул дискового пространства. Затем вы можете свободно расширять или создавать новые LV, не заботясь о том, где заканчивается один PV и начинается другой. Все это будет обрабатываться LVM прозрачно.

Во-первых, используйте gpartedили любой другой инструмент, который вам нравится, чтобы превратить это нераспределенное пространство в пригодный для использования раздел. Вы должны установить его тип («флаги» вgparted)как lvm2 pv, но, строго говоря, это не обязательно. Я предполагаю, что он будет называться /dev/nvme0n1p7.

Убедитесь, что новый раздел виден в /proc/partitions, что указывает на то, что ядро ​​приняло новую таблицу разделов. Если этого не произошло, вам может потребоваться запустить partprobe /dev/nvme0n1и проверить еще раз.Если раздел по-прежнему не распознается ядром, вам может потребоваться перезагрузка на этом этапе.

Как только раздел станет видимым, вы можете продолжить. Используйте pvs, чтобы увидеть, инициализировал ли уже gpartedраздел как LVM PV; если нет, запустите pvcreate /dev/nvme0n1p7для его инициализации.

Затем, предполагая, что ваша группа томов LVM использует имя по умолчанию fedora, запустите vgextend fedora /dev/nvme0n1p7.

Теперь ранее -нераспределенное пространство было добавлено в группу томов, и вы можете использовать его для расширения существующих LV и/или создания новых по своему усмотрению.

3
10.01.2018, 23:10
3 ответа

Funciones como readdir()y amigos se implementan en libc, que es una biblioteca compartida. Al igual que con todas las bibliotecas compartidas, eso agrega cierta redirección para poder resolver la dirección de memoria de la función dentro de la biblioteca compartida.

La primera vez que se realiza una llamada de biblioteca en particular, el enlazador dinámico necesita buscar la dirección de la llamada de biblioteca dentro de una tabla hash. Esto implica al menos una (pero posiblemente más )comparaciones de cadenas, un método comparativamente costoso. La dirección encontrada luego se guarda en la tabla de vinculación de procedimientosPLT(), de modo que la próxima vez que se llame a la función, la sobrecarga de encontrar la función se reduce a tres instrucciones (en la arquitectura x86, menos que eso. en algunas otras arquitecturas ). Esta es la razón por la que compilar algo como un objeto compartido (en lugar de un objeto estático )tiene algunos gastos generales. Para obtener más información sobre la sobrecarga de bibliotecas compartidas y cómo funcionan las bibliotecas compartidas en Linux, consulte la explicación técnica detallada de Ulrich Drepper sobre el tema .

La ​​función syscall()en sí misma está también implementada en libc, por lo que también tiene esa redirección. Sin embargo, dado que solo usaría esa función (y ninguna otra ), el enlazador dinámico tiene menos trabajo que hacer. Además,la implementación de una función particular como readdirtendría que convertir los valores devueltos y realizar una verificación de errores, etc. al salir de la función syscall(), lo cual es una sobrecarga adicional. Un programa que se ejecuta syscall()directamente funcionaría con los valores de retorno directos de la llamada al sistema y no necesitaría esa conversión (, aún necesitaría hacer la verificación de errores, lo que complicaría la función significativamente ).

La desventaja de ejecutar syscall()directamente es que pasa a una API que es menos portátil. La página de manual syscall()explica algunas limitaciones específicas de la arquitectura -que libc trata por usted; si usa syscall()directamente, su función podría funcionar en la arquitectura con la que está tratando, pero fallaría, por ejemplo, en una máquina de brazo.

En general, recomendaría no usar la API syscall()directamente, por la misma razón por la que recomendaría no escribir el código en lenguaje ensamblador directamente. Sí, eso podría terminar siendo más rápido al final, pero la carga de mantenimiento se vuelve (mucho )mayor. Algunas cosas que podrías hacer en su lugar:

  • No te preocupes por el rendimiento. Los sistemas se vuelven cada vez más baratos y, en muchos casos, "agregar otro sistema para que las cosas vayan más rápido" es más barato que "pagar las tarifas por hora de un programador para mejorar el rendimiento".
  • Compile el software contra bibliotecas estáticas en lugar de usar bibliotecas compartidas, para las pocas cosas pequeñas donde el rendimiento es crítico (es decir,gcc -static)
  • Use un generador de perfiles para ver dónde las cosas van lentas y concéntrese en esas cosas, en lugar de preocuparse por cómo hacer una llamada al sistema.
1
27.01.2020, 21:18

Такие факторы, как PLTкосвенность или syscall()'sвариативность -ness (регистры должны быть сохранены в памяти )должны играть небольшую роль, учитывая, что getdentsявляется одним из самых дорогих вызовов в Linux.

Полное чтение пустого каталога на моей машине занимает около 5 мкс, каталога из 100 -элементов — 37 мкс, каталога из 1000 -элементов — 340 мкс, а каталога из 10 000 -элементов — 3,79 мс.

Что fdopendir+ readdirделает поверх getdents, так это добавляет выделение/освобождение буфера (0,1 мкс )и statпроверку того, что предоставленный fd относится к разновидности каталога (0,4 мкс ). readdirзатем делает один дешевый вызов для каждой записи каталога (перемещает позицию в буфере и, возможно, перезаполняет ).

Таким образом, есть что-то вроде одного -временного накладного расхода в 0,5 мкс, что составляет 10% времени сканирования каталога для пустых каталогов, но только 1% для каталогов из 100 -элементов и ничтожно мало для больших каталогов. Эти накладные расходы в 5 раз меньше (только стоимости выделения/освобождения ), если вам не нужен fdopen.(вам нужен fdopen только в том случае, если вы не можете diropenнапрямую и, следовательно, должны использовать отдельно полученный (например, openat'ted )файловый дескриптор ).

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

Что касается вызовов readdir, стоимость косвенного обращения PLT на современном оборудовании обычно составляет менее 1 нс, служебные затраты на вызов функции составляют около 1 -2 нс. Учитывая, что время сканирования каталога составляет порядка микросекунд, вам нужно будет сделать не менее 1000 readdirвызовов, чтобы эти коэффициенты были переведены в одну мкс, но тогда стоимость сканирования составляет 340 мкс, а накопленная 1 дополнительная мкс равна примерно 0,3% от этого --незначительного эффекта. Встраивание этихreaddir(таким образом устраняет накладные расходы на вызовы и накладные расходы PLT )только для расширения кода, но это не сильно улучшит производительность, поскольку getdentsявляется здесь очень узким местом.

(readdir_rдороже из-за дополнительной блокировки, но вам не нужно readdir_r, потому что обычные вызовы readdirобычно являются потокобезопасными -, если только у вас нет нескольких потоков, вызывающих их на ] тот же поток каталога . POSIX, возможно, еще не говорит об этом явно, но я считаю, что эта гарантия должна быть стандартизирована в ближайшее время, учитывая, что glibc зашел так далеко, что объявил readdir_rустаревшим.)

3
27.01.2020, 21:18

Is there any specific explanation for why a "direct kernel call" would be measurably faster

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

http://be-n.com/spw/you-can-list-a-million-files-in-a-directory-but-not-with-ls.html

В большинстве случаев объем буферизации, используемый glibc, не вызывает никаких проблем. Указание на эту крайность как на оправдание обхода обычного кода буферизации может привести к вызовам «преждевременной оптимизации» или аналогичному раздражению :-).

https://github.com/BurntSushi/walkdir/issues/108


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

https://lore.kernel.org/lkml/20061229171654.e6e1b1c7.akpm@osdl.org/T/#u

ext4 _readdir ()не был изменен, чтобы удовлетворить разглагольствования Линуса. Я также не вижу желаемого им подхода, используемого в readdir ()других файловых систем. Я думаю, что XFS использует (физически индексированный )буферный кеш для каталогов [по крайней мере, это означает, что он не может не воспользоваться основной реализацией упреждающего чтения, если каталог фрагментирован]. bcachefs вообще не использует кэш страниц для readdir (); он использует свой собственный кеш для btrees. Я мог что-то упустить в btrfs.

1
27.01.2020, 21:18

Теги

Похожие вопросы