Firefox максимальное число процессов контента. Особенности высоконагруженных WEB систем. Система хранения данных

Старт SLS Block 1 (источник иллюстрации: NASA)

К сожалению, первый старт тяжелой ракеты-носителя Space Launch System (SLS), который был на ноябрь 2018 года (а до этого - на конец 2017), будет перенесен на 2019 год. Пока что команда проекта говорит о возможном запуске ракеты на начало 2019 года, но все может измениться и носитель полетит еще позже.

Перенос старта на более поздний срок - уже решенный вопрос, подтвержденный как научной группой проекта, так и администраторами из Счётной Палаты США. «Мы согласны со Счетной Палатой в плане того, что поддержка плана старта ракеты в 2018 году не та задача, которая должна быть выполнена любой ценой, поэтому сейчас мы в процессе выбора новой даты для 2019 года», - заявил глава NASA по пилотируемым программам Уильям Герстенмейер.

Решение было принято с оглядкой на проблемы различного характера с самой ракетой, аппаратом Orion и стартовой площадкой. По словам Герстенмейера, запуск переносится для того, чтобы у агентства было время исправить все текущие проблемы, которых накопилось немало.

Кстати, изначально НАСА планировала проведение первого полета ракеты, получившего название Exploration Mission-1 (EM-1), в автоматическом режиме. Несколько позже специалисты начали рассматривать возможность осуществления запуска с командой на борту. Об этом НАСА попросил Белый дом.

«Мы признаем, что риск будет повышенным», - говорит Уильям Герстенмейер. - «Мы принимаем этот риск, и хотим сопоставить его с возможными преимуществами».

В связи с планированием первого полета с командой на борту НАСА необходимо провести ряд дополнительных работ. Например, нужно в быстром темпе доработать верхнюю ступень ракеты для пилотируемого полета и добавить систему жизнеобеспечения для астронавтов. Кроме того, необходимо добавить и многие элементы системы жизнеобеспечения в капсулу Orion. «Нам придется разобрать то, что уже сделано и модифицировать систему для добавления системы жизнеобеспечения, которая нужна для полета», - говорит Джейсон Крузан (Jason Crusan) руководитель одного из подразделений НАСА.

Кроме того, 7 февраля в районе сборки ракеты прошел торнадо, который повредил некоторые конструкции самой площадки и ракеты. Ничего особо критичного не произошло, но на ремонт и новую проверку готовности систем требуется время, а также деньги. С деньгами здесь все сложно, поскольку, по мнению агентства, может понадобиться вплоть до полутора миллиардов долларов США.

Проанализировав все эти проблемы, Счетная Палата США совместно с администрацией НАСА пришли к выводу, что к 2018 году команда проекта не управится, так что первый старт придется перенести. Точная новая дата не определена, о чем говорилось выше, но уже ясно, что это будет не 2018 год.

на интересный выпуск Вестника НПО им Лавочкина от февраля 2014 года. В самом его конце очень понравилась статья коллектива авторов (А.Ю.Данилюка, В.Ю.Клюшникова, И.И. Кузнецова и А.С.Осадченко ) об истории развития сверхтяжелых ракето-носителей. Сверхтяжелыми ракетами-носителями обычно называют такие носители, которые способны вывести на околоземную орбиту, как минимум 100 тонн полезной нагрузки. Конечно, обычно такие мощные ракеты создают для пилотируемых полетов к Луне или Марсу , но и конечно, очевидна важность их создания для запусков зондов во внешние области Солнечной Системы или для вывода очень тяжелых космических обсерваторий . Поэтому в этой заметке, я решил резюмировать текущее состояние в этой области в разных странах мира.

В настоящее время не проводятся запуски таких ракет. С некоторой натяжкой, последним запуском такого носителя можно назвать 8 июля 2011 года , когда был совершен последний запуск по программе Спейс Шаттл . С некоторой натяжкой, потому что в таких полетах, орбитальный челнок фактически выполняет роль последней ступени ракеты-носителя и масса выводимой полезной нагрузки на околоземную орбиту при этом ограничена всего 20-30 тоннами. В связи с этим можно сказать, что последний запуск такого типа носителей был фактически производен 15 мая 1987 года , когда с помощью советского ракеты-носителя Энергия , была произведена неудачная попытка вывода на орбиту макета боевой лазерной станции , общим весом 80 тонн.

3 D- модель ракета-носителя Энергия с пристыкованной станцией Полюс или . .

В США же последний подобный запуск был произведен 41 год назад — 14 мая 1973 года . Тогда в последнем запуске Сатурна-5 была запущена орбитальная станция Скайлэб , массой в 77 тонн. Тот запуск тоже был фактически частично неудачным — при запуске станция потеряла теплоизолирующий экран и одну из двух солнечных батарей. После того запуска, космические державы перешли к модульному созданию орбитальных станций. С другой стороны, в настоящее время, целых три страны разрабатывают сверхтяжелые ракеты-носители — Россия , США и Китай .

В России такой проект связан с планами пилотируемых полетов к Луне и Марсу . Для Луны планируется создать до 2030 года носитель, выводящий на околоземную орбиту до 80-90 тонн. Для Марса планируется создать, уже после 2030 года, носитель выводящий на околоземную орбиту до 160-190 тонн. В уже упомянутом Вестнике НПО им Лавочкина приводится несколько вариантов таких носителей. К примеру таких:


Для запусков подобных носителей планируется использовать новый космодром Восточный . Первый запуск с этого космодрома (носителя Союз-2 ) должен произойти в конце 2015 года. С другой стороны, выбор Восточного означает, что всю космическую инфраструктуру под сверхтяжелые носители, там придется создавать с нуля. Это достаточно обидно, учитывая, что на Байконуре в советские годы был создан огромный задел по прошлым подобным носителям, таким как Н1 и Энергия-Буран . Недавно я видел сообщение , что бывший огромный ангар на Байконуре , где готовили к запуску Н1 и Энергию, по прежнему в том же состояние, в котором он был в 2002 году, после обрушения кровли.

Планируемые траектории выведения с космодрома Восточный . .

