2009-08-05 3 views
24

Я разработал мини-HTTP-сервер на C++, используя boost :: asio, и теперь я загружаю его несколькими клиентами, и мне не удалось приблизиться к насыщению CPU. Я тестирую экземпляр Amazon EC2 и получаю около 50% использования одного процессора, 20% другого, а остальные два неактивны (согласно htop).Сервер Socket Socket - не удалось насытить CPU

Детали:

  • Сервер запускает один поток на ядро ​​
  • Запросы принимаются, разобранные, обработаны и ответы выписаны
  • Запросы данных, который считывается из память (только для чтения для этого теста)
  • Я загружаю сервер с использованием двух машин, каждый из которых запускает приложение Java, работает 25 потоков, отправляет запросы
  • Я вижу около 230 запросов/сек. ughput (это приложение запросы, которые состоят из многих запросов HTTP)

Итак, что я должен смотреть на то, чтобы улучшить этот результат? Учитывая, что процессор в основном неактивен, я бы хотел использовать эту дополнительную емкость, чтобы получить более высокую пропускную способность, скажем, 800 запросов/сек или что-то еще.

Идеи У меня была:

  • Просьбы очень мал, и часто выполняется в течение нескольких миллисекунд, я мог бы изменить клиент для отправки/сочинить больше запросов (возможно, с помощью пакетирование)
  • I может изменить HTTP-сервер, чтобы использовать шаблон дизайна Select, это уместно?
  • я мог бы сделать некоторое профилирование, чтобы попытаться понять, что являются узким местом-х/является
+0

Удовлетворительно предположить, что на сервере имеется порт 1 Гбит/с? Каковы ваши размеры запросов и ответов (на проводе)? – nik

+2

Каково использование полосы пропускания на сетевом порту сервера (тот, который я предполагаю равным 1 Гбит/с) – nik

+1

Тест работает на EC2, который, я считаю, использует Gigabit. Bmon сообщает о скорости передачи данных в 3MiB (мегабит), а также скорости 2.5Mib RX. Многие размеры запросов/ответов небольшие (всего 100 байт), но некоторые ответы до 1 Мбайта, запросы, вероятно, до 0,25 мб. –

ответ

40

повышения :: ASIO не как нить людей, как вы хотели бы надеяться, - есть большой замок вокруг кода Epoll в импульсе /asio/detail/epoll_reactor.hpp, что означает, что только один поток может вызывать в syscall ядра в одно время. И для очень маленьких запросов это имеет значение (это означает, что вы увидите только однопоточную производительность).

Обратите внимание, что это ограничение того, как boost :: asio использует возможности ядра Linux, а не только ядро ​​Linux. Сценарий epoll поддерживает несколько потоков при использовании событий, связанных с краем, но правильное (без чрезмерной блокировки) может быть довольно сложным.

BTW, я выполнял некоторую работу в этой области (объединяя полностью многопотоковый цикл событий эпоксидного цикла с пользовательскими потоками/волокнами) и сделал некоторый код доступным в рамках проекта nginetd.

+0

Спасибо за информацию cmeerw, это интересно. –

+1

(+1) cmeer У меня есть неотвеченный пост, связанный с повышением boost :: asio в целом на windows и linux. Если вы прочитали большие разделы asio, пожалуйста, приходите и отвечайте на мой пост: P –

+3

Я действительно беспокоился об этом глобальном замке. Это не такая уж большая проблема, как казалось бы. Шея бутылки может возникать только в сценариях с высокой пропускной способностью. Однако, когда asio работает в режиме epoll (linux), он превентивно пытается писать или читать, когда выдается вызов «async_ *». В сценарии с высоким входным сигналом сокет обычно готов к чтению, позволяя «async_read» полностью пропускать epoll. Вы не можете запрашивать лучшую производительность сети, чем это. –

2

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

3 + 2.5 MiB/sec находится вокруг шара-парка 50Mbps (по сравнению с вашим портом 1 Гбит/с).

Я бы сказал, что у Вас есть один из следующих двух проблем,

  1. Недостаточная загруженность (низкая скорость запроса от ваших клиентов)
    • Блокировка на сервере (вмешивались генерацию ответа)

Глядя на cmeerw «s нот и ваше использование CPU цифры
(на холостом ходу на 50% + 20% + 0% + 0%)
кажется скорее всего ограничением в реализации вашего сервера.
I второй ответ cmeerw (+1).

+1

Он запускает тесты на кластере облачных вычислений Amazon EC2. Трудно исключить, возможно, плохую работу на EC2. – unixman83

3

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

This article содержит несколько подробностей и обсуждение стратегий ввода-вывода для производительности веб-сервера около 2003 года. У кого-нибудь появилось что-то более новое?

+0

Имейте в виду, что 230 запросов/сек являются «запросами приложений», которые состоят из множества HTTP-запросов. –

+0

Существует не так много блокировок, чтобы избавиться от них, ни одного в моем коде, но как cmeerw указывает на boost :: asio делает некоторую внутреннюю блокировку. HTTP-сервер выполняет исключительно ограниченную работой CPU, поэтому не использовать дополнительные ядра - это дорогостоящие отходы. –

+2

Если цель состоит в том, чтобы просто насытить процессор, выполните работу в одном потоке и попросите три других вычислить PI или что-то еще. Наличие нескольких потоков пользовательского уровня не облегчит или ускорит работу оборудования OS и IO для чтения и записи сетевых пакетов. Потоки и сердечники предназначены для вычислительной работы, если вы их не делаете, они ничего не могут вам принести, и рискнуть конфликтом с чем бы то ни было, что делает система. – soru

12

Поскольку вы используете EC2, все ставки отключены.

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

Я еще не разработал, какой EC2 полезен, если кто-то узнает, пожалуйста, дайте мне знать.

+0

Эта система будет развернута в EC2, поэтому тестирование производительности системы на реальном оборудовании было бы нецелесообразным, я не думаю. –

+6

Точка маркера действительна: для профилирования используется реальная машина или, по крайней мере, более контролируемая среда. Разверните в EC2 все, что вам нравится, но поймите, что вы работаете в образе VM, а это означает, что ваш «незанятый» процессор может быть просто из-за того, что какой-то другой арендатор на коробке получил весь процессор некоторое время. И это затрудняет профилирование. – janm

+2

(+1) ненавидят плохо информированные пустые голоса –

0

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

Для чего это стоит. используя вызовы raw сокета на моем настраиваемом HTTP, может обслуживать 800K динамических запросов в секунду с 4-ядерным I7. Он служит из ОЗУ, где вам нужно быть на таком уровне производительности. На этом уровне производительности сетевой драйвер и ОС потребляют около 40% процессора. Используя ASIO, я могу получить от 50 до 100 тыс. Запросов в секунду, его производительность довольно изменчива и в основном связана в моем приложении. Пост @cmeerw в основном объясняет, почему.

Одним из способов повышения производительности является внедрение прокси-сервера UDP. Перехватывая HTTP-запросы, а затем маршрутизируя их по UDP на ваш сервер UDP-HTTP, вы можете обойти много накладных расходов TCP в операционных системах. Вы также можете иметь передние концы, которые проходят через UDP самостоятельно, что не должно быть слишком сложным для себя. Преимущество прокси-сервера HTTP-UDP заключается в том, что он позволяет вам использовать любой хороший интерфейс без изменений, и вы можете поменять их по своему усмотрению без какого-либо воздействия. Вам просто нужно еще несколько серверов для его реализации. Эта модификация в моем примере снизила загрузку ОС до 10%, что увеличило мои запросы в секунду до чуть более миллиона на этом одном бэкэнд. И FWIW. У вас всегда должна быть встроенная настройка для любого сайта-исполнителя, поскольку интерфейсы могут кэшировать данные без замедления более важных динамических запросов.

Будущее, похоже, создает собственный драйвер, который реализует собственный сетевой стек, чтобы вы могли как можно ближе подойти к запросам и реализовать свой собственный протокол там.Скорее всего, это не то, что большинство программистов хотят услышать, поскольку это сложнее. В моем случае я мог бы использовать на 40% больше ЦП и переходить на более 1 млн динамических запросов в секунду. Прокси-метод UDP может приблизить вас к оптимальной производительности без необходимости делать это, однако вам понадобится больше серверов, хотя, если вы делаете это много запросов в секунду, вам обычно потребуется несколько сетевых карт и несколько интерфейсов для обработки полосы пропускания, поэтому пара легких прокси UDP в этом не является большой сделкой.

Надеюсь, что часть этого может быть вам полезна.

+1

Хотите показать пример или рабочий проект? Без этого это так же полезно, как бесполезные разговоры. Не пытайтесь унизить вас, но здесь нужен конкретный код. –

0

Сколько экземпляров io_service у вас есть? У Boost asio есть example, который создает io_service для каждого процессора и использует их в виде RoundRobin.

Вы по-прежнему можете создавать четыре потока и назначать по одному на каждый процессор, но каждый поток может опросить собственный io_service.

Смежные вопросы