
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.30] |
![]() |
|
Страницы: (16) « Первая ... 6 7 [8] 9 10 ... 15 16 все ( Перейти к последнему сообщению ) |
Сообщ.
#106
,
|
|
|
Цитата Flex Ferrum @ А расскажите, в каких областях требуется управлять тысячам (или сотнями тысяч) подписчиков в рамках паттерна publisher-subscriber? Мне вот даже интересно стало. У меня сейчас ~4000 коннектов по сокетам на сервере, это постоянных, на подписке. Каждый из них в свою очередь подписываются на какие-то данные, изменения данных, в рамках того самого паттерна. Примерно раз в секунду происходит коннект-дисконнект, какие-то коннекты отваливаются, но в основном сидят подолгу. Подписаны они на события из базы данных и котировки. Обновления идут очень часто. По событиям из базы данных вызываются процедуры, вообще асинхронно, но определённая синхронизация есть, иначе никаких потоков не хватит. Ещё выполняются скрипты, JavaScript - google V8, тоже асинхронно. Область - веб-сервер начитывает данные с моего сервера. Онлайн-брокер. Цитата Flex Ferrum @ Кстати, в твоём примере выше ты зачем-то дважды по списку пробегаешься при нотификации. Кстати, в моём примере, благодаря отказу от чудовищной Unsubscribe, появилась возможность избежать этой двойной пробежки (или копирования, что одно и тоже): - под блокировкой сделать move; - пробежаться по списку, вызвать функции или удалить отписавшихся; - под блокировкой сделать splice. Тогда можно будет вообще забыть 10 у тебя клиентов или 10000. Цитата Flex Ferrum @ И я, образно говоря, не вижу смысла покупать бентли только чтобы на дачу ездить. У меня в проекте другие узкие места, которые требуют агрессивной оптимизации. Это не вопрос "агрессивной оптимизации", это скорее вопрос гигиены. |
Сообщ.
#107
,
|
|
|
А каждый подписывается на свои виды котировок и все получают всё?
|
Сообщ.
#108
,
|
|
|
Каждый на свой перечень, подписка идёт от клиента, из браузера
|
Сообщ.
#109
,
|
|
|
Я бы предложил тебе в сторону того, как реализован гугловый gRpc. Возможно, подсмотришь чего интересное. А пока такой вопрос: ты уверен, что правильный паттерн выбрал для реализации? И самое узкое место - в работе с shared-указателями?
|
Сообщ.
#110
,
|
|
|
Цитата Flex Ferrum @ А пока такой вопрос: ты уверен, что правильный паттерн выбрал для реализации? И самое узкое место - в работе с shared-указателями? Ну, реализация паттерна, как ты заметил, примерно такая же, как у тебя. Кроме той блокировки, отличий, собственно, не найдёшь. У тебя хорошая, очень грамотная реализация (кроме Unsubscribe!!!). Проблема в том, что mutex занимает слишком много памяти, при работе с большими массивами данных это дорого. Ну и блокировки - основная беда. Кода очень много, следить за всем очень сложно, поэтому пытаешься сделать так, чтобы сами классы не допускали возможность дедлоков. Добавлено Цитата Flex Ferrum @ Wizard Профиль · PM Поощрения: 25 Dgm Рейтинг (т): [ 495 ] Я бы предложил тебе в сторону того, как реализован гугловый gRpc. Возможно, подсмотришь чего интересное. Дай ссылку. Хотя я не любитель гугловских реализаций. Интерфейс V8 написан школьником задней левой ногой. Я себе всю башку сломал, пока худо-бедно разобрался, сто раз пожалел, что связался. |
Сообщ.
#111
,
|
|
|
Цитата Олег М @ Цитата Flex Ferrum @ А пока такой вопрос: ты уверен, что правильный паттерн выбрал для реализации? И самое узкое место - в работе с shared-указателями? Ну, паттерн, как ты заметил, примерно такой же, как у тебя. Кроме той блокировки, отличий. Так вот я и не уверен, что pub-sub тут подходит. Тут наклевывается реактор с producer-consumer или авторами (тут недалеко есть темка с SObjectizer). И асинхронной рассылкой данных. Кстати, смысла так упарываться со сморт-поинтерами, атомиками и прочим особого не вижу. Освобождение ресурсов, связанных с конкретным коннектом, занимает дохрена времени само по себе. Как, впрочем, и отправка данных в сеть. |
Сообщ.
#112
,
|
|
|
Я очень слабо разбираюсь в паттернах, названия мне ничего не говорят
Собственно, сервер подписок работает примерно по той же схеме - копия списка под блокировкой, обработка и т.д. Только обработка заключается в том, что - для каждого подписчика запускается поток из пула - он получает список изменённых данных, либо сообщения - вызывает функцию подписчика С указателями не упарываешься - написал один раз и забыл навсегда Добавлено Цитата Flex Ferrum @ Тут наклевывается реактор с producer-consumer или авторами (тут недалеко есть темка с SObjectizer). Где? |
Сообщ.
#113
,
|
|
|
Тем не менее. Я так и не уверен, что мой код работает. Кто–нибудь может мне объяснить помогло добавление volatile к std::atomic или нет? Если помогло, то каким образом?
|
Сообщ.
#114
,
|
|
|
Цитата Олег М @ Это не вопрос "агрессивной оптимизации", это скорее вопрос гигиены. Ну, мы, чай, не на олимпиаде по программированию, на которой надо сходу придумать наиболее оптимальный и быстрый алгоритм из возможных. Оптимизация должна делаться с умом и, по сути, нет нужды оптимизировать код, который (будучи исследован инструментальными средствами) в оптимизации не нуждается. Ссылки: GRPC SObjectizer 5.3.0 Цитата Олег М @ Я очень слабо разбираюсь в паттернах, названия мне ничего не говорят Собственно, сервер подписок работает примерно по той же схеме - копия списка под блокировкой, обработка и т.д. Только обработка заключается в том, что - для каждого подписчика запускается поток из пула - он получает список изменённых данных, либо сообщения - вызывает функцию подписчика Давай разберёмся. У тебя некий сервер, работающий с браузерами по протоколу HTTP/HTTPS 1.1 (минимум). Браузеры коннектятся к серверу, формируют запрос на котировки, после чего сервер по установленному соединению шлёт запрошенные котировки, пока клиент не отвалится. Таких клиентов - штук 4000 минимум. Чтобы отправить котировки сервер должен обратиться к БД, выбрать нужные, определить клиентов, которым нужны те или иные тикеты, после чего сформировать ответы и послать. В виде, видимо, JSON. Вопрос номер раз: ты уверен, что игрища с "коллекциями подписчиков" - это наиболее горячее место, требующее оптимизации? А что сказал какой-нибудь Intel VTune? Он вообще что-нибудь сказал? Вопрос номер два: почему, собственно, тебя беспокоит скорость подписки/отписки клиентов в "менеджере подписок", если это заведомо тяжёлые операции? В первом случае - получить запрос (в виде текста, замечу), распарсить, что-нибудь куда-нибудь положить, модифицировать список получаемых из БД тикетов. Отписка - освободить все ресурсы, память, модифицировать запрос к БД и т. п. Вопрос номер три: верно ли утверждение, что данные о тикетах отправляются сразу в сокет и в текстовом виде? Если да, то тебя на фоне этой операции действительно беспокоит, насколько долго будут лочится списки подписчиков? Уточню: надо сформировать HTTP-ответ (в текстовом виде), зашифровать его (если работа по SSL), отправить в сокет (пусть и асинхронно), отхендлить ошибки типа отвалившихся клиентов, внезапно упавшей сети и прочие прелести. Кроме того, 4000 клиентов - это не то, чтобы много, на самом деле, для веб-сервиса. Вопрос номе четыре: (главный, возвращаясь, так сказать, к началу комментария) а какова, собственно, цель оптимизации? Написать for fun потокобезопасный SmartPointer - это, конечно, весело. Но при работе с продакшен-кодом любая активность должна иметь некую цель, завязанную на бизнес-задачи. В данном случае какую проблему ты решаешь, пытаясь оптимизировать одни этот конкретный участок? И тот ли участок ты оптимизируешь? |
Сообщ.
#115
,
|
|
|
Цитата Flex Ferrum @ Давай разберёмся. У тебя некий сервер, работающий с браузерами по протоколу HTTP/HTTPS 1.1 (минимум). Браузеры коннектятся к серверу, формируют запрос на котировки, после чего сервер по установленному соединению шлёт запрошенные котировки, пока клиент не отвалится. Таких клиентов - штук 4000 минимум. Чтобы отправить котировки сервер должен обратиться к БД, выбрать нужные, определить клиентов, которым нужны те или иные тикеты, после чего сформировать ответы и послать. В виде, видимо, JSON. Сервер, вернее один из серверов, - по сути просто кэширует данные, которые хранятся в базе данных и отдаёт их либо по rpc-запросу, либо по подписке клиенту. Данные в кэше обновляются асинхронно, по сигналам из базы. Ещё, по запросам выполняются ява-скрипты, которые получают данные из памяти сервера, делают какие-то вычисления и возвращают результат. Он не работает с браузеры, запросы идут от веб-серверов, по сокетам, TCP. Цитата Flex Ferrum @ Вопрос номер раз: ты уверен, что игрища с "коллекциями подписчиков" - это наиболее горячее место, требующее оптимизации? А что сказал какой-нибудь Intel VTune? Он вообще что-нибудь сказал? Вопрос номер два: почему, собственно, тебя беспокоит скорость подписки/отписки клиентов в "менеджере подписок", если это заведомо тяжёлые операции? В первом случае - получить запрос (в виде текста, замечу), распарсить, что-нибудь куда-нибудь положить, модифицировать список получаемых из БД тикетов. Отписка - освободить все ресурсы, память, модифицировать запрос к БД и т. п. Ну, во-первых я там ничего не оптимизирую, там и так всё нормально работает. Во-вторых, меня не беспокоит скорость подписки/отписки - куда ещё быстрее?. Это должно беспокоить тебя. Цитата Flex Ferrum @ Вопрос номер три: верно ли утверждение, что данные о тикетах отправляются сразу в сокет и в текстовом виде? Если да, то тебя на фоне этой операции действительно беспокоит, насколько долго будут лочится списки подписчиков? У меня не лочатся списки подписчиков. Все нотификации выполняются асинхронно и независимо от других. Я не могу допустить, чтоб все клиенты блокировались из-за одного, либо чтоб данные перестали обновляться, из-за того, что какая-то процедура тормозит. Вернее, определённые блокировки есть, но в основном для того чтоб контролировать количество запущенных потоков. Цитата Flex Ferrum @ Кроме того, 4000 клиентов - это не то, чтобы много, на самом деле, для веб-сервиса. У меня не веб-сервис. 4000 (тут, признаюсь, немного приврал, такой цифры я не видел. В среднем - 3500) это коннекты по веб-сокетам, постоянные. RPC-коннекты я не считаю, но в среднем где-то один в секунду. Цитата Flex Ferrum @ Вопрос номе четыре: (главный, возвращаясь, так сказать, к началу комментария) а какова, собственно, цель оптимизации? Написать for fun потокобезопасный SmartPointer - это, конечно, весело. Но при работе с продакшен-кодом любая активность должна иметь некую цель, завязанную на бизнес-задачи. В данном случае какую проблему ты решаешь, пытаясь оптимизировать одни этот конкретный участок? И тот ли участок ты оптимизируешь? У меня сервер работает на машине с 4 процессорами и 16Гб памяти. Хранит данные о 50тыс аккаунтов и 15тыс инструментов, постоянно обновляет их и рассылает подписчикам. Как ты думаешь у меня там есть возможность делать что-то не оптимально (хотя, конечно, косячу регулярно)? Потокобезопасный указатель означает, что мне не надо использовать дополнительных средств, ресурсов и блокировок при работе с этим классом. Это не от хорошей жизни, поверь. |
Сообщ.
#116
,
|
|
|
Цитата Олег М @ Тем не менее. Я так и не уверен, что мой код работает. Кто–нибудь может мне объяснить помогло добавление volatile к std::atomic или нет? Поиск мелких багов - довольно утомительная (хотя и интересная) работа. И не всегда простая. Кто-же выполнит её за тебя ? --- А что такое "volatile" ? Это запрет регистровой оптимизации для переменных. Т.е. если объявлена некая переменная, компилятор из соображений оптимизации может разместить переменную в регистр. Часто это бывает с счётчиками циклов. --- Ничего подробно не знаю про std::atomic. Но это шаблонный класс. Вряд ли его экземпляр разместят в регистре. Задача этого класса - гарантировать атомарность операций. Для его пользователя не важно, как он устроен внутри. |
Сообщ.
#117
,
|
|
|
Цитата ЫукпШ @ Поиск мелких багов - довольно утомительная (хотя и интересная) работа. И не всегда простая. Кто-же выполнит её за тебя ? Я не прошу выискивать мелкие баги, прошу лишь посмотреть на код свежим взглядом. Одна ошибка обнаружилась, вроде ты же на неё и указал, думаю, не особо копаясь в коде. Насчёт atomic - да, я тоже раньше думал, что ему не требуется volatile. Видимо, это не так. У него и методы идут парами - один с volatile, другой без. |
Сообщ.
#118
,
|
|
|
[quote=Flex Ferrum,1485242843,3703624]3. (важно!) обеспечивается синхронизация между отпиской клиента и его нотификацией. Если этой синхронизации не будет, то клиент (каждый!) должен будет работать из расчёта на то, что отписка ничего не гарантирует. И после отписки ему всё равно могут придти вызовы. Клиентов обычно очень расстраивает этот факт.[/quo
Не рассказал, как я решаю эту проблему (вернее, она решалась довольно коряво, стыдно было рассказывать). У меня тоже есть дескриптор подписчика, причём в единственном экземпляре, noncopyable. Он хранит у себя shared_ptr на подписчика(теперь CSharedPtr), дублирует его интерфейс (тут, наверное, можно было бы и унаследоваться). Но, методе reset() ждёт, чтобы все экземпляры на его указатель были уничтожены ![]() ![]() void reset() noexcept { if (!m_sp) return; TS::CWeakPtr<T> sp = m_sp; m_sp.reset(); while (!sp.expired()) std::this_thread::yield(); } |
Сообщ.
#119
,
|
|
|
Цитата Олег М @ Одна ошибка обнаружилась, вроде ты же на неё и указал, думаю, не особо копаясь в коде. Да я не полагал, что это - ошибка. Это недостаток. --- Попробуем сначала. 1. Будем писать шаблонный класс SP - группа объектов указывает на какой-то объект в памяти. SP должен уметь создать группу, уничтожить группу и объект, присоединиться к группе, отсоединиться от группы. Обеспечить доступ к объекту. Желательно возможность модификации объекта как-нибудь по-проще. 2. Имеется счётчик ссылок. 3. Предполагаем волюнтаристским способом, что создание или уничтожение группы - потокобезопасно (ПБ). Поскольку оба действия предполагают наличие только одного объекта SP. Достаточно таких возможностей ? 4. Значит, надо обеспечить ПБ только на изменение (инкремент/декремент) или установку значения счётчика ссылок. 5. Варианты создания объекта группы: a) с критической секцией. б) с использованием "Interlocked" функций WINAPI MSDN Выбирай, что больше нравится. Никто никого нигде специально не ждёт. Модифицируем переменную WINAPI функцией. Вроде всё. --- А что за клиент - если не секрет ? Игрушка ? |
Сообщ.
#120
,
|
|
|
Как раз это реальная ошибка, на поиски которой я б в последствии потратил бы кучу времени. Не скажу, что она явно проявилась, но в любом случае – тебе огромнейшее спасибо.
На остальные вопросы отвечу чуть позже. |