Теперь перейдем к США . В настоящее время там разрабатывается фактически два разных сверхтяжелых носителя: государственный от NASA и частный от SpaceX . В первом случае носитель появился, как замена программы Спейс Шаттл . Сначала он назывался Арес-5 и разрабатывался для программы Созвездие с целью пилотируемых полетов на Луну . В 2010 году произошел фактически отказ от лунных планов, хотя от разработки сверхтяжелого носителя NASA не отказалось. Проект носителя был существенно изменен и получил название SLS (Space Lauch System ) . Теперь уже предлагается его использовать не для пилотируемых полетов к Луне , а для пилотируемых полетов к астероидами или Марсу . Первый запуск этого носителя ожидается в 2017 году. Существует в разработке два варианта SLS : пилотируемый и грузовой. Первый выводит до 70 тонн на орбиту, второй до 130 тонн.

Крайний справа это грузовой вариант SLS . Слева от него пилотируемый вариант SLS. .

SLS очень широко использует и инфраструктуру, и технологии оставшиеся после программы Спейс Шаттл . К примеру, для сборки будет использоваться тоже здание вертикальной сборки и те же пусковые площадки на мысе Канаверел , что применялись для программы Сатурн-5 и Спейс Шаттл . Ожидается, что первый запуск SLS будет произведен к 2017-2018 году.


Здание вертикальной сборки на мысе Канаверел , в которое с начала этого года перестали пускать туристов, по причине начала подготовки его использования для программы SLS . .

Другим планируемым американским супертяжем является носитель Falcon Heavy от частной компании SpaceX . Его возможности будут скромнее, чем у SLS — только 53 тонны на околоземную и 5 метровый головной обтекатель, в тоже время, он планируется в значительной мере многоразовым. Для запусков на первых порах решено использовать стартовую площадку SLC-4E на космодроме Ванденберг в Калифорнии . Эту площадку до 2005 года использовали военные с целью запусков секретных спутников на полярные орбиты. Ожидается, первый запуск Falcon Heavy случится уже в этом году, но учитывая хронические переносы SpaceX , вероятнее всего его стоит ждать в 2015 году. С другой стороны, скорее всего Falcon Heavy в ближайшие годы станет самым мощным ракета-носителем из существующих, в связи с тем, что реализация всех остальных супертяжей проходит на значительно более ранних этапах развития. И конечно, собственный частный капитал миллиардера Элона Маска позволяет SpaceX меньше зависеть от политических капризов, которые являются бичом государственных космических агентств. Если запуски пройдут успешно, то в будущем NASA обещает разрешить использовать Falcon Heavy для запусков стартовый комплекс на мысе Канаверел под номером 39 , на пару с SLS . В более далекой перспективе у SpaceX существует проект носителя Falcon XX , грузоподъемностью до 130 тонн.


Различные ракеты-носители SpaceX в сравнение с Сатурн-5 . .

И наконец перейдем к Китаю . Как выяснилось в прошлые годы, там тоже разрабатывают сверхтяжелый носитель под названием Великий поход-9 , скорее всего для пилотируемого полета к Луне . Его грузоподъемность оценивается в 130 тонн. Очевидно, что его запуски будут производиться с нового космодрома Вэньчан на острове Хайнань . Прошлые китайские космодромы имели большие проблемы с зонами падения отработанных ступеней в густонаселенных районах. При каждом запуске часто происходят эвакуации многих тысяч местных жителей. Сооружение стартовых комплексов на новом космодроме ведется с 2007 года, первые запуски с него в космос ожидаются в ближайшее время (это будет новая ракета Великий поход-5, которая немного мощнее нашего Протона ).


Будущие китайские ракеты-носители. .

70.000 - 129.000 кг на НОО История запусков Состояние в разработке Места запуска LC-39 , Космический центр Кеннеди Число запусков 0 - успешных 0 - неудачных 0 Первый запуск планируется в конце 2018 Первая ступень - Solid Rocket Booster Маршевый двигатель РДТТ Тяга 12.5 МН на уровне моря Удельный импульс 269 с Время работы 124 с

Планируется, что по массе грузов, выводимых на околоземные орбиты, SLS будет самой мощной действующей ракетой-носителем ко времени своего первого старта, а также четвёртой в мире и второй в США РН сверхтяжёлого класса - после «Сатурн-5 », которая использовалась в программе «Аполлон » для запуска кораблей к Луне, и советских Н-1 и Энергия . Ракета будет выводить в космос пилотируемый корабль MPCV, который проектируется на основе корабля «Орион» из закрытой программы «Созвездие» .

Система в базовом варианте будет способна выводить 70 тонн груза на опорную орбиту. Конструкция ракеты-носителя предусматривает возможность увеличения этого параметра до 130 тонн в усиленной версии .

Предполагается что первая ступень ракеты будет оснащаться твердотопливными ускорителями и водородно-кислородными двигателями RS-25D/E от шаттлов , а вторая - двигателями J-2X разработанными для проекта «Созвездие» . Также ведутся тесты с газогенераторами двигателей F-1 от РН Сатурн V .

Стоимость программы SLS оценивается в $35 млрд . Стоимость одного запуска оценивается в $500 млн.

Галерея

    Art of SLS launch.jpg

    Предполагаемый вид старта носителя базового варианта

    SLS configurations.png

    Планируемые конфигурации носителя (Block I, Block IA и Block II)

    SLS Versions (metric).png

    Пилотируемый Block I (70 т) и грузовой Block II (130 т)

    Art of the Space Launch System on Launch Pad.jpg

    Предполагаемый вид стартового комплекса

Напишите отзыв о статье "Space Launch System"

Примечания

Ссылки

  • , nasa.gov

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

Нас в первую очередь интересуют два подхода к хранению и работе с данными SQL и NoSQL.

SQL (Structured Query Language) - язык структурированных запросов, применяемый для создания, модификации и управления данными в реляционных базах данных, основанных на реляционной модели данных. Думаю, подробно останавливаться на рассмотрении одноименного подхода не стоит, так как это первое с чем сталкивается любой, при изучении баз данных.

NoSQL (not only SQL, не только SQL) - ряд подходов, направленных на реализацию моделей баз данных, имеющих существенные отличия от средств языка SQL, характерного для традиционных реляционных баз данных.

Термин NoSQL был придуман Эриком Эвансом, когда Джоан Оскарсон из Last.fm хотел организовать мероприятие для обсуждения распределенных баз данных с открытым исходным кодом.

