Linux increase stack size

Размер стека процесса, можно ли увеличить?

ulimit -a говорит что размер стека процесса не может превышать 8ми мегабайт.

Есть ли способы увеличить размер стека процесса доступные из под контекста обычного пользователя (без всяких настроек через su, и тем более без перекомпиляции чего-либо системного)

В виндоуз 64битной, по умолчанию размер стека 1мб, но при потребности (если прога скомпилирована с соответствующим ключом) — то можно нарастить стековое пространство до 1гигабайта

Есть ли что-то похожее в linux? (да, понятное дело что то что не влазит — можно в кучу перенести, но код не мой, а задачу хотелось бы решить с минимумом правок оригинального кода, который в винде работает, а в лине переполняет стек)

Не работает такое на Linux. Как я понял, этот ключ работает на Windows.

Но зато перечитал ключи для gcc и нашел -fsplit-stack

С ним стек стал больше. 1 гигабайт по крайней мере работает. Только для linux.

ulimit -s unlimited

На openvz каком-нить ругнется — мол, хер вам, жрите 8 Мбайт.

Просто интересно — это кто-то пишет ПО, которое на размер стэка завязано используя какие-то особые техники оптимизации и построения архитектуры ПО?

Видимо, всякие go поделия легко могут на такое дело ругаться.

Видал я, как тип в процессинге транзакций финансовых, свои потоки со скуки запилил. Я думал, вдруг это какой то полезный тренд?

Да и в go наверное всё же как во всяких доморощенных корутинах, весь стек на куче, со своим планировщиком в юзерспейсе не?

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

И вот в этом коде за раз (в конструкторе объекта) выделяется на стеке три массива длинной в WCHAR_MAX (WCHAR_MAX == 2147483647). При этом два из массивов состоят из элементов длинной 4 байта, а один — состоит из элементов, где каждый имеет размер в 16 байт.

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

Причем перенеся в кучу в линуксе всеравно на таких объёмных массивах крошится в сегфолт. Что пробовал я ключи компиляции которые подсказали выше, что задавать unlim на стек через

В итоге я просто от фонаря поделил WCHAR_MAX на 8 и этого уже хватило и для того что бы не падало и для работы алгоритма на тестовом множестве данных.

Алгоритмика там сложная (для меня) вряд ли буду вникать, нужны ли им такие объемы или нет, просто на днях сделаю туда класс обёртку над массивами, чтобы внешне класс был как обычный массив, но выход за индексы выделял бы новую память — т.е. чисто по потребности выделял а не сразу огромную кучу.

Источник

Что такое Stack Size (размер стека) в UNIX-like

Понятие «стека» (Stack) имеет довольно обширное понятие в вычислительной технике. Существуют такие виды стеков как «Программный стек», «Аппаратный стек» и «Сетевой стек», но Stack Size (размер стека) обычно подразумевает тематику именно «Программного стека» и имеет прямое отношение к оперативной памяти.

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

Обычно в Linux Stack Size (размер стека) равен 10240 kb (10M), управляется конфигурационным файлом /etc/security/limits.conf и командой ulimit -s StackSize , где StackSize размер в kb.

Существует также понятие soft (мягкий) лимит и hard (жесткий) лимит на размер стека. Когда достигнут предел soft (мягкий) лимита, то приложению будет позволено увеличить размер стека до планки hard лимита. По-умолчанию жесткий лимит в Linux не ограничен, проверить можно командой:

Читайте также:  Как установить yum kali linux

Многие программы обычно способны к расширению стека (stack expansion), но в некоторых случаях расширение стека может быть невозможно, что может послужить причиной завершения приложения с многочисленными ошибками.

Для примера чувствительных к размеру стека приложений можно взять веб-сервер Apache с его модулем mod_fcgid и вики-движок MediaWiki. Так например в описании директивы ThreadStackSize веб-сервера Apache сказано, что в большинстве случаев размер стека определённый операционной системой является разумным, но в некоторых случаях требует корректировки:

  • На платформах (например, HP-UX), с относительно небольшим размером стека может произойти сбой в работе сторонних модулей Apache. В таком случае увеличение размера стека через параметр ThreadStackSize может решить проблему.
  • На платформах с довольно большим размером стека по умолчанию, снижение размера стека через параметр ThreadStackSize можно снизить расход оперативной памяти.

Для нормальной работы вики-движка MediaWiki есть особые рекомендации для веб-сервера Apache, включая требования к StackSize не ниже чем 8М.

Параметры ядра на StackSize можно изменять, но в разумных пределах и с контролем влияния настройки на общую производительность отдельно взятой машины имхо популярный в сети Интернет способ экономии РАМы за счёт размера стека не всегда может дать положительный результат.

Уменьшение размера стека (StackSize) безусловно снизит общее потребление оперативной памяти, но в вместе с тем может снизить стабильность системы и не обязательно даст желаемый прирост производительности. Если хоть на один байт размер стека окажется меньше необходимого, то некоторые процессы могут обрываться с многочисленными ошибками.

Кроме стабильности нужно помнить и о безопасности. Приложение, которое работает на сервере может быть хорошо защищено само по себе, но экспериментами с параметрами стека мы можем широко распахнуть дверь перед злоумышленниками.

Рекомендуемый контент

А тут же ж мог быть рекомендуемый контент от гугла 🙂 Для отображения рекомендуемого контента необходимо в браузере разрешить выполнение JavaScript скриптов, включая скрипты с доменов googlesyndication.com и doubleclick.net

Вы не любите рекламу!? Напрасно!:) На нашем сайте она вовсе ненавязчивая, а потому для нашего сайта можете полностью отключить AdBlock (uBlock/uBlock Origin/NoScript) и прочие блокировщики рекламы! AdBlock/uBlock может препятствовать нормальной работе системы поиска по сайту, отображению рекомендуемого контента и прочих сервисов Google. Рекомендуем полностью отключить блокировщик рекламы и скриптов, а также разрешить фреймы (aka iframe).

Источник

Настройка сетевого стека Linux для высоконагруженных систем

Максимизируем количество входящих соединений

Приглашаем всех желающих посетить открытый демо-урок «Практикум по написанию Ansible роли». На этом вебинаре участники вместе с экспертом будут писать, тестировать и отлаживать ansible роли. Это важно для тех, кто хочет автоматизировать настройку инфраструктуры, поскольку это один из инструментов, который это позволяет сделать. Сетевой стек — одна из самых запутанных вещей в Linux. И не только из-за сложности некоторых концепций и терминов, но и из-за изменения смысла некоторых параметров в разных версиях ядра. В этой статье приведена информация для ядра 2.2 и выше, а также, там где это возможно, указано различие между версиями вплоть до 5.5.

Очередь приема и netdev_max_backlog

Каждое ядро процессора перед обработкой пакетов сетевым стеком может хранить их в кольцевом буфере. Если буфер заполняется быстрее, чем TCP-стек обрабатывает пакеты, то пакеты отбрасываются и увеличивается счетчик отброшенных пакетов (dropped packet counter). Для увеличения размера очереди следует использовать параметр net.core.netdev_max_backlog .

net.core.netdev_max_backlog — параметр задается на ядро процессора.

Очередь ожидающих запросов на соединение и tcp_max_syn_backlog

Соединения создаются для SYN-пакетов из очереди приема и перемещаются в очередь ожидания (SYN Backlog Queue). Также соединение помечается как «SYN_RECV» и клиенту отправляется «SYN+ACK». Эти соединения не перемещаются в очередь установленных соединений ожидающих обработки accept() (accept queue) до тех пор, пока не будет получен и обработан соответствующий ACK. Максимальное количество соединений в этой очереди устанавливается параметром net.ipv4.tcp_max_syn_backlog .

Для просмотра очереди приема используйте команду netstat . На правильно настроенном сервере при нормальной нагрузке значение не должно быть больше 1. При большой нагрузке значение должно быть меньше размера очереди ожидания (SYN Backlog):

Если в состоянии «SYN_RECV» находятся много соединений, то можно также подстроить продолжительность нахождения SYN-пакета в этой очереди.

Если SYN cookie отключены, то клиент просто повторяет отправку SYN-пакета. Если включены (net.ipv4.tcp_syncookies), то соединение не создается и не помещается в SYN backlog, но клиенту отправляется SYN+ACK так, как если бы это было сделано на самом деле. SYN cookie могут быть полезны при нормальной нагрузке, но при всплесках трафика некоторая информация о соединении может быть потеряна и клиент столкнется с проблемами, когда соединение будет установлено. Подробнее о SYN cookie можно прочитать в статье Грэма Коула (Graeme Cole) SYN cookies ate my dog (SYN cookie съели мою собаку), в которой подробно объясняется, почему включение SYN cookie на высоконагруженных серверах может привести к проблемам.

Читайте также:  Низкая скорость ssd linux

Повторы SYN+ACK

Что происходит, если SYN+ACK отправлен, но ответа ACK нет? В этом случае сетевой стек сервера повторит отправку SYN+ACK. Задержка между попытками вычисляется таким образом, чтобы обеспечить восстановление сервера. Если сервер получает SYN и отправляет SYN+ACK, но не получает ACK, то тайм-аут повторной передачи вычисляется по экспоненте (Exponental Backoff) и, следовательно, зависит от количества повторных попыток. Количество повторных попыток отправки SYN+ACK задается параметром ядра net.ipv4.tcp_synack_retries (по умолчанию равно 5). Повторные попытки будут через следующие интервалы: 1с, 3с, 7с, 15с, 31с. При шести попытках последняя будет примерно через 63 секунды после первой. Это позволяет удержать SYN-пакет в очереди ожидания более 60 секунд до истечения времени ожидания пакета. Если очередь SYN backlog мала, то не требуется большого количества соединений, чтобы возникла ситуация, когда полуоткрытые соединения никогда не завершатся и тогда никакие соединения не смогут быть установлены. Установите количество повторных попыток SYN+ACK равным 0 или 1, чтобы избежать такого поведения на высоконагруженных серверах.

Повторы SYN

Несмотря на то что повторные SYN-пакеты отправляются клиентом во время ожидания SYN+ACK, они могут влиять и на высоконагруженные серверы, работающие с прокси-соединениями. Например, сервер nginx, устанавливающий несколько десятков прокси-соединений к бэкенд-серверу, из-за всплесков трафика может на некоторое время перегрузить сетевой стек, а повторные попытки создадут дополнительную нагрузку на бэкэнд как в очереди приема, так и в очереди ожидания (SYN backlog). Это, в свою очередь, может повлиять на клиентские соединения. Повторные попытки SYN контролируются параметром net.ipv4.tcp_syn_retries (по умолчанию 5 или 6 в зависимости от дистрибутива). Ограничьте количество повторных попыток SYN до 0 или 1, чтобы не было долгих повторных попыток отправки в течение 63–130 с.

Более подробно о проблемах с клиентскими соединениями при обратном прокси-сервере читайте в статье Linux Kernel Tuning for High Performance Networking: Ephemeral Ports.

Очередь установленных соединений ожидающих принятия (accept queue) и somaxconn

Очередь запросов на соединение создает приложение, используя listen() и указывая размер очереди в параметре «backlog». Начиная с ядра 2.2 поведение этого параметра изменилось с максимального количества неоконченных запросов на соединение, которое может удерживать сокет, на максимальное количество полностью установленных соединений, ожидающих, пока они будут приняты. Как описано выше, максимальное количество неоконченных запросов на соединение теперь задается с помощью параметра ядра net.ipv4.tcp_max_syn_backlog .

somaxconn и параметр backlog в listen()

Хотя за размер очереди для каждого слушателя отвечает приложение, есть ограничение на количество соединений, которые могут находиться в очереди. Размером очереди управляют два параметра: 1) параметр backlog в функции listen() и 2) параметр ядра net.core.somaxconn , задающий максимальный размер очереди.

Значения по умолчанию для очереди

Значение по умолчанию для net.core.somaxconn берется из константы SOMAXCONN, которая в ядрах Linux вплоть до версии 5.3 имеет значение 128, но в 5.4 она была увеличена до 4096. Однако, на момент написания этой статьи, ядро 5.4 еще не очень распространено, поэтому в большинстве систем значение будет 128, если вы не модифицировали net.core.somaxconn.

Часто приложения для размера очереди по умолчанию используют константу SOMAXCONN, если этот размер не задается в конфигурации приложения. Хотя некоторые приложения устанавливают и свои значения по умолчанию. Например, в nginx размер очереди равен 511, который автоматически усекается до 128 в ядрах Linux до версии 5.3.

Изменение размера очереди

Многие приложения позволяют указывать размер очереди в конфигурации, указывая значение параметра backlog для listen() . Если приложение вызывает listen() со значением backlog , превышающим net.core.somaxconn, то размер очереди будет автоматически усечен до значения SOMAXCONN.

Потоки

Если очередь большая, то подумайте также об увеличении количества потоков, которые обрабатывают запросы в приложении. Например, установка для nginx очереди ожидания в 20480 для HTTP-listener без достаточного количества worker_connections для управления очередью приведет к тому, что сервер будет отказываться отвечать на запросы на установку соединения.

Соединения и файловые дескрипторы

Системные ограничения

Любое сокетное соединение использует файловый дескриптор. Максимальное количество дескрипторов, которые могут быть созданы в системе, задается параметром ядра fs.file-max. Посмотреть количество используемых дескрипторов можно следующим образом:

Вывод показывает, что используется 1976 файловых дескрипторов. Выделено, но не используется 12 (для ядер 2.6+), а максимальное количество — 2048. В высоконагруженной системе значение должно быть достаточно большим, чтобы справиться как с большим количеством соединений, так и с потребностями в файловых дескрипторах других процессов.

Читайте также:  Wimax bpenum windows 10 64 bit

Пользовательские ограничения

Помимо системного ограничения количества файловых дескрипторов, у каждого пользователя есть свои лимиты. Они настраиваются в системном файле limits.conf (nofile) или, при запуске процесса под управлением systemd, в unit-файле systemd (LimitNOFILE). Чтобы увидеть значение по умолчанию запустите:

Для systemd (на примере nginx):

Настройка

Для настройки системных ограничений установите параметр ядра fs.max-file в максимальное количество файловых дескрипторов, которое может быть в системе (с учетом некоторого буфера). Например:

Для настройки пользовательского лимита установите достаточно большое значение, чтобы хватило сокетам и файловым дескрипторам рабочих процессов (также с некоторым буфером). Пользовательские ограничения устанавливаются в /etc/security/limits.conf, в conf-файле в /etc/security/limits.d/ или в unit-файле systemd. Например:

Количество worker’ов

Аналогично файловым дескрипторам, количество worker’ов или потоков, которые может создать процесс, ограничено как на уровне ядра, так и на уровне пользователя.

Системные ограничения

Процессы могут создавать рабочие потоки. Максимальное количество потоков, которые могут быть созданы, задается параметром ядра kernel.threads-max . Для просмотра максимального и текущего количества потоков, выполняющихся в системе, запустите следующее:

Пользовательские ограничения

Есть свои ограничения и у каждого пользовательского процесса. Это также настраивается с помощью файла limits.conf (nproc) или unit-файла systemd (LimitNPROC). Для просмотра максимального количества потоков, которое может создать пользователь запустите:

Для systemd (на примере nginx):

Настройка

В большинстве случаев системные ограничения достаточно большие, чтобы справиться с высокой нагрузкой. Однако их можно настроить через параметр ядра kernel.threads-max . Установите его значение в максимальное количество потоков, необходимых системе, плюс некоторый буфер. Например:

Как и в случае с nofile , ограничения для пользователей ( nproc ) устанавливаются в /etc/security/limits.conf, в conf-файле в /etc/security/limits.d/ или в unit-файле systemd. Пример с nproc и nofile :

Обратный прокси и TIME_WAIT

При большом всплеске трафика прокси-соединения, застрявшие в «TIME_WAIT», суммарно могут потреблять много ресурсов при закрытии соединения. Это состояние говорит, что клиент получил последний FIN-пакет от сервера (или вышестоящего worker’а) и находится в ожидании для корректной обработки пакетов. Время нахождения соединения в состоянии «TIME_WAIT» по умолчанию составляет 2 x MSL (Maximum Segment Length — максимальная длина сегмента), что составляет 2 x 60 с. В большинстве случаев это нормальное и ожидаемое поведение, и значение по умолчанию в 120 с вполне приемлемо. Однако много соединений в состоянии «TIME_WAIT» может привести к тому, что приложение исчерпает эфемерные порты для соединений к клиентскому сокету. В этом случае следует уменьшить FIN тайм-аут.

Управляет этим тайм-аутом параметр net.ipv4.tcp_fin_timeout . Рекомендуемое значение для высоконагруженных систем составляет от 5 до 7 секунд.

Собираем все вместе

Очередь приема (receive queue) должна быть рассчитана на обработку всех пакетов, полученных через сетевой интерфейс, не вызывая отбрасывания пакетов. Также необходимо учесть небольшой буфер на случай, если всплески будут немного выше, чем ожидалось. Для определения правильного значения следует отслеживать файл softnet_stat на предмет отброшенных пакетов. Эмпирическое правило — использовать значение tcp_max_syn_backlog, чтобы разрешить как минимум столько же SYN-пакетов, сколько может быть обработано для создания полуоткрытых соединений. Помните, что этот параметр задает количество пакетов, которое каждый процессор может иметь в своем буфере, поэтому разделите значение на количество процессоров.

Размер SYN очереди ожидания (SYN backlog queue) на высоконагруженном сервере должен быть рассчитан на большое количество полуоткрытых соединений для обработки редких всплесков трафика. Здесь эмпирическое правило заключается в том, чтобы установить это значение, по крайней мере, на максимальное количество установленных соединений, которое слушатель может иметь в очереди приема, но не выше, чем удвоенное количество установленных соединений. Также рекомендуется отключить SYN cookie, чтобы избежать потери данных при больших всплесках соединений от легитимных клиентов.

Очередь установленных соединений, ожидающих принятия (accept queue) должна быть рассчитана таким образом, чтобы в периоды сильного всплеска трафика ее можно было использовать в качестве временного буфера для установленных соединений. Эмпирическое правило — устанавливать это значение в пределах 20–25% от числа рабочих потоков.

Параметры

В этой статье были рассмотрены следующие параметры ядра:

И следующие пользовательские ограничения:

Заключение

Все параметры в этой статье приведены в качестве примеров и не должны вслепую применяться на ваших продакшн-серверах без тестирования. Есть и другие параметры ядра, которые влияют на производительность сетевого стека. Но в целом, это наиболее важные параметры, которые я использовал при настройке ядра для высоконагруженных систем.

Источник

Оцените статью