Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Оценка эффективности ASIO сервера 
:(
    Опции темы
rumit7
Дата 20.10.2011, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Здравствуйте!

В данный момент активно занялся изучением возможностей Boost::ASIO. Впечатления от самой библиотеки только самые положительные, давно мне так сильно ничего не нравилось, наверно с тех самых пор, как я познакомился с С++, лет так 8 назад)

Изучая ASIO ExamplesASIO Samples, а также другие примеры в сети, задумался над выработкой критериев для сравнения различных моделей построения асинхронного сервера, таких как (простите, не знаю как лучше перевести на русский):
  • io_service per cpu;
      
  • single io_service + thread pool;
      
  • one io_service for session manager + one io_service for all sessions;
      
  • ...

На данный момент меня интересует - преимущества и недостатки каждой из моделей, на основе чего можно было бы сделать выбор под конкретные требования сервера.. Я так понимаю, наиболее важные критерии это: 
  • скорость обработки запроса;
      
  • сложность реализации и поддержки;
      
  • отказоустойчивость;
      
  • ресурсопотребляемость;
      
  • что-то еще.

Как правильнее оценить? Что обычно применяют в таких случаях? Какие-то утилиты вроде Jmeter? Или что-то еще? Обращаюсь к Вам с просьбой помочь разобраться в теме..

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

Код

#include <cstdlib>
#include <cstring>
#include <iostream>

#include <string>
#include <deque>
#include <vector>

#include <boost/ref.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

namespace ba = boost::asio;

typedef boost::shared_ptr<ba::io_service> io_service_ptr;
typedef boost::shared_ptr<ba::deadline_timer> deadline_timer_ptr;


enum { max_length = 1024 };


void start_work(const io_service_ptr & io_service, ba::ip::tcp::resolver::iterator iterator, ba::deadline_timer::duration_type * used_time);

size_t get_thread_num(int argc, char* argv[]);


int main(int argc, char* argv[])
{
    try
    {
        if(argc != 3 && argc != 4)
        {
            std::cerr << "Usage: blocking_tcp_echo_client <host> <port> <thread_num = 2>" << std::endl;
            return 1;
        }
        
        /// 1. Resolve connection
        ba::io_service io_service;
        ba::ip::tcp::resolver resolver(io_service);
        ba::ip::tcp::resolver::query query(ba::ip::tcp::v4(), argv[1], argv[2]);
        ba::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
        
        /// 2. The running time calculation
        std::string str_expires = boost::posix_time::to_simple_string(
            ba::deadline_timer::traits_type::now() 
                + boost::posix_time::seconds(4)
        );
        
        /// 3. The number of threads to be used
        const size_t thread_num = get_thread_num(argc, argv);

        // The pool of io_services, timers.
        std::deque<io_service_ptr> io_services;
        std::deque<deadline_timer_ptr> deadline_timers;
        
        std::vector<ba::deadline_timer::duration_type> used_time(thread_num);
        
        for(size_t i = 0; i < thread_num; ++i)
        {
            io_service_ptr ios = boost::make_shared<ba::io_service>();
            
            deadline_timer_ptr dt = boost::make_shared<ba::deadline_timer>(
                boost::ref(*ios),
                boost::posix_time::time_from_string( str_expires.c_str() )
            );
            
            dt->async_wait( boost::bind(&start_work, ios, iterator, &used_time[i]) );
            
            io_services.push_back(ios);
            deadline_timers.push_back(dt);
        }
        
        /// Create a pool of threads to run all of the io_services.
        boost::thread_group thread_group;
        
        for(size_t i = 0; i < thread_num; ++i)
        {
            thread_group.create_thread( boost::bind(&ba::io_service::run, io_services[i]) );
        }

        // wait until all thread will finished
        thread_group.join_all();
        
        /// Calculate time used by all threads
        ba::deadline_timer::duration_type all_time;
        
        for(size_t i = 0; i < thread_num; ++i)
        {
            all_time += used_time[i];
        }
        
        std::cout << "END with " << all_time << std::endl;
    }
    catch(std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}


void start_work(const io_service_ptr & io_service, ba::ip::tcp::resolver::iterator iterator, ba::deadline_timer::duration_type * used_time)
{
    ba::deadline_timer::time_type tm1 = ba::deadline_timer::traits_type::now();
        
    //std::cout << "Thread started at " << tm1 << std::endl;

    for(int i = 0; i<1000; i++)
    {
        ba::ip::tcp::socket s(*io_service);
        ba::connect(s, iterator);

        for(int j = 0; j<100; j++)
        {
            char data[max_length];
            
            ba::write(s, ba::buffer(data, max_length));

            size_t reply_length = ba::read(s, ba::buffer(data, max_length));
        }
    }

    ba::deadline_timer::time_type tm2 = ba::deadline_timer::traits_type::now();
    
    //std::cout << "Thread end at " << tm2 << std::endl;
    //std::cout << "Time took : " << tm2-tm1 << std::endl;
    
    *used_time = tm2-tm1;
}


size_t get_thread_num(int argc, char* argv[])
{
    if(argc == 4)
        return boost::lexical_cast<size_t>( argv[3] );
    else
        return 2;
}

 

PM MAIL   Вверх
Lazin
Дата 20.10.2011, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 5
Всего: 154



Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
io_service per cpu;

если вы хотите что-бы все запросы от одного клиента выполнялись на одном процессоре, синхронизация в этом случае может быть проще, но только если обработчики запросов из разных io_service-ов не лезут в общую память за данными, если лезут то преимуществ никаких нет.
если вы хотите быстро и масштабируемо и, при этом без синхронизации - то не нужно использовать asio, asio это proactor, а вам нужно смотреть на библиотеки, реализующие reactor, в ace например есть, что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным

Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
single io_service + thread pool;

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

Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
one io_service for session manager + one io_service for all sessions;

не понял

Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
...

архитектура сервера это не то, сколько io_service-ов вы будете использоваться, это несколько более широкая тема, может быть вам вообще не стоит связываться со stateful архитектурой а забабахать sateless архитектуру без всяких сессий, но зато с преферансом и гимназистками?


Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
скорость обработки запроса;

asio это тонкая надстройка над io completion ports, по крайней мере под виндой, поэтому можно с уверенностью сказать, что скорость обработки запроса зависит от скорости обработки запроса smile 

Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
сложность реализации и поддержки;

it depends, явно проще чем использовать голый win api

Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
отказоустойчивость;

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

Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
ресурсопотребляемость;

некоторое количество памяти на каждую асинх. операцию ввода вывода, где-то ведь должен храниться ваш callback, чем их больше, тем больше тратится ресурсов. поэтому потребление ресурсов несколько непредсказуемо, чем больше всего происходит одновременно, чем больше асинхронных операций в процессе, тем больше нужно ресурсов
PM MAIL Skype GTalk   Вверх
boostcoder
Дата 21.10.2011, 01:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



rumit7, слишком уж абстрактно все у вас описано. можно долго распинаться описывая для вас то, что перепечатано во множестве книжек.
поконкретнее вопросы, пожалуйста.
PM WWW   Вверх
rumit7
Дата 21.10.2011, 06:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(boostcoder @ 21.10.2011,  01:05)
rumit7, слишком уж абстрактно все у вас описано. можно долго распинаться описывая для вас то, что перепечатано во множестве книжек.
поконкретнее вопросы, пожалуйста.


На данный момент меня интересует - скорость обработки запроса. Т.е. каким образом правильнее организовать сравнение по скорости обработки различных примеров, приводимых в ASIO Examples, ASIO Samples. Будут ли достоверными данные предоставляемые выше приведенной самописной тестовой тулзой? 
PM MAIL   Вверх
rumit7
Дата 21.10.2011, 06:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата

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


Я так понимаю здесь возможно использование memory pool на каждый проц и плюс к этому использование custom memory allocation, чтобы исключить обращение к общей памяти при выполнении асинхронных операций? 

Цитата

если вы хотите быстро и масштабируемо и, при этом без синхронизации - то не нужно использовать asio, asio это proactor, а вам нужно смотреть на библиотеки, реализующие reactor, в ace например есть, что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным


Спасибо. Пока моя цель - "быстро и масштабируемо", но по возможности с использованием ASIO. А там будем делать выводы..

Цитата

Цитата

io_service for session manager + one io_service for all sessions

не понял


Это модель применена в ASIO Samples, когда один io_service (+ 1 или 2 потока) используется для акцепта клиентов, создания сессий и управления ими, а второй io_service (+ по потоку на каждый проц) используется всеми сессиями (т.е. взаимодействие с клиентами). 

Цитата

архитектура сервера это не то, сколько io_service-ов вы будете использоваться, это несколько более широкая тема


Да я это понимаю. На данный момент я бы хотел выяснить: какой из моделей способов использования ASIO библиотеки дает больший перформанс и в каких случаях? Просто сравнивать примеры эхо серверов это глупо, яный пень в реальном проекте гораздо больше взаимодействий между различными факторами.. Но нужно же как-то выбрать. Следовательно нужно выполнить сравнение прототипов, думаю на первом этапе по скорости обработки клиентов. Здесь у меня начинается ступор - как лучше организовать сравнительный тест?

Цитата

может быть вам вообще не стоит связываться со stateful архитектурой а забабахать sateless архитектуру без всяких сессий, но зато с преферансом и гимназистками?


Спасибо за Ваш ответ!
PM MAIL   Вверх
rumit7
Дата 21.10.2011, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(Lazin @ 20.10.2011,  22:24)
Цитата(rumit7 @  20.10.2011,  21:12 Найти цитируемый пост)
io_service per cpu;

если вы хотите быстро и масштабируемо и, при этом без синхронизации - то не нужно использовать asio, asio это proactor, а вам нужно смотреть на библиотеки, реализующие reactor, в ace например есть, что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным

Из документации Boost::ASIO:

Цитата

As you already know, the asio library provides a guarantee that callback handlers will only be called from threads that are currently calling boost::asio::io_service::run(). Consequently, calling boost::asio::io_service::run() from only one thread ensures that callback handlers cannot run concurrently.


Это ведь значит, что и с использованием ASIO можно добиться "что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным"?
PM MAIL   Вверх
boostcoder
Дата 21.10.2011, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(rumit7 @  21.10.2011,  06:46 Найти цитируемый пост)
Это модель применена в ASIO Samples, когда один io_service (+ 1 или 2 потока) используется для акцепта клиентов, создания сессий и управления ими, а второй io_service (+ по потоку на каждый проц) используется всеми сессиями (т.е. взаимодействие с клиентами).

я и сам использую реализацию из asio-samples построенную на этой архитектуре, и, мое имхо - это лучшая архитектура. т.к. обладает высокой скоростью accepta+reusing_sessions, что позволит пережить большинство DDOS атак, так и тем что второй io_service существует в единственном экземпляре, что позволяет при использовании strand`ов избавится от прямой необходимости в синхронизации.


ну а тестирование_производительности/сравнение_производительности - это очень субъективно и зависимо... smile

Добавлено через 3 минуты и 30 секунд
Цитата(rumit7 @  21.10.2011,  07:42 Найти цитируемый пост)
Это ведь значит, что и с использованием ASIO можно добиться "что-бы вся бизнес логика была в одном потоке, на одном ядре, а весь I/O был асинхронным"?

да. при использовании двух и более io_service`ов. но в этом случае всю синхронизацию придется обеспечивать руками. а в этом случае, не факт что такая архитектура будет обладать большей производительностью.
PM WWW   Вверх
rumit7
Дата 21.10.2011, 08:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(boostcoder @ 21.10.2011,  07:44)
я и сам использую реализацию из asio-samples построенную на этой архитектуре, и, мое имхо - это лучшая архитектура. т.к. обладает высокой скоростью accepta+reusing_sessions, что позволит пережить большинство DDOS атак, так и тем что второй io_service существует в единственном экземпляре, что позволяет при использовании strand`ов избавится от прямой необходимости в синхронизации.

...

да. при использовании двух и более io_service`ов. но в этом случае всю синхронизацию придется обеспечивать руками. а в этом случае, не факт что такая архитектура будет обладать большей производительностью.

Я хочу объеденить два подхода: показанный в примерах asio-samples и io_service на каждый проц. 

Идея заключается в том, чтобы по возможности локализовать обращение к памяти внутри одного проца (потока). Для этого выделять память, как для объектов сессий, так и для каждой асинхронной операции (custom memory allocation) - память из memory pool? При этом, чтобы исключить синхронизацию между потоками, создать для каждого потока свой memory pool. Возможно использовать вместо shared_ptr - intrusive_ptr. 

При все этом не потерять преимущества архитектуры использованной в asio-samples, насколько это вообще технически возможно..


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

Это сообщение отредактировал(а) rumit7 - 21.10.2011, 08:20
PM MAIL   Вверх
boostcoder
Дата 21.10.2011, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(rumit7 @  21.10.2011,  08:08 Найти цитируемый пост)
Для этого выделять память, как для объектов сессий, так и для каждой асинхронной операции (custom memory allocation) - память из memory pool?

грубо говоря - да.
но можно иначе: кол-во сессий обычно ограниченно сверху. т.е. можно просто создать пул сессий, к примеру по максимуму, 65К, и поместить их в какой-то recycled-buffed/queue. каждая сессия содержит свои аллокаторы для custom_memory_allocation. таким образом полностью пропадает необходимость в memory_pool для служебных данных(собственно asio-samples и их echo_server так(ну, почти так) и реализован). но остаются еще буфера для пользовательских данных...

Это сообщение отредактировал(а) boostcoder - 21.10.2011, 08:23
PM WWW   Вверх
rumit7
Дата 21.10.2011, 08:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(boostcoder @ 21.10.2011,  08:20)
грубо говоря - да.
но можно иначе: кол-во сессий обычно ограниченно сверху. т.е. можно просто создать пул сессий, к примеру по максимуму, 65К, и поместить их в какой-то recycled-buffed/queue. каждая сессия содержит свои аллокаторы для custom_memory_allocation. таким образом полностью пропадает необходимость в memory_pool для служебных данных(собственно asio-samples и их echo_server так и реализован). но остаются еще буфера для пользовательских данных...

Да у меня возникла такая-же идея при изучении примеров из asio-samples. 

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

Над этим нужно подумать.. Спасибо!
PM MAIL   Вверх
boostcoder
Дата 21.10.2011, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(rumit7 @  21.10.2011,  08:27 Найти цитируемый пост)
Следовательно остается только memory_pool-ы для пользовательских данных..

тут можно поступить следующим образом, влоб: т.к. кол-во асинхронных операций так же ограничено сверху двумя, то в объекте сессии, так же можно предаллоцировать их, выбрав при этом необходимый объем. к примеру 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
PM WWW   Вверх
rumit7
Дата 21.10.2011, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(boostcoder @ 21.10.2011,  08:40)
Цитата(rumit7 @  21.10.2011,  08:27 Найти цитируемый пост)
Следовательно остается только memory_pool-ы для пользовательских данных..

тут можно поступить следующим образом, влоб: т.к. кол-во асинхронных операций так же ограничено сверху двумя, то в объекте сессии, так же можно предаллоцировать их, выбрав при этом необходимый объем. к примеру 32к.
и того: WA+RA+TA+WB+RB*65к=~4Gb
где:
WA - allocator for write handlers
RA - allocator for read handlers
TA - allocator for timer handlers
WB - allocator for write buffer
RB - allocator for read buffer

но, в реале сессий все же меньше.

Спасибо! Вот только как эта массовая предаллокация скажется на других задачах выполняющихся на сервере? 

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

Цитата

Добавлено @ 08:50
собственно, такой способ преаллокации_всего дает два плюса: 1)устраняет проблему фрагментации памяти, 2)устраняет run-time оверхед memory_poll`ов.


Но ведь использование memory-pool также решает проблему фрагментации памяти, а run-time оверхед не такой уж и большой, если исключить синхронизацию между потоками!? При этом memory pool можно настроить таким образом, чтобы лишняя память освобождалась..
PM MAIL   Вверх
boostcoder
Дата 21.10.2011, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(rumit7 @  21.10.2011,  09:03 Найти цитируемый пост)
Вот только как эта массовая предаллокация скажется на других задачах выполняющихся на сервере?

никак smile вот только памяти должно быть в достатке. иначе свопинг сожрет всю! производительность. но сервера, обычно, имеют минимум 8Gb. обычно 16.

Цитата(rumit7 @  21.10.2011,  09:03 Найти цитируемый пост)
Но ведь использование memory-pool также решает проблему фрагментации памяти

и
Цитата(rumit7 @  21.10.2011,  09:03 Найти цитируемый пост)
memory pool можно настроить таким образом, чтобы лишняя память освобождалась

 = противоречие.

Цитата(rumit7 @  21.10.2011,  09:03 Найти цитируемый пост)
а run-time оверхед не такой уж и большой

это зависит... но он есть.
мое скромное имхо - я бы вовсе не заморачивался с экономией памяти, т.к. 16Gb это не какой-то космический объем.
PM WWW   Вверх
rumit7
Дата 21.10.2011, 09:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата

Цитата(rumit7 @  21.10.2011,  09:03 Найти цитируемый пост)
Но ведь использование memory-pool также решает проблему фрагментации памяти

и
Цитата(rumit7 @  21.10.2011,  09:03 Найти цитируемый пост)
memory pool можно настроить таким образом, чтобы лишняя память освобождалась

 = противоречие.


Здесь я имел ввиду следующее - если в пик активности сервера памяти в memory pool не достаточно, то соот. выделяется еще один дополнительный блок (может быть даже х2 размера от предыдущего) и так циклически; после того как активность спадает, то из всего этого выделенного пространства будет реально использоваться куда меньше.. Так вот этот излишек можно вернуть (разумеется оставить с запасом), чтобы избежать свопинга..

Цитата

мое скромное имхо - я бы вовсе не заморачивался с экономией памяти, т.к. 16Gb это не какой-то космический объем.


Спасибо большое!
PM MAIL   Вверх
mabrarov
Дата 21.10.2011, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

Репутация: нет
Всего: 9



Цитата(rumit7 @ 20.10.2011,  21:12)

  • io_service per cpu;
  • single io_service + thread pool;  
  • one io_service for session manager + one io_service for all sessions;  
  • ...

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

Стратегию "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".

PM MAIL WWW Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0709 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.