Концепция NoSQL не является полным отрицанием языка SQL и реляционной модели. NoSQL - это важный и полезный, но не универсальный инструмент. Одна из проблем классических реляционных БД - это сложности при работе с данными очень большого объема и в высоконагруженных системах. Основная цель NoSQL - расширить возможности БД там, где SQL недостаточно гибок, не обеспечивает должной производительности, и не вытеснять его там, где он отвечает требованиям той или иной задачи.

В июле 2011 компания Couchbase, разработчик CouchDB, Memcached и Membase, анонсировала создание нового SQL-подобного языка запросов - UnQL (Unstructured Data Query Language). Работы по созданию нового языка выполнили создатель SQLite Ричард Гипп (Richard Hipp) и основатель проекта CouchDB Дэмиен Кац (Damien Katz). Разработка передана сообществу на правах общественного достояния

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

NoSQL системы

NoSQL СУБД

Определимся с понятиями.

Масштабируемость - автоматическое распределение данных между несколькими серверами. Такие системы мы называем распределенные базы данных. В них входят Cassandra, HBase, Riak, Scalaris и Voldemort. Если вы используете объем данных, который не может быть обработан на одной машине или если вы не хотите управлять распределением вручную, то это то, что вам нужно.

Следует обратить внимание на следующие вещи: поддержка нескольких датацентров и возможность добавления новых машин в работающий кластер прозрачно для ваших приложений.

Прозрачное добавление машины в кластер

Поддержка нескольких датацентров

Необходимо доработать напильником

К нераспределенным базам данных относятся: CouchDB, MongoDB, Neo4j, Redis и Tokyo Cabinet . Эти системы можно использовать в качестве «прослойки» для распределенных систем.

Модель данных и запросов

Существует огромное количество моделей данных и API запросов в NoSQL базах данных.

Модель данных

API запросов

Семейство столбцов

Документы

Семейство столбцов

Документы

Коллекции

Документы

Nested hashes, REST

Ключ / Значение

Ключ / Значение

Ключ / Значение

Система семейства столбцов (column family) используется в Cassandra и HBase. В обеих системах, у вас есть строки и столбцы, но количество строк не велико: каждая строка имеет переменное число столбцов и столбцы не должны быть определены заранее.

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

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

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

Scalaris уникальна в части использования распределенных транзакций между несколькими ключами.

Система хранения данных

Это вид, в котором данные представлены в системе.

Вид данных

Memtable / SSTable

Append-only B-Tree

Memtable / SSTable on HDFS

On-disk linked list

In-memory with background snapshots

Pluggable (primarily BDB MySQL)

Система хранения данных может помочь при оценке нагрузок.

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

Memtables / SSTables буферизируют запросы на запись в памяти (Memtable), а после записи добавляют в лог. После накопления достаточного количества записей, Memtable сортируется и записывается на диск, как SSTable. Это позволяет добиться производительности близкой к производительности оперативной памяти, в тоже время избавиться от проблем, актуальных при хранении только в памяти.

B-деревья используются в базах данных уже очень давно. Они обеспечивают надежную поддержку индексирования, однако производительность, при использовании на машинах с магнитными жесткими дисками, очень низкая.
Интересным является использование в CouchDB B-деревьев, только с функцией добавления (append-only B-Trees), что позволяет получить хорошую производительность при записи данных на диск. Достигается это тем, что бинарное дерево не нужно перестраивать при добавлении элемента.

Отдельного рассмотрения заслуживает проект Memcached , ставший прародителем для множества других систем.

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

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

С помощью клиентской библиотеки Memcached позволяет кэшировать данные в оперативной памяти из множества доступных серверов. Распределение реализуется путем сегментирования данных по значению хэша ключа по аналогии с сокетами хэш-таблицы. Клиентская библиотека, используя ключ данных, вычисляет хэш и использует его для выбора соответствующего сервера. Ситуация сбоя сервера трактуется как промах кэша, что позволяет повышать отказоустойчивость комплекса за счет наращивания количества memcached серверов и возможности производить их горячую замену.

Memcached имеет множество модификаций, развиваемых в рамках нескольких проектов: Mycached, membase, Memcache, MemcacheQ, Memcacheddb и libMemcached .

Центральный проект, локомотив концепции NoSQL - Memcached. Один из самых существенных минусов Memcached состоит в том, что сам кэш - весьма ненадежное место хранения данных. Устранить этот недостаток и призваны дополнительные решения: Memcacheddb и membase. На уровне интерфейса (API) эти продукты полностью совместимы с Memcached. Но здесь, при устаревании данных, они сбрасываются на диск (стратегия « db checkpoint »). В таком виде они представляют собой яркий пример «нереляционных баз данных» - персистентных (долговременных) систем распределённого хранения данных в виде пар «ключ-значение».

Следующий продукт, на основе Memcached - MemcacheQ. Это система очередей сообщений, в которой используется очень упрощенный API от Memcached. MemcacheQ образует именованный стек, куда можно записать свои сообщения, а сами данные физически хранятся в БД BerkeleyDB (аналогично Memcacheddb), следовательно, обеспечиваются сохранность, возможность реплицирования и прочее.

LibMemcached - это известная клиентская библиотека, написанная на С++, для работы с уже стандартным протоколом Memcached.

Все нереляционные хранилища, выполненные в виде распределенной системы и хранящие пары «ключ-значение», можно подразделить на два типа: устойчивые и неустойчивые. Устойчивые (например, MemcachedB, membase, Hypertable ) - записывают данные на диск, обеспечивая их сохранность в случае сбоя. Неустойчивые (классический Memcached) - хранят ключи в энергозависимой памяти и не гарантируют их сохранность. Неустойчивые хранилища оправдано использовать для кеширования и снижения нагрузки на устойчивые - в этом их неразрывная связь и главное преимущество.

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

Схема frontend+backend

Самая распространенная схема, при которой в роли frontend выступает быстрый и легкий web сервер (например Nginx), а в качестве backend работает Apache.

Давайте рассмотрим преимущества такой схемы на примере. Представим, что web серверу Apache необходимо обслужить порядка 1000 запросов одновременно, причем многие из этих клиентов подключены к интернету по медленным каналам связи. В случае использования Apache мы получим 1000 процессов httpd, на каждый из которых будет выделена оперативная память, и эта память будет занята до тех пор, пока клиент не получит запрошенный контент или не возникнет ошибка.

В случае применения схемы frontend+backend, после того как пришел запрос клиента, Nginx передает запрос Apache и быстро получает ответ. А в случае со статическим контентом (html, картинки, файлы кеша и пр.) Nginx самостоятельно сформирует ответ, не потревожив Apache. Если нам все-таки нужно выполнить логику (php-скрипт), Apache после того как сделал это и отдал ответ Nginx освобождает память, далее с клиентом взаимодействует web сервер Nginx, который как раз и предназначен для раздачи статического контента, большому количеству клиентов, при незначительном потреблении системных ресурсов. В купе с грамотным кэшированием, получаем колоссальную экономию ресурсов сервера и систему, которую по праву можно назвать высоконагруженной.

Рабочие лошадки

Apache - оптимизация производительности

Для схемы frontend+backend производительность Apache не стоит столь остро, но если Вам дорога каждая микросекунда процессорного времени и каждый байт оперативной памяти, то следует уделить внимание этому вопросу.

Самый «крутой» способ – увеличить производительность сервера – поставить более шустрый процессор(ы) и побольше памяти, но мы с Вами пойдем по менее радикальному пути для начала. Ускорим работу Apache путем оптимизации его конфигурации. Существуют конфигурации, которые можно применить только при пересборке Apache, другие же можно применять без перекомпиляции сервера.

Загружайте только необходимые модули

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

Уменьшив количество модулей, Вы уменьшите объем потребляемой памяти. Если вы решили скомпилировать Apache самостоятельно, то либо тщательно подходите к выбору списка модулей, которые Вы хотите включить, либо скомпилируйте их как DSO, используя apxs в Apache1 и apxs2 в Apache2. Чтобы отключить ненужные DSO-модули, достаточно закомментировать лишние строчки LoadModule в httpd.conf. Если скомпилировать модули статически, Apache будет потреблять чуть меньше памяти, но Вам придется каждый раз его перекомпилировать, чтобы отключить или вкличить тот или иной модуль.

Выбирайте подходящий MPM

Для обработки запроса в Apache выделяется свой процессе или поток. Эти процессы работают в соответствии с одной из MPM (Мультипроцессорная модель). Выбор MPM зависит от многих факторов, таких как наличие поддержки потоков в ОС, объема свободной памяти, а также требований стабильности и безопасности.

Если безопасность превыше производительности, выбирайте peruser или Apache-itk. Если важнее производительность, обратите внимание на prefork или worker.

Название

Разработчик

Поддерживаемые OS

Описание

Назначение

Apache Software Foundation

Гибридная мультипроцессорно-мультипоточная модель. Сохраняя стабильность мультипроцессорных решений, она позволяет обслуживать большое число клиентов с минимальным использованием ресурсов.

Среднезагруженные веб-серверы.

Стабильный.

Apache Software Foundation

MPM, основанная на предварительном создании отдельных процессов, не использующая механизм threads.

Большая безопасность и стабильность за счёт изоляции процессов друг от друга, сохранение совместимости со старыми библиотеками, не поддерживающими threads.

Стабильный.

Apache Software Foundation

Гибридная модель, с фиксированным количеством процессов.

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

В разработке, нестабильный.

Apache Software Foundation

Мультипоточная модель, оптимизированная для работы в среде NetWare.

Серверы Novell NetWare

Стабильный.

Apache Software Foundation

Microsoft Windows

Мультипоточная модель, созданная для операционной системы Microsoft Windows.

Серверы под управлением Windows Server.

Стабильный.

Steinar H. Gunderson

MPM, основанная на модели prefork. Позволяет запуск каждого виртуального хоста под отдельными uid и gid.

Хостинговые серверы, серверы, критичные к изоляции пользователей и учёту ресурсов.

Стабильный.

Sean Gabriel Heacock

Модель, созданная на базе MPM perchild. Позволяет запуск каждого виртуального хоста под отдельными uid и gid. Не использует потоки.

Обеспечение повышенной безопасности, работа с библиотеками, не поддерживающими threads.

Для смены MPM требуется перекомпиляция Apache. Для этого удобнее взять source-based дистрибутив.

DNS lookup

Директива HostnameLookups включает обратные DNS запросы, при этом в логи пишутся dns-хосты клиентов вместо ip-адресов. Это существенно замедляет обработку запроса, т.к. запрос не обработается, пока не будет получен ответ от DNS-сервера. Следите, чтобы эта директива всегда была выключена (HostnameLookups Off). Если необходимы dns-адреса, можно «прогнать» лог в утилите logresolve.

Кроме того, следите, чтобы в директивах Allow from и Deny From использовались ip-адреса а не доменные имена. В противном случае Apache будет делать два dns запроса (обратный и прямой), чтобы узнать ip и убедиться что клиент валиден.

AllowOverride

Если директива AllowOverride не установлена в None, Apache попытается открыть.htaccess файлы в каждой директории, которую он посещает и во всех директориях выше нее. Например:

DocumentRoot /var/www/html

AllowOverride all

Если будет запрошен /index.html, Apache попытается открыть (и интерпретировать) файлы /.htaccess, /var/.htaccess, /var/www/.htaccess, и /var/www/html/.htaccess. Очевидно, что это увеличивает время обработки запроса. Так что, если вам нужен.htaccess только для одной директории, разрешите его только для нее:

DocumentRoot /var/www/html

AllowOverride None

AllowOverride all

FollowSymLinks и SymLinksIfOwnerMatch

Если для каталога включена опция FollowSymLinks, Apache будет следовать по символическим ссылкам в этом каталоге. Если включена опция SymLinksIfOwnerMatch, Apache будет следовать по символическим ссылкам, только если владелец файла или каталога на которую указывает эта ссылка, совпадает с владельцем указанного каталога. Поэтому при включенной опции SymLinksIfOwnerMatch Apache делает больше системных запросов. Кроме того, дополнительные системные запросы требуются, когда FollowSymlinks не определен. Следовательно, наиболее оптимальным для производительности будет включение опции FollowSymlinks, конечно, если политика безопасности позволяет это сделать.

Content Negotiatio

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

Нетрудно понять, чем это грозит для производительности сервера, поэтому избегайте применения content negotiaion.

MaxClients

Директива MaxClients устанавливает максимальное количество параллельных запросов, которые будет поддерживать сервер. Значение MaxClient не должно быть слишком маленьким, иначе многим клиентам будет отказано. Нельзя устанавливать слишком большое количество – это грозит нехваткой ресурсов и «падением» сервера. Ориентировочно, MaxClients = количество памяти выделенное под веб-сервер / максимальный размер порожденного процесса или потока. Для статических файлов Apache использует около 2-3 Мб на процесс, для динамики (php, cgi) – зависит от скрипта, но обычно около 16-32 Мб. Если сервер уже обслуживает MaxClients запросов, новые запросы попадают в очередь, размер которой устанавливается директивой ListenBacklog.

MinSpareServers, MaxSpareServers, и StartServers

Создание потока, и особенно процесса – ресурсоемкая операция, поэтому Apache создает их про запас. Директивы MaxSpareServers и MinSpareServers устанавливают минимальное и максимальное число процессов/потоков, которые должны быть готовы принять запрос. Если значение MinSpareServers слишком мало и пришло много запросов, Apache начнет создавать много новых процессов/потоков, что создаст лишнюю нагрузку в пиковые моменты. Если MaxSpareServers слишком велико, Apache будет излишне нагружать систему, даже если число запросов минимально.

Опытным путем нужно попдобрать такие значения, чтобы Apache не создавал более 4 процессов/потоков в секунду. Если он создаст более 4, в ErrorLog будет сделана соответствующая запись – сигнал того что MinSpareServers нужно увеличить.

MaxRequestsPerChild

Директива MaxRequestsPerChild определяет максимальное число запросов, которое может обработать один дочерний процесс/поток прежде чем он завершиться. По умолчанию значение установлено в 0, что означает, что не будет завершен никогда. Рекомендуется установить MaxRequestsPerChild равное числу запросов за час. Это не создаст лишней нагрузки на сервер и, в то же время, поможет избавиться от проблем с утечкой памяти в дочерних процессах (например, если вы используете нестабильную версию php).

KeepAlive и KeepAliveTimeout

KeepAlive позволяет делать несколько запросов в одном TCP-подключении. При использовании схемы frontend+backend, эти директивы не актуальны.

HTTP-сжатие

Сейчас все современные клиенты и практически все сервера поддерживают HTTP-сжатие. Использование сжатия позволяет понизить трафик между клиентом и сервером до 4-х рах, повышая при этом нагрузку на процессор сервера. Но, если сервер посещает много клиентов с медленными каналами, сжатие способно снизить нагрузку посредством уменьшения времени передачи сжатого ответа. При этом ресурсы, занятые дочерним процессом освобождаются быстрее, и уменьшается число одновременных запросов. Это особенно заметно в условиях ограничения памяти.

Отмечу, что не следует устанавливать степень сжатия gzip более 5, так как существенно возрастает нагрузка на процессор, а степень сжатия растет незначительно. Также, не следует сжимать файлы, формат которых уже подразумевает сжатие – это практически все мультимедийные файлы и архивы.

Кеширование на стороне клиента

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

Отключение логов

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

Nginx

Простой и легкий веб-сервер, специально предназначенный для обработки статических запросов. Причина его производительности в том, что рабочие процессы обслуживают одновременно множество соединений, мультиплексируя их вызовами операционной системы select, epoll (Linux) и kqueue (FreeBSD). Сервер имеет эффективную систему управления памятью с применением пулов. Ответ клиенту формируется в буферах, которые хранят данные либо в памяти, либо указывают на отрезок файла. Буферы объединяются в цепочки, определяющие последовательность, в которой данные будут переданы клиенту. Если операционная система поддерживает эффективные операции ввода-вывода, такие как writev и sendfile , то Nginx, по возможности, применяет их.

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

Lighttpd

«Веб-сервер, разрабатываемый с расчётом на быстроту и защищённость, а также соответствие стандартам.» – википедия

Является альтернативой Nginx и применяется для тех же целей.

Акселераторы PHP

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

Существующие решения

The Alternative PHP Cache -был задуман, как бесплатный, открытый и стабильный фреймворк для кэширования и оптимизации исходного кода PHP. Поддерживает PHP4 и PHP5, включая 5.3.

eAccelerator - это свободный открытый проект, выполняющий также роли акселератора, оптимизатора и распаковщика. Имеет встроенные функции динамического кэширования контента. Имеется возможность оптимизации PHP-скриптов. Поддерживает PHP4 и PHP5, включая 5.3.

PhpExpress бесплатный ускоритель обработки PHP скриптов на веб-сервере. Также обеспечивает поддержку загрузки файлов закодированных через Nu-Coder. Поддерживает PHP4 и PHP5, включая 5.3

XCache поддерживает PHP4 и PHP5, включая 5.3. Начиная с версии 2.0.0 (release candidate от 2012-04-05) включена поддержка PHP 5.4.

Windows Cache Extension for PHP - PHP-акселератор для Microsoft IIS (BSD License). Поддерживает только PHP (5.2 и 5.3).

Логика кэширования

«Кэшировать, кэшировать и еще раз кэшировать!» - вот девиз высоконагруженной системы.

Давайте представим себе идеальный высоконагруженный сайт. Сервер получает http запрос от клиент. Frontend сопоставляет запрос с физическим файлом на сервере и, если тот существует, отдает его. Загрузку скриптов и картинок опустим, так как это в большинстве своем статика и отдается по такому же принципу. Далее, если физически файл не существует, frontend обращается с этим запросом к backend-у, который занимается обработкой логики (скриптов php и т.д.). Backend должен решить кэшировать ли данный запрос и создать файл в определенном месте, который и будет отдаваться frontend-ом в дальнейшем. Таким образом, мы навсегда закэшировали данный запрос и сервер будет обрабатывать его максимально быстро с минимально возможной нагрузкой на сервер.

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

Самым удобным и распространенным способом разделения данных является разделение страницы на блоки. Это логично и удобно, ведь страница, с точки зрения верстки, состоит из блоков. Избежать логики в этом случае естественно не получится, но логика эта будет обрабатываться с наименьшими затратами.

