![]() |
|
Модераторы: feodorv |
![]()
|
|
| rumit7 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Здравствуйте!
В данный момент активно занялся изучением возможностей Boost::ASIO. Впечатления от самой библиотеки только самые положительные, давно мне так сильно ничего не нравилось, наверно с тех самых пор, как я познакомился с С++, лет так 8 назад) Изучая ASIO Examples, ASIO Samples, а также другие примеры в сети, задумался над выработкой критериев для сравнения различных моделей построения асинхронного сервера, таких как (простите, не знаю как лучше перевести на русский):
На данный момент меня интересует - преимущества и недостатки каждой из моделей, на основе чего можно было бы сделать выбор под конкретные требования сервера.. Я так понимаю, наиболее важные критерии это:
Как правильнее оценить? Что обычно применяют в таких случаях? Какие-то утилиты вроде Jmeter? Или что-то еще? Обращаюсь к Вам с просьбой помочь разобраться в теме.. Пока сам пробую применить самописный многопоточный клиент - клиент запускает указанное кол-во потоков, каждый из которых одновременно начинает соединяться с сервером и собирает временную статистику. Ниже привожу код данного эхо клиента.
|
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
если вы хотите что-бы все запросы от одного клиента выполнялись на одном процессоре, синхронизация в этом случае может быть проще, но только если обработчики запросов из разных io_service-ов не лезут в общую память за данными, если лезут то преимуществ никаких нет. если вы хотите быстро и масштабируемо и, при этом без синхронизации - то не нужно использовать asio, asio это proactor, а вам нужно смотреть на библиотеки, реализующие reactor, в ace например есть, что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным запросы от одного клиента могут выполняться на разных процессорах и, может быть, даже параллельно(что-бы они не выполнялись параллельно используют strand), преимущество этого подхода перед первым - балансировка нагрузки между процессорами
не понял архитектура сервера это не то, сколько io_service-ов вы будете использоваться, это несколько более широкая тема, может быть вам вообще не стоит связываться со stateful архитектурой а забабахать sateless архитектуру без всяких сессий, но зато с преферансом и гимназистками? asio это тонкая надстройка над io completion ports, по крайней мере под виндой, поэтому можно с уверенностью сказать, что скорость обработки запроса зависит от скорости обработки запроса it depends, явно проще чем использовать голый win api отказоустойчивость, это свойство системы сохранять работоспособность после отказа некоторых ее частей, этого не достигнуть просто используя какую либо библиотеку некоторое количество памяти на каждую асинх. операцию ввода вывода, где-то ведь должен храниться ваш callback, чем их больше, тем больше тратится ресурсов. поэтому потребление ресурсов несколько непредсказуемо, чем больше всего происходит одновременно, чем больше асинхронных операций в процессе, тем больше нужно ресурсов |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 13 Всего: 110 |
rumit7, слишком уж абстрактно все у вас описано. можно долго распинаться описывая для вас то, что перепечатано во множестве книжек.
поконкретнее вопросы, пожалуйста. |
|||
|
||||
| rumit7 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
На данный момент меня интересует - скорость обработки запроса. Т.е. каким образом правильнее организовать сравнение по скорости обработки различных примеров, приводимых в ASIO Examples, ASIO Samples. Будут ли достоверными данные предоставляемые выше приведенной самописной тестовой тулзой? |
|||
|
||||
| rumit7 |
|
||||||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Я так понимаю здесь возможно использование memory pool на каждый проц и плюс к этому использование custom memory allocation, чтобы исключить обращение к общей памяти при выполнении асинхронных операций?
Спасибо. Пока моя цель - "быстро и масштабируемо", но по возможности с использованием ASIO. А там будем делать выводы..
Это модель применена в ASIO Samples, когда один io_service (+ 1 или 2 потока) используется для акцепта клиентов, создания сессий и управления ими, а второй io_service (+ по потоку на каждый проц) используется всеми сессиями (т.е. взаимодействие с клиентами).
Да я это понимаю. На данный момент я бы хотел выяснить: какой из моделей способов использования ASIO библиотеки дает больший перформанс и в каких случаях? Просто сравнивать примеры эхо серверов это глупо, яный пень в реальном проекте гораздо больше взаимодействий между различными факторами.. Но нужно же как-то выбрать. Следовательно нужно выполнить сравнение прототипов, думаю на первом этапе по скорости обработки клиентов. Здесь у меня начинается ступор - как лучше организовать сравнительный тест?
Спасибо за Ваш ответ! |
||||||||||||
|
|||||||||||||
| rumit7 |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Из документации Boost::ASIO:
Это ведь значит, что и с использованием ASIO можно добиться "что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным"? |
||||
|
|||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 13 Всего: 110 |
я и сам использую реализацию из asio-samples построенную на этой архитектуре, и, мое имхо - это лучшая архитектура. т.к. обладает высокой скоростью accepta+reusing_sessions, что позволит пережить большинство DDOS атак, так и тем что второй io_service существует в единственном экземпляре, что позволяет при использовании strand`ов избавится от прямой необходимости в синхронизации. ну а тестирование_производительности/сравнение_производительности - это очень субъективно и зависимо... Добавлено через 3 минуты и 30 секунд
да. при использовании двух и более io_service`ов. но в этом случае всю синхронизацию придется обеспечивать руками. а в этом случае, не факт что такая архитектура будет обладать большей производительностью. |
|||
|
||||
| rumit7 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Я хочу объеденить два подхода: показанный в примерах asio-samples и io_service на каждый проц. Идея заключается в том, чтобы по возможности локализовать обращение к памяти внутри одного проца (потока). Для этого выделять память, как для объектов сессий, так и для каждой асинхронной операции (custom memory allocation) - память из memory pool? При этом, чтобы исключить синхронизацию между потоками, создать для каждого потока свой memory pool. Возможно использовать вместо shared_ptr - intrusive_ptr. При все этом не потерять преимущества архитектуры использованной в asio-samples, насколько это вообще технически возможно.. А вот чтобы сравнить две модели мне и нужно иметь какую-то тестовую тулзу + сценарий выполнения тестов.. Это сообщение отредактировал(а) rumit7 - 21.10.2011, 08:20 |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 13 Всего: 110 |
грубо говоря - да. но можно иначе: кол-во сессий обычно ограниченно сверху. т.е. можно просто создать пул сессий, к примеру по максимуму, 65К, и поместить их в какой-то recycled-buffed/queue. каждая сессия содержит свои аллокаторы для custom_memory_allocation. таким образом полностью пропадает необходимость в memory_pool для служебных данных(собственно asio-samples и их echo_server так(ну, почти так) и реализован). но остаются еще буфера для пользовательских данных... Это сообщение отредактировал(а) boostcoder - 21.10.2011, 08:23 |
|||
|
||||
| rumit7 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Да у меня возникла такая-же идея при изучении примеров из asio-samples. Если, как Вы говорите, преаллоцировать память для всех сессий, то соответственно упростится та схема, которую я описал выше. Следовательно остается только memory_pool-ы для пользовательских данных.. Над этим нужно подумать.. Спасибо! |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 13 Всего: 110 |
тут можно поступить следующим образом, влоб: т.к. кол-во асинхронных операций так же ограничено сверху двумя, то в объекте сессии, так же можно предаллоцировать их, выбрав при этом необходимый объем. к примеру 32к. и того: WA+RA+TA+WB+RB*65к=~4Gb где: WA - allocator for write handlers(session.hpp:360) RA - allocator for read handlers(session.hpp:361) TA - allocator for timer handlers(session.hpp:362) WB - allocator for write buffer RB - allocator for read buffer но, в реале сессий все же меньше. Добавлено @ 08:50 собственно, такой способ преаллокации_всего дает два плюса: 1)устраняет проблему фрагментации памяти, 2)устраняет run-time оверхед memory_poll`ов. Up. и 4Gb для подобных задач - совсем не много. на самом деле, сессий все же меньше 65к, т.к. часть портов зарезервирована_системой/занята_другими_программами. Это сообщение отредактировал(а) boostcoder - 21.10.2011, 09:02 |
|||
|
||||
| rumit7 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Спасибо! Вот только как эта массовая предаллокация скажется на других задачах выполняющихся на сервере? У нас например возможна ситуация, когда на одном и том-же железе работать будет как наш сервер-приложение, так и стороннее приложение, в взаимодействии с которым мы фактически и выполняем работу..
Но ведь использование memory-pool также решает проблему фрагментации памяти, а run-time оверхед не такой уж и большой, если исключить синхронизацию между потоками!? При этом memory pool можно настроить таким образом, чтобы лишняя память освобождалась.. |
|||
|
||||
| boostcoder |
|
||||||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 13 Всего: 110 |
никак
и
= противоречие. это зависит... но он есть. мое скромное имхо - я бы вовсе не заморачивался с экономией памяти, т.к. 16Gb это не какой-то космический объем. |
||||||
|
|||||||
| rumit7 |
|
||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 16.6.2011 Репутация: нет Всего: 7 |
Здесь я имел ввиду следующее - если в пик активности сервера памяти в memory pool не достаточно, то соот. выделяется еще один дополнительный блок (может быть даже х2 размера от предыдущего) и так циклически; после того как активность спадает, то из всего этого выделенного пространства будет реально использоваться куда меньше.. Так вот этот излишек можно вернуть (разумеется оставить с запасом), чтобы избежать свопинга..
Спасибо большое! |
||||||||
|
|||||||||
| mabrarov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Стратегию "io_service per CPU" вроде как используют в Yandex. Она позволяет исключить миграцию, например, экземпляров ma::echo::server::session между кэшами разных ядер/процессоров. Т.е. все ma::echo::server::session, относящиеся к одному экземпляру io_service, теоретически могут влезть (и не вылазить от туда в течение всей работы) в кэш одного ядра. Кроме того, это избавляет от необходимости защищать ma::echo::server::session при помощи io_service::strand (который тоже не бесплатно дается и ОС и процессору). Я подумывал дать возможность в echo_server использовать такую стратегию для ma::echo::server::session (указывая это как параметр CLI). Но пока не решил вопрос с рапределением ma::echo::server::session по набору экземпляров io_service. Здесь нужна какая-то статистика с каждого io_service, которая тоже будет отнимать ресурсы и время. Стратегии "single io_service + thread pool" и "one io_service for session manager + one io_service for all sessions" почти одно и то же. Во втором случае ma::echo::server::session_manager вынесен отдельно аля SEDA. Это сделано для гарантии того, что даже при максимальной загрузке ma::echo::server::session_manager (простейшая DOS-атака) на обработку сессий будет потрачено не менее определенной части всего процессорного времени, выделенного на процесс сервера. Ну и да, тестировать и еще раз тестировать. "Золотая тропа" известна: make it build and work, make it work right, if need (!) make it (more) fast. Стратегия "one io_service for session manager + one io_service for all sessions" остановилась на втором шаге. Возможно, на третьем шаге стратегия "io_service per CPU" победит. Однако, эффективная реализация "io_service per CPU" м/б сложнее "one io_service for session manager + one io_service for all sessions". |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Сети | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |