Тюнинг FreeBSD 7

Опубликовано admin в Вс, 21/06/2009 - 17:42
Статья взята с dadv.livejournal.com (_http://dadv.livejournal.com/49013.html).

Видеозапись (_http://rootconf.ru/papers2009/12568.html) лекции Игоря Сысоева по настройке некоторых подсистем FreeBSD 7 (44 минуты 30 секунд). Квинтэссенция:

  • открытый TCP-сокет суммарно потребляет порядка 1800 байт в ядре и, выставляя sysctl kern.ipc.maxsockets=100000, мы позволяем ядру занять более 170Mb только под хранение информации об открытых сокетах;

    количество открытых в данный момент сокетов можно посмотреть в sysctl kern.ipc.numopensockets;

  • поиск сокета по входящему пакету хешированный с размером хеш-таблицы, изменяемой через /boot/loader.conf параметром net.inet.tcp.tcbhashsize; по умолчанию 512 записей, можно увеличить до 32K для ускорения поиска;
  • очередь установленных TCP-коннектов, ещё не принятых (accept) приложением, имеет размер sysctl kern.ipc.somaxconn (128 по умолчанию); netstat -Lan показывает список этих очередей, включая степень их заполненности;
  • принятый TCP-коннект порождает дескриптор открытого файла, который потребляет 128 байт (итого более 190Mb на 100000 коннектов с учетом 170Mb на сокеты);

    общее количество открытых файлов в системе ограничивает sysctl kern.maxfiles, а текущее показывает sysctl kern.openfiles;

    плюс имеется ограничение на количество открытых файлов на процесс sysctl kern.maxfilesperproc;

    плюс могут быть ещё ограничения в самом приложении (а также внутренний расход памяти приложения на каждый файл);

  • данные, приходящие из сети в сокет, попадают в ядерные буфера mbuf (256 байт) и mbuf cluster (2Kb) (связный набор буферов mbuf, в сумме хранящий все данные пакета);

    выставляя sysctl kern.ipc.nmbclusters=100000, разрешаем ядру использовать под эти буфера дополнительно более 207Mb (2048+256 байт на каждый кластер и прилагающийся с нему дополнительный служебный mbuf);

  • в один сокет может прийти до sysctl net.inet.tcp.recvspace данных, не принятых ещё приложением - они потребляют упомянутые выше буфера;

    в FreeBSD 7 есть (отключаемый) механизм автоувеличения этого параметра (sysctl net.inet.tcp.recvbuf_auto, описание см. ниже на примере net.inet.tcp.sendbuf_auto);

  • начиная с FreeBSD 7 отправляемые приложением в сеть данные потребляют mbuf и mbuf clusters размером по странице (4K для i386) и не используют двухкилобайтные nmbclusters (см. выше);

    количество четырехкилобайтных кластеров, используемых для отправки, ограничивается через sysctl kern.ipc.nmbjumbop, по умолчанию 12800; на 100000 их потребуется более 488Mb ядерной памяти (128+4096 байт на каждый);

  • исходящие данные одного сокета могут занять в ядерной памяти до sysctl net.inet.tcp.sendspace байт и при медленно принимающих клиентах и неправильных настройках этого параметра и kern.ipc.nmbjumbop буфера на отправку могут исчерпаться (медленные клиенты могут устроить DoS), причем в FreeBSD 7 по умолчанию включено автоувеличение этого буфера для быстрых клиентов (sysctl net.inet.tcp.sendbuf_auto=1), но до обрыва соединения невозможно освободить выросший буфер, если быстрый клиент вдруг прекратит приём;

    автоинкремент идет порциями по net.inet.tcp.sendbuf_inc, максимальный размер буфера задаёт net.inet.tcp.sendbuf_max;

  • закрытое сервером соединение ожидает подтверждения закрытия от клиента, потребляя меньше памяти, чем открытое;

    таких соединений может быть до sysctl net.inet.tcp.maxtcptw (часть от kern.ipc.maxsockets, поэтому такие сокеты мешают открытию новых);

    однако, если приложение не предпринимает специальных мер (ограничение linger-таймаута), то после закрытия сокета довольно длительное время буфера могут оставаться занятыми данными, для которых не было получено подтверждения приёма от клиента;

  • начиная с версии 7.2/amd64 размер ядерной памяти по умолчанию равен четверти физической памяти, но не более 3.6Gb (ранее предел был чуть более 1.5Gb);

    этот размер можно увеличить до двух размеров физической памяти в /boot/loader.conf параметром vm.kmem_size, например: vm.kmem_size=3G

  • максимальный размер файлового кеша ограничивается лимитом на количество кешируемых файлов sysctl kern.maxvnodes (не более 100000 по умолчанию) и при большом объеме памяти и недостаточном значении kern.maxvnodes память может не использоваться эффективно под кеш, если файлы мелкие и их очень много;
  • пакеты, приходящие через драйвер сетевой карты, могут обрабатываться сразу при sysctl net.isr.direct=1, либо сначала укладываться в очередь при нулевом значении этого параметра;

    размер очереди задаётся через sysctl net.inet.ip.intr_queue_maxlen (можно поставить и 2048, и 4096); при использовании очереди и её переполнении пакет выкидывается;

  • top -S показывает потребление процессора системными тредами и при net.isr.direct=0 можно увидеть отдельно процент процессорного времени, затрачиваемый на обработку пакетов сетевым стеком уже без участия драйвера сетевой карты - при включенной очереди вся обработка выполняется одним тредом и не распараллеливается;

    распараллеливание можно получить, отключив очередь и принимая трафик несколькими сетевыми картами;

    файрволы (пакетные фильтры) мешают параллельной обработке пакетов своими блокировками на этапе проверки правил;

  • установка sysctl kern.ipc.shm_use_phys=1 при использовании приложений, активно потребляющих SYSV Shared Memory (СУБД), экономит ядерную память и запрещает вытеснение такой разделяемой памяти в своп;
  • использование версии 7.2 позволяет использовать сегменты разделяемой памяти SYSV размером более 2Gb и автоматически (прозрачно для приложений) использовать 4-мегабайтные страницы вместо 4-килобайтных, уменьшая размер системных таблиц и количество промахов процессорного кеша, увеличивая таким образом общее быстродействие системы.
( categories: )