Таким образом, запрос клиента (кроме запроса статики) переадресуется на backend и его обработка сводится к следующим действиям:

  1. Получение информации о блоках, которые будут на странице.
  2. Проверка информации о кэшах для каждого блока. Кэш может не существовать или нуждаться в обновлении. В этом случае генерируем файл кэша. Если блок не должен кэшироваться выполняем соответствующую логику. Информацию о кэшах можно хранить в nosql базе данных или в файловой структуре. Тут требование одно: получение этой информации должно занимать минимум ресурсов.
  3. Формируем html страницы. Закэшированные блоки встраиваем при помощи ssi инструкции (вставляется ссылка на файл кэша), что позволит существенно экономить память.
  4. Страница попадает на frontend, который производит замену всех ssi инструкций на содержимое файлов и отдает страницу клиенту.

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

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

Картинки, пикчи, тумбочки

Оказывается изображение тоже можно кэшировать. Зачем? Спросите Вы. В принципе, после загрузки на сервер у нас уже есть файл, который frontend быстренько выплюнет при необходимости. Но часто нам требуется получить на основе уже имеющейся картинки другое изображение (например, других размеров). Допустим, нам нужна миниатюра изображения – thumbnail (тумбочка жарг.). В этом случае, нам достаточно сформировать путь к бедующему файлу уменьшенной картинки и отдать страницу клиенту.

  1. Клиент, получив исходный код страницы, начинает подгружать статику и обращается с запросом на несуществующую пока картинку к frontend-у.
  2. Frontend переадресует запросы к несуществующим изображениям на backend.
  3. Backend анализирует запрос, формирует файл изображения и отдает бинарные данные с соответствующим http-заголовком.
  4. Все последующие запросы будут отдаваться frontend-ом.

Это четвертая статья из серии "Преодолевая границы Windows", в рамках которой я рассказываю об ограничениях, существующих для фундаментальных ресурсов в Windows. На сей раз, я собираюсь обсудить с вами ограничение на максимальное количество потоков и процессов, поддерживаемое Windows. Здесь я кратко опишу различие между потоком и процессом, ограничение потока опроса (от англ. survey thread), после чего мы поговорим об ограничениях, связанных с процессами. В первую очередь я решил рассказать об ограничениях потоков, так как каждый активный процесс имеет, по крайней мере, один поток (процесс, который завершился, но ссылка на который хранится в обработчике, предоставленном другим процессом, не имеет ни одного потока), так что ограничения процессов напрямую зависят от основных ограничений, связанных с потоками.

В отличие от некоторых вариантов UNIX, большинство ресурсов Windows не имеют фиксированного ограничения, заложенного в операционную систему на этапе сборки, а скорее получают ограничения на основании имеющихся в распоряжении ОС базовых ресурсов, о которых я рассказывал ранее. Процессы и потоки, например, требуют для себя физической памяти, виртуальной памяти и памяти пула, так что число процессов и потоков, которые могут быть созданы на данной системе Windows, в конечном счете, определяется одним из этих ресурсов, в зависимости от того, каким образом эти процессы или потоки были созданы и какое из ограничений базовых ресурсов будет достигнуто первым. Поэтому я рекомендую вам, чтобы вы прочитали мои предыдущие статьи, если вы до сих пор этого не сделали, потому что далее я буду обращаться к таким понятиям, как зарезервированная память, выделенная память и системное ограничение памяти, о которых я говорил в предыдущих своих статьях:

Процессы и потоки
Процесс Windows по своей сути является контейнером, в котором хранится код команд из исполняемого файла. Он представляет собой объект процесса ядра и Windows использует этот объект процесса и связанные с ним структуры данных для хранения и сопровождения информации об исполняемом коде приложения. Например, процесс имеет виртуальное адресное пространство, в котором хранятся его частные и общие данные и в которое отображаются исполняемый образ и связанные с ним библиотеки DLL. Windows с помощью инструментов диагностики записывает информацию об использовании процессом ресурсов для обеспечения учета и выполнения запросов и регистрирует ссылки процесса на объекты операционной системы в таблице дескриптора процесса. Процессы работают с контекстом безопасности, именуемом маркером, который идентифицирует учетную запись пользователя, группы учетной записи и привилегии, назначенные процессу.

Процесс включает в себя один или более потоков, которые фактически выполняют код в процессе (технически, выполняются не процессы, а потоки) и представлены в системе в виде объектов потоков ядра. Есть несколько причин, почему приложения создают потоки в дополнение к их исходному начальному потоку: 1) процессы, обладающие пользовательским интерфейсом, обычно создают потоки для того, чтобы выполнять свою работу и при этом сохранять отзывчивость основного потока к командам пользователя, связанными с вводом данных и управлением окнами; 2) приложения, которые хотят использовать несколько процессоров для масштабирования производительности или же которые хотят продолжать работать, в то время как потоки останавливают свою работу, ожидая синхронизации операций ввода/вывода, создают потоки, чтобы получить дополнительную выгоду от многопоточной работы.

Ограничения потоков
Помимо основной информации о потоке, включая данные о состоянии регистров ЦП, присвоенный потоку приоритет и информацию об использовании потоком ресурсов, у каждого потока есть выделенная ему часть адресного пространства процесса, называемая стеком, которую поток может использовать как рабочую память по ходу исполнения кода программы, для передачи параметров функций, хранения локальных переменных и адресов результатов работы функций. Таким образом, чтобы избежать нерациональной траты виртуальной памяти системы, первоначально распределяется только часть стека, или же часть ее передается потоку, а остаток просто резервируется. Поскольку стеки в памяти растут по нисходящей, система размещает так называемые "сторожевые" страницы (от англ. guard pages) памяти вне выделенной части стека, которые обеспечивают автоматическое выделение дополнительной памяти (называемой расширением стека), когда она потребуется. На следующей иллюстрации показано, как выделенная область стека углубляется и как сторожевые страницы перемещаются по мере расширения стека в 32-битном адресном пространстве:

Структуры Portable Executable (PE) исполняемых образов определяют объем адресного пространства, которое резервируется и изначально выделяется для стека потока. По умолчанию компоновщик резервирует 1Мб и выделяет одну страницу (4Кб), но разработчики могут изменять эти значения либо меняя значения PE, когда они организуют связь со своей программой, либо путем вызова для отдельного потока функции CreateTread . Вы можете использовать утилиту, такую как Dumpbin , которая идет в комплекте с Visual Studio, чтобы посмотреть настройки исполняемой программы. Вот результаты запуска Dumpbin с опцией /headers для исполняемой программы, сгенерированной новым проектом Visual Studio:

Переведя числа из шестнадцатеричной системы исчисления, вы можете увидеть, что размер резерва стека составляет 1Мб, а выделенная область памяти равна 4Кб; используя новую утилиту от Sysinternals под названием MMap , вы можете подключиться к этому процессу и посмотреть его адресное пространство, и тем самым увидеть изначально выделенную страницу памяти стека процесса, сторожевую страницу и остальную часть зарезервированной памяти стека:

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

Ограничения 32-битных потоков
Даже если бы у процесса вообще не было ни кода, ни данных и все адресное пространство могло бы быть использовано под стеки, то 32-битный процесс с установленным по умолчанию адресным пространством в 2 б мог бы создать максимум 2048 потоков. Вот результаты работы программы Testlimit , запущенной в 32-битной Windows с параметром -t (создание потоков), подтверждающие наличие этого ограничения:

Еще раз, так как часть адресного пространства уже использовалась под код и начальную динамическую память, не все 2Гб были доступны для стеков потоков, так что общее количество созданных потоков не смогло достигнуть теоретического предела в 2048 потоков.

Я попробовал запустить Testlimit с дополнительной опцией, предоставляющей приложению расширенное адресное пространство, надеясь, что если уж ему дадут больше 2Гб адресного пространства (например, в 32-битных системах это достигается путем запуска приложения с опцией /3GB или /USERVA для Boot.ini, или же эквивалентной опцией BCD на Vista и позднее increaseuserva), оно будет его использовать. 32-битным процессам выделяется 4Гб адресного пространства, когда они запускаются на 64-битной Windows, так сколько же потоков сможет создать 32-битный Testlimit, запущенный на 64-битной Windows? Если основываться на том, что мы уже обсудили, ответ должен быть 4096 (4Гб разделенные на 1Мб), однако на практике это число значительно меньше. Вот 32-битный Testlimit, запущенный на 64-битной Windows XP:

Причина этого несоответствия кроется в том факте, что когда вы запускаете 32-битное приложение на 64-битной Windows, оно фактические является 64-битным процессом, которое выполняет 64-битный код от имени 32-битных потоков, и потому в памяти для каждого потока резервируются области под 64-битные и 32-битные стеки потоков. Для 64-битного стека резервируется 256Кб (исключения составляют ОС, вышедшие до Vista, в которых исходный размер стека 64-битных потоков составляет 1Мб). Поскольку каждый 32-битный поток начинает свое существование в 64-битном режиме и размер стека, который ему выделяется при старте, превышает размер страницы, в большинстве случаев вы увидите, что под 64-битный стек потока выделяется как минимум 16Кб. Вот пример 64-битных и 32-битных стеков 32-битного потока (32-битный стек помечен как "Wow64"):

32-битный Testlimit смог создать в 64-битной Windows 3204 потока, что объясняется тем, что каждый поток использует 1Мб + 256Кб адресного пространство под стек (повторюсь, исключением являются версии Windows до Vista, где используется 1Мб+ 1Мб). Однако, я получил другой результат, запустив 32-битный Testlimit на 64-битной Windows 7:

Различия между результатами на Windows XP и Windows 7 вызвано более беспорядочной природой схемы распределения адресного пространства в Windows Vista, Address Space Layout Randomization (ASLR), которая приводит к некоторой фрагментации. Рандомизация загрузки DLL, стека потока и размещения динамической памяти, помогает улучшить защиту от вредоносного ПО. Как вы можете увидеть на следующем снимке программы VMMap, в тестовой системе есть еще 357Мб доступного адресного пространства, но наибольший свободный блок имеет размер 128Кб, что меньше чем 1Мб, необходимый для 32-битного стека:

Как я уже отмечал, разработчик может переустановить заданный по умолчанию размер резерва стека. Одной из возможных причин для этого может быть стремление избежать напрасного расхода адресного пространства, когда заранее известно, что стеком потока всегда будет использоваться меньше, чем установленный по умолчанию 1Мб. PE-образ Testlimit по умолчанию использует размер резерва стека в 64Кб, и когда вы указываете вместе параметром -t параметр -n, Testlimit создает потоки со стеками размером в 64Кб. Вот результат работы этой утилиты на системе с 32-битной Windows XP и 256Мб RAM (я специально провел этот тест на слабой системе, что подчеркнуть данное ограничение):

Здесь следует отметить, что произошла другая ошибка, из чего следует, что в данной ситуации причиной является не адресное пространство. Фактически, 64Кб-стеки должны обеспечить приблизительно 32 000 потоков (2Гб/64Кб = 32768). Так какое же ограничение проявилось в данном случае? Если посмотреть на возможных кандидатов, включая выделенную память и пул, то никаких подсказок в нахождении ответа на этот вопрос они не дают, поскольку все эти значения ниже их пределов:

Ответ мы можем найти в дополнительной информации о памяти в отладчике ядра, который укажет нам искомое ограничение, связанное с доступной резидентной памятью, весь объем которой был исчерпан:

Доступная резидентная память - это физическая память, выделяемая для данных или кода, которые обязательно должны находиться в оперативной памяти. Размеры невыгружаемого пула и невыгружаемых драйверов высчитываются независимо от этого, также как, например, память, зарезервированная в RAM для операций ввода/вывода. У каждого потока есть оба стека пользовательского режима, об этом я уже говорил, но у них также есть стек привилегированного режима (режима ядра), который используется тогда, когда потоки работают в режиме ядра, например, исполняя системные вызовы. Когда поток активен, его стек ядра закреплен в памяти, так что поток может выполнять код в ядре, для которого нужные страницы не могут отсутствовать.

Базовый стек ядра занимает 12Кб в 32-битной Windows и 24Кб в 64-битной Windows. 14225 потоков требуют для себя приблизительно 170Мб резидентной памяти, что точно соответствует объему свободной памяти на этой системе с выключенным Testlimit:

Как только достигается предел доступной системной памяти, многие базовые операции начинают завершаться с ошибкой. Например, вот ошибка, которую я получил, дважды кликнув на ярлыке Internet Explorer, расположенном на рабочем столе:

Как и ожидалось, работая на 64-битной Windows с 256Мб RAM, Testlimit смог создать 6600 потоков - примерно половину от того, сколько потоков эта утилита смогла создать в 32-битной Windows с 256Мб RAM - до того, как исчерпалась доступная память:

Причиной, по которой ранее я употреблял термин "базовый" стек ядра, является то, что поток, который работает с графикой и функциями управления окнами, получает "большой" стек, когда он исполняет первый вызов, размер которого равен (или больше) 20Кб на 32-битной Windows и 48Кб на 64-битной Windows. Потоки Testlimit не вызывают ни одного подобного API, так что они имеют базовые стеки ядра.
Ограничения 64-битных потоков

Как и у 32-битных потоков, у 64-битных потоков по умолчанию есть резерв в 1Мб для стека, но 64-битные имеют намного больше пользовательского адресного пространства (8Тб), так что оно не должно стать проблемой, когда дело доходит до создания большого количества потоков. И все же очевидно, что резидентная доступная память по-прежнему является потенциальным ограничителем. 64-битная версия Testlimit (Testlimit64.exe) смогла создать с параметром -n и без него приблизительно 6600 потоков на системе с 64-битной Windows XP и 256Мб RAM, ровно столько же, сколько создала 32-битная версия, потому что был достигнут предел резидентной доступной памяти. Однако, на системе с 2Гб оперативной памяти Testlimit64 смог создать только 55000 потоков, что значительно меньше того количества потоков, которое могла бы создать эта утилита, если бы ограничением выступила резидентная доступная память (2Гб/24Кб = 89000):

В данном случае причиной является выделенный начальный стек потока, который приводит к тому, что в системе заканчивается виртуальная память и появляется ошибка, связанная с нехваткой объема файла подкачки. Как только объем выделенной памяти достигает размера оперативной памяти, скорость создания новых потоков существенно снижается, потому что система начинает "пробуксовывать", ранее созданные стеки потоков начинают выгружаться в файл подкачки, чтобы освободить место для стеков новых потоков, и файл подкачки должен увеличиваться. С включенным параметром -n результаты те же, поскольку таким же остается начальный объем выделенной памяти стека.

Ограничения процессов
Число процессов, поддерживаемых Windows, очевидно, должно быть меньше, чем число потоков, потому как каждый процесс имеет один поток и сам по себе процесс приводит к дополнительному расходу ресурсов. 32-битный Testlimit, запущенный на системе с 64-битной Windows XP и 2Гб системной памяти создает около 8400 процессов:

Если посмотреть на результат работы отладчика ядра, то становится понятно, что в данном случае достигается ограничение резидентной доступной памяти:

Если бы процесс использовал резидентную доступную память для размещения только лишь стека потока привилегированного режима, Testlimit смог бы создать намного больше, чем 8400 потоков на системе с 2Гб. Количество резидентной доступной памяти на этой системе без запущенного Testlimit равно 1,9Гб:

Путем деления объема резидентной памяти, используемой Testlimit (1,9Гб), на число созданных им процессов получаем, что на каждый процесс отводится 230Кб резидентной памяти. Так как 64-битный стек ядра занимает 24 Кб, мы получаем, что без вести пропали примерно 206Кб для каждого процесса. Где же остальная часть используемой резидентной памяти? Когда процесс создан, Windows резервирует достаточный объем физической памяти, чтобы обеспечить минимальный рабочий набор страниц (от англ. working set). Это делается для того, чтобы гарантировать процессу, что любой ситуации в его распоряжении будет достаточное количество физической памяти для сохранения такого объема данных, который необходим для обеспечения минимального рабочего набора страниц. По умолчанию размер рабочего набора страниц зачастую составляет 200Кб, что можно легко проверить, добавив в окне Process Explorer столбец Minimum Working Set:

Оставшиеся 6Кб - это резидентная доступная память, выделяемая под дополнительную нестраничную память (от англ. nonpageable memory), в которой хранится сам процесс. Процесс в 32-битной Windows использует чуть меньше резидентной памяти, поскольку его привилегированный стек потока меньше.

Как и в случае со стеками потока пользовательского режима, процессы могут переопределять установленный для них по умолчанию размер рабочего набора страниц с помощью функции SetProcessWorkingSetSize . Testlimit поддерживает параметр -n, который, в совокупности с параметром -p, позволяет устанавливать для дочерних процессов главного процесса Testlimit минимально возможный размер рабочего набора страниц, равный 80Кб. Поскольку дочерним процессам нужно время, чтобы сократить их рабочие наборы страниц, Testlimit, после того, как он больше не сможет создавать процессы, приостанавливает работу и пробует ее продолжить, давая его дочерним процессам шанс выполниться. Testlimit, запущенный с параметром -n на системе с Windows 7 и 4Гб RAM уже другого, отличного от ограничения резидентной доступной памяти, предела - ограничения выделенной системной памяти:

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

До запуска Testlimit средний уровень выделенного объема памяти был равен приблизительно 1,5Гб, так что потоки заняли около 8Гб выделенной памяти. Следовательно, каждый процесс потреблял примерно 8 Гб/6600 или 1,2Мб. Результат выполнения команды!vm отладчика ядра, которая показывает распределение собственной памяти (от англ. private memory) для каждого процесса, подтверждает верность данного вычисления:

Начальный объем выделенной памяти под стек потока, описанный ранее, оказывает незначительное влияние на остальные запросы на предоставление памяти, требуемой для структур данных адресного пространства процесса, записей таблицы страниц, таблицы дескрипторов, объектов процесса и потока, и собственных данных, которые процесс создает во время своей инициализации.

Сколько процессов и потоков будет достаточно?
Таким образом, ответы на вопросы "сколько потоков поддерживает Windows?" и "сколько процессов вы можете одновременно запустить на Windows?" взаимосвязаны. Помимо нюансов методов, по которым потоки определяют размер их стека и процессы определяют их минимальный рабочий набор страниц, двумя главными факторами, определяющим ответы на эти вопросы для каждой конкретной системы, являются объем физической памяти и ограничение выделенной системной памяти. В любом случае, если приложение создает достаточное количество потоков или процессов, чтобы приблизиться к этим пределам, то его разработчику следует пересмотреть проект этого приложения, поскольку всегда существуют различные способы достигнуть того же результата с разумным числом процессов. Например, основной целью при масштабировании приложения является стремление сохранить число выполняющихся потоков равным числу ЦП, и один из способов добиться этого состоит в переходе от использования синхронных операции ввода/вывода к асинхронным с использованием портов завершения, что должно помочь сохранить соответствие числа запущенных потоков с числом ЦП.



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: