мая 15 2009 11:37 пп

Оптимизация TCP/IP стека в Linux, FreeBSD, Mac Os X и других операционных системах

Connect2Internet-Icon-Akkasone.jpg

Данная инструкция предназначена для описания действий по оптимизации параметров протокола TCP.

TCP использует параметр, который называют «congestion window», или CWND, чтобы определить, сколько пакетов можно послать в конечную единицу времени. Чем больший размер congestion window, тем выше пропускная способность. Размер congestion window определяется с помощью алгоритмов TCP «slow start» и «congestion avoidance». Максимальное значение congestion window зависит от объема буфера, назначенного ядром для каждого сокета. Для каждого сокета имеется значение размера буфера, установленное по умолчанию, которое можно изменить программно, используя системный вызов из библиотек прежде, чем будет открыт данный сокет. Так же имеется параметр, задающий максимальный размер буфера ядра. Изменить можно размер как передающего, так и принимающего буфера сокета.

Чтобы получить максимальную пропускную способность, необходимо использовать оптимально установленный размер передающего и принимающего буферов сокета для канала, который вы используете. Если буфера будут слишком маленькими, то congestion window никогда не будет полностью открываться. Если передающий буфер слишком большой, то возможны разрывы управления потоком данных TCP и отправитель может переполнить буфер получателя, что заставит уменьшить окно TCP. Это, вероятно, случится быстрее на хосте-отправителе, чем на хосте-получателе. Чрезмерно большой принимающий буфер — не самая большая проблема, пока у вас есть лишняя память.

Оптимальный размер буфера можно посчитать как пропускная способность*задержку используемого канала.

buffer size = 2 * bandwidth * delay

Для определения задержки может быть использована утилита ping или инструментарий типа pathrate для определения емкости канала от точки А до точки В (если пропускная способность между точками переменная). Так как утилита ping дает время прохождения пакета туда и обратно (RTT), то вместо предыдущей может быть использована следущая формула:

buffer size = bandwidth * RTT

Для примера, если ping показывает 50 ms, и от точки А до точки В используются каналы 100 BT Ethernet и OC3 (155 Mbps), значение буферов TCP составит .05 sec * (100 Mbits / 8 bits) = 625 KBytes. (Если вас гложут сомнения, то 10 MB/s будет хорошим первым приближением для сетей ESnet/vBNS/Abilene-like).

Есть 2 параметра настройки TCP, о которых Вы должны знать. Это размер буферов приема/отправки по умолчанию и максимальный размер буферов приема/отправки. Отметьте, что у большинства современных UNIX OS максимальный размер буфера по умолчанию только 256 Кбайт! Ниже мы покажем, как изменить это значение в большинстве современных ОС. Вы врядли захотите увеличить заданный по умолчанию размер буфера, на значение больше чем 128 Кбайт, потому что это может неблагоприятно повлиять на производительность локальной сети. Поэтому вы должны использовать UNIX вызов setsockopt для буферов приема/отправки, чтобы установить оптимальный размер буфера для канала, который вы используете.

Linux

Есть большие отличия между версиями Linux 2.4 и 2.6, но мы сейчас рассмотрим общие вопросы. Чтобы изменить параметры настройки TCP, вам необходимо добавить строки, представленные ниже, к файлу /etc/sysctl.conf и затем выполнить команду sysctl -p.

Как и во всех прочих ОС, размер буферов в Linux очень мал. Применим следущие настройки:

# increase TCP max buffer size setable using setsockopt()
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# increase Linux autotuning TCP buffer limits
# min, default, and max number of bytes to use
# set max to at least 4MB, or higher if you use very high BDP paths
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

Вы должны также проверить, что следующие параметры установлены в значение по умолчанию, равное 1.

sysctl net.ipv4.tcp_window_scaling
sysctl net.ipv4.tcp_timestamps
sysctl net.ipv4.tcp_sack

Отметьте: Вы должны оставить tcp_mem в покое. Значения по умолчанию и так прекрасны.

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

ifconfig eth0 txqueuelen 1000

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

Также, по слухам, может помочь в увеличении пропускной способности утилита ‘tc’ (traffic control)

Linux 2.4

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

Однако, у Linux 2.4 есть другая странность, о которой нужно знать. Например: значение ssthresh для данного пути кэшируется в таблице маршрутизации. Это означает, что, если подключение осуществляет повторную передачу и уменьшает значение окна, то все подключения с тем хостом в течение следующих 10 минут будут использовать уменьшенный размер окна, и даже не будут пытаться его увеличить. Единственный способ отключить это поведение состоит слкдующем (с правами пользователя root):

sysctl -w net.ipv4.route.flush=1

Дополнительную информацию можно получить в руководстве Ipsysctl.

Linux 2.6

Начинаясь с Linux 2.6.7 (с обратным портированием на 2.4.27), linux включает в себя альтернативные алгоритмы управления перегрузкой, помимо традиционного ‘reno’ алгоритма. Они разработаны таким образом, чтобы быстро оправиться от потери пакета на высокоскоростных глобальных сетях.

Linux 2.6 также включает в себя алгоритмы автоматической оптимизации буферов принимающей и отправляющей стороны. Может применяться тоже решение, чтобы устранить странности ssthresh кэширования, что описанно выше.

Есть пара дополнительных sysctl параметров настройки для 2.6:

# don't cache ssthresh from previous connection
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_moderate_rcvbuf = 1
# recommended to increase this for 1000 BT or higher
net.core.netdev_max_backlog = 2500
# for 10 GigE, use this
# net.core.netdev_max_backlog = 30000

Начиная с версии 2.6.13, Linux поддерживает подключаемые алгоритмы управления перегрузкой. Используемый алгоритм управления перегрузки можно задать, используя sysctl переменную net.ipv4.tcp_congestion_control, которая по умолчанию установлена в cubic or reno, в зависимости от версии ядра.

Для получения списка поддерживаемых алгоритмов, выполните:

sysctl net.ipv4.tcp_available_congestion_control

Выбор опций контроля за перегрузкой выбирается при сборке ядра. Ниже представлены некоторые из опций, доступных в 2.6.23 ядрах:

* reno: Традиционно используется на большинстве ОС. (default)
* cubic:CUBIC-TCP (Внимание: Есть бага в ядре Linux 2.6.18. Используйте в 2.6.19 или выше!)
* bic:BIC-TCP
* htcp:Hamilton TCP
* vegas:TCP Vegas
* westwood:оптимизирован для сетей с потерями

Для очень длинных и быстрых каналов я предлагаю пробовать cubic или htcp, если использование reno желательно. Чтобы установить алгоритм, сделайте следующее:

sysctl -w net.ipv4.tcp_congestion_control=htcp

Дополнительную информацию по алгоритмам и последствиям их использования можно посмотреть тут.

Вниманию использующих большие MTU: если вы сконфигурировали свой Linux на использование 9K MTU, а удаленная сторона использует пекеты в 1500 байт, то вам необходимо в 9/1.5 = 6 раз большее значение буферов, чтобы заполнить канал. Фактически, некоторые драйверы устройств распределяют память в зависимости от двойного размера, таким образом Вы можете даже нуждаться в 18/1.5 = в 12 раз больше!

И наконец предупреждение и для 2.4 и для 2.6: для очень больших BDP путей, где окно > 20 MB, вы вероятно столкнетесь с проблемой Linux SACK. Если в «полете» находится слишком много пакетов и наступает событие SACK, то обработка SACKed пакета может превысить таймаут TCP и CWND вернется к 1 пакету. Ограничение размера буфера TCP приблизительно равно 12 Мбайтам, и кажется позволяет избежать этой проблемы, но ограничивает вашу полную пропускную способность. Другое решение состоит в том, чтобы отключить SACK.

Linux 2.2

Если вы используете Linux 2.2, обновитесь! Если это не возможно, то добавьте следущее в /etc/rc.d/rc.local:

echo 8388608 > /proc/sys/net/core/wmem_max
echo 8388608 > /proc/sys/net/core/rmem_max
echo 65536 > /proc/sys/net/core/rmem_default
echo 65536 > /proc/sys/net/core/wmem_default

FreeBSD

Добавьте это в /etc/sysctl.conf и перезагрузитесь:

kern.ipc.maxsockbuf=16777216
net.inet.tcp.rfc1323=1

В FreeBSD 7.0 добавлена функция автокогфигурирования буферов. Но значения их можно отредактировать, так как по умолчанию буферы 256 KB, а это очень мало:

net.inet.tcp.sendbuf_max=16777216
net.inet.tcp.recvbuf_max=16777216

Для общего развития покажу еще несколько параметров, но их дефолтные значения и так хороши:

net.inet.tcp.sendbuf_auto=1 # Send buffer autotuning enabled by default
net.inet.tcp.sendbuf_inc=8192 # step size
net.inet.tcp.recvbuf_auto=1 # enabled
net.inet.tcp.recvbuf_inc=16384 # step size

У FreeBSD есть кое-какие ограничения, включенным по умолчанию. Это хорошо для модемных подключений, но может быть вредно для пропускной способности на высокоскоростных каналах. Если Вы хотите «нормальное» TCP Reno, сделайте следущее:

net.inet.tcp.inflight.enable=0

По умолчанию, FreeBSD кэширует подробности подключения, такие как порог slow start и размер окна перегрузки(congestion windows) с предыдущего подключения на тот же самый хост в течение 1 часа. В то время как это хорошая идея для веб-сервера, но плохая для тестирования пропускной способности, поскольку 1 большой случай перегрузки задушит производительность в течение следующего часа. Чтобы уменьшить этот эффект, установите это:

net.inet.tcp.hostcache.expire=1

В этом случае мы будем все еще кэшировать значения в течение 5 минут, по причинам, описанным в этой статье от Centre for Advanced Internet Architectures (CAIA) at Swinburne University in Autralia. В ней вы также найдете другую интересную информацию о тюнинге FreeBSD. Также можно использовать H-TCP patch for FreeBSD

Для получения информации о тюнинге NetBSD, обратитесь к этой статье.

Внимание: у FreeBSD версий ниже 4.10 нет реализации SACK, что сильно снижает ее производительность по сравнению с другими операционными системами. Вы необходимо обновиться до 4.10 или выше.

Solaris

Для Solaris просто сделайте загрузочный скрипт (например, /etc/rc2.d/S99ndd) следующего содержания:

#!/bin/sh
# increase max tcp window
# Rule-of-thumb: max_buf = 2 x cwnd_max (congestion window)
ndd -set /dev/tcp tcp_max_buf 4194304
ndd -set /dev/tcp tcp_cwnd_max 2097152

# increase DEFAULT tcp window size
ndd -set /dev/tcp tcp_xmit_hiwat 65536
ndd -set /dev/tcp tcp_recv_hiwat 65536

Для получения дополнительной информации, обратитесь к документации Solaris

Windows XP

Самый простой способ настроить TCP под Windows XP состоит в том, чтобы получить DrTCP из «DSL Reports». Установите «Tcp Receive Window» в вычесленное значение BDP (e.g. 4000000), включите «Window Scaling» «Selective Acks» и «Time Stamping».

Провести дополнительную настройку можно с помощью сторонних утилит, таких как SG TCP Optimizer и Cablenut.

Для проверки изменений можно воспользоваться редактором реестра. Наша цель — вот эти параметры:

# turn on window scale and timestamp option
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Tcp1323Opts=3
# set default TCP receive window size
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpWindowSize=256000
# set max TCP send/receive window sizes (max you can set using setsockopt call)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\GlobalMaxTcpWindowSize=16777216

Вы можете использовать setsockopt() для программного изменения значения буферов до размера GlobalMaxTcpWindowSize, или можете использовать TcpWindowSize для задания значения буферов по умолчанию всех сокетов. Второй вариант может быть плохой идеей, если у вас мало памяти.

Для получения дополнительной информации, обратитесь к документам Windows network tuning, TCP Configuration Parameters, TCP/IP Implementation Details и Windows 2000/XP Registry Tweaks

Windows Vista

Хорошая новость! У Windows Vista имеется автонастройка TCP. Максимальный размер окна может быть увеличен до 16 MB. Если вы знаете, как сделать его больше. Дайте мне знать.

Vista также включает в себя «Compound TCP (CTCP)», что очень похоже на cubic в Linux. Для задействования этого механизма, необходимо выполнить:

netsh interface tcp set global congestionprovider=ctcp"

Если вы хотите включить/выключить автонастройку, выполните следующие команды:

netsh interface tcp set global autotunninglevel=disabled
netsh interface tcp set global autotunninglevel=normal

Внимание, команды выполняются с привилегиями Администратора.

Нет возможности увеличить значение буферов по умолчанию, которое составляет 64 KB. Также, алгоритм автонастройки не используется, если RTT не больше чем 1 ms, таким образом единственный streamTCP переполнит этот маленький заданный по умолчанию буфер TCP.

Для получения дополнительной информации, обратитесь к следующим документам:

* TCP Receive Window Auto-Tuning in Vista
* Enterprise Networking with Windows Vista
* Why TcpWindowSize does not work in Vista

Mac OSX

Mac OSX настраивается подобно FreeBSD.

sysctl -w net.inet.tcp.win_scale_factor=8
sysctl -w kern.ipc.maxsockbuf=16777216
sysctl -w net.inet.tcp.sendspace=8388608
sysctl -w net.inet.tcp.recvspace=8388608

Для OSX 10.4, Apple также предоставляет патч Broadband Tuner, увеличивающий максимальный размер буферов сокета до 8MB и еще кое-что по мелочи.

Для получения дополнительной информации, обратитесь к OSX Network Tuning Guide.

AIX

Для повышения производительности на SMP системах, выполните:

ifconfig thread

Это позволит обработчику прерываний интерфейов GigE на многопроцессорной машине AIX выполняться в многопоточном режиме.

IRIX

Добавьте в файл /var/sysgen/master.d/bsd такие строки:

tcp_sendspace
tcp_recvspace

Максимальный размер буфера в Irix 6.5 составляет 1MB и не может быть увеличен.

Оригинал статьи: http://fasterdata.es.net/TCP-tuning/
Перевод: Сгибнев Михаил
Источник: http://dreamcatcher.ru/bsd/017_tcp.html





2 комментария »


2 комментария to “Оптимизация TCP/IP стека в Linux, FreeBSD, Mac Os X и других операционных системах”

  1. qw3 on 16 мая 2009 at 06:35 #

    если я правильно понял, это общесистемные настройки, не для каждого интерфейса в отдельности. А как быть если это гетвэй у которого один гигабитный интерфейс смотрящий в локалку а другой — спутниковый модем с задержками в 1500 мс?

  2. Stepanoff on 16 мая 2009 at 11:52 #

    Искать золотую серидину. Ну и почитать более подробные руководства.

Trackback URI | Comments RSS

Leave a Reply

You must be logged in to post a comment.


« | »



Server load average: 0.03, 0.02, 0.00
Server uptime: 20 days, 5:46
Your IP is: 54.225.57.89.