Russian Qt Forum
Март 28, 2024, 15:06
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
Очень многопоточная архитектура приложения.
Страниц: [
1
]
2
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Очень многопоточная архитектура приложения. (Прочитано 13372 раз)
RedDog
Частый гость
Offline
Сообщений: 221
Очень многопоточная архитектура приложения.
«
:
Май 07, 2018, 20:04 »
Есть некоторое приложение, с большим количеством разнообразных логик: БД, сеть, бизнес-логики N штук, логирование 4 вида.
До некоторого времени разрабатывалось по принципу: "в любой не понятной ситуации создавай отдельный QThread и суй в него свою очередную логику".
Итого, имеем: на БД создается в районе 50 нитей (много подключений, каждое в своем потоке), на сеть около 10 (здесь пул потоков, одна нить несколько подключений обслуживает), вся остальная логика еще на полтинничек тянет.
Делалось это с той целью, что бы одна "логическая единица" не мешала и не лочила работы других, потому как сервер и должен обслуживать клиентов в почти онлайн-режиме.
Вопрос вот в чем: стоит ли продолжать в таком духе и когда пора остановится?
Про пулы потоков в курсе, но есть сложности в определении свободной нити, что бы не лочить при тяжелых вычислениях.
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #1 :
Май 15, 2018, 21:13 »
Я извиняюсь, может вопрос не так задал?
Или все же нормальная практика делать для отдельной логики отдельную нить?
Записан
ssoft
Программист
Offline
Сообщений: 574
Re: Очень многопоточная архитектура приложения.
«
Ответ #2 :
Май 15, 2018, 22:12 »
Цитата: RedDog от Май 15, 2018, 21:13
Я извиняюсь, может вопрос не так задал?
Или все же нормальная практика делать для отдельной логики отдельную нить?
Какой ответ Вы хотите получить?
Если программа работает и хорошо себя чувствует, то, возможно, такой подход оправдан, так как прост и относительно надежен. Это с практической точки зрения.
Если смотреть с технической или академической точки зрения, то чем больше потоков, тем хуже себя чувствует диспетчер ОС.
Если у Вас задачи связанны с высокой производительностью и большими нагрузками, то имхо такой подход неприемлем, лучше посмотреть в сторону корутин буста, на std::future или еще куда-нибудь.
В общем, ответ зависит от критериев разумности в рамках решения конкретной задачи.
Записан
vic57
Чайник
Offline
Сообщений: 90
Re: Очень многопоточная архитектура приложения.
«
Ответ #3 :
Май 15, 2018, 23:03 »
Цитата: RedDog от Май 15, 2018, 21:13
Я извиняюсь, может вопрос не так задал?
Или все же нормальная практика делать для отдельной логики отдельную нить?
сервер по любому должен крутиться, а для БД может лучше async?
https://xydan.livejournal.com/8595.html
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #4 :
Май 16, 2018, 18:48 »
Цитата: ssoft от Май 15, 2018, 22:12
Какой ответ Вы хотите получить?
Если программа работает и хорошо себя чувствует, то, возможно, такой подход оправдан, так как прост и относительно надежен. Это с практической точки зрения.
Если смотреть с технической или академической точки зрения, то чем больше потоков, тем хуже себя чувствует диспетчер ОС.
Если у Вас задачи связанны с высокой производительностью и большими нагрузками, то имхо такой подход неприемлем, лучше посмотреть в сторону корутин буста, на std::future или еще куда-нибудь.
В общем, ответ зависит от критериев разумности в рамках решения конкретной задачи.
Пофантазируем...
К примеру есть 8 нитей (QList<QThread>). Есть 32 объекта (SomeWorker), которые должны обрабатывать свои слоты, не мешаясь друг другу.
В начальный момент времени я по какой то логике на каждую нить вешаю по 4 объекта.
Рандомно объекты начинают нагружаться.
Настает момент времени, когда на одной нитке объекты начинают мешать друг другу, следовательно какой то из объектов желательно в соседнюю перекинуть.
Задача в том, как найти наименее нагруженную нитку?
Пока смутно маячит решение в SomeWorker делать а-ля флажок (в каждом слоте?) работает конкретный экземпляр или "курит".
Тогда зная весь массив SomeWorker-ов можно пробежаться и найти нитку с наименьшим/наибольшим кол-вом работающих.
Можно ввести "веса" нагрузки для каждого SomeWorker-а.
Тогда берем наиболее загруженный поток, выдергиваем из него N SomeWorker-ов и кидаем в наименее загруженный.
Ну вот как то так...
М.б. у кого то еще какие мысли будут.
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #5 :
Май 16, 2018, 18:51 »
Цитата: vic57 от Май 15, 2018, 23:03
а для БД может лучше async?
Каждое подключение к БД работает в своем Qt-шном потоке.
Кстати, логика работы в БД во всей архитектуре, самая быстрая получается, дольше манарегы разгребают, все что из БД выкачалось.
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3257
Re: Очень многопоточная архитектура приложения.
«
Ответ #6 :
Май 16, 2018, 18:56 »
Идея такая - есть несколько рабочих потоков (пусть будет 4) разгребают сообщения. Если обработка занимает мало времени, то они обрабатывают напрямую и кидают сигнал дальше.
Если обработка долгая, то ставим задачу в тред пул, вешаем вотчера, асинхронно ждем сигнала от вотчера.
В целом, можно любую задачу класть в пул, но будут накладные расходы на задачах, которые проще обработать так.
Можно накрутить свой фреймворк поверх QFuture/QFutureInterface который бы исполнял задачу в том же потоке в зависимости от "веса" и сделать это универсально. Идея такая.
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #7 :
Май 16, 2018, 19:08 »
Цитата: Авварон от Май 16, 2018, 18:56
Идея такая - есть несколько рабочих потоков (пусть будет 4) разгребают сообщения.
Тут сложность в реализации, а именно 100500 логических единиц абсолютно разной направленности, с вообще не похожей архитектурой, и их слить в единый АПИ по генерации сообщений (по всей видимости однотипных), как мне видится, не реально.
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3257
Re: Очень многопоточная архитектура приложения.
«
Ответ #8 :
Май 16, 2018, 19:13 »
void run(std::function<void()>) да поможет вам
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Очень многопоточная архитектура приложения.
«
Ответ #9 :
Май 17, 2018, 05:53 »
Цитата: RedDog от Май 16, 2018, 18:48
В начальный момент времени я по какой то логике на каждую нить вешаю по 4 объекта.
Рандомно объекты начинают нагружаться.
А просто очередь задач (возможно с приоритетом)? При поступлении задачи кладете ее в очередь и сигнальчик всем ниткам. Каждая нитка достает задачу их очереди и выполняет ее, Нет задач - возвращается в run до след сигнала
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #10 :
Май 17, 2018, 19:13 »
Цитата: Igors от Май 17, 2018, 05:53
А просто очередь задач (возможно с приоритетом)?
Будете смеяться, но такая логика уже есть, и она сидит в своем потоке, и шлет сообщения остальным.
PS: вся сложность, что проект довольно большой, около 2000 цпп файлов, и рефакторинг, как я вижу, надо проводить "по верхам", т.е наследоваться от QThread и еще некоторый враппер объектов, которые по потокам раскидываются.
Есть некоторые мысли на этот счет, если вырастут в некий прототип, то выложу на рассмотрение.
Записан
ssoft
Программист
Offline
Сообщений: 574
Re: Очень многопоточная архитектура приложения.
«
Ответ #11 :
Май 18, 2018, 08:31 »
Цитата: RedDog от Май 17, 2018, 19:13
Есть некоторые мысли на этот счет, если вырастут в некий прототип, то выложу на рассмотрение.
Если требуется рефакторинг по "верхам", то прототип тут уже известен - Worker'ы вместо Thread'ов, работающие в пуле потоков.
Оставим Worker'у свою очередь сообщений, добавим признак, что сообщение отправлено в очередь пула потоков для обработки.
Далее такая логика с соответствующими блокировками:
При добавлении нового сообщения Worker'у, если признак обработки сообщения выставлен, то складываем сообщение в очередь Worker'а, если нет - формируем задание на выполнение и помещаем прямиком в пул потоков. Выставляем признак, что сообщение в обработке
Выполняем задание.
После завершения обработки очередного задания пытаемся получить у Worker'а сообщение для формирования нового задания, если есть - помещаем новое задание в очередь пула (или сразу выполняем, зависит от выбранной стратегии)
Такой подход обеспечит отсутствие параллельной работы в рамках каждого Worker'а (за исключением части с очередью сообщений), что здесь и требуется.
ОДНАКО!
Большинство средств Qt реализованы таким образом, что работать с экземплярами объектов можно только в том потоке, с которым ини связаны!
Это относится к сети, GUI, м.б. к SQL и т.п. Поэтому вышеописанный подход напрямую не заработает, придется костыли выдумывать и т.п.
Если ПО нормально функционирует и обеспечивает необходимые характеристики, то мой совет - не нужно ничего менять.
Добавляйте новый функционал по новым правилам, а старый модифицируйте только по мере необходимости.
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #12 :
Июль 09, 2018, 19:00 »
Попутный вопрос возник:
Есть некий WorkerMain живущий в своем QThread-е, подписанный на 100500 различных других Worker, которые тоже по ниткам раскиданы.
Необходимо циклично обрабатывать сигналы Worker-ов, таким образом, что бы не было оверхеда в WorkerMain.
Для этого берутся все Worker-ы и испускают по одному сигналу.
Следующий сигнал они не могут испускать, пока очередь сообщений WorkerMain не станет пуста.
Вопрос вот в чем: как достучаться до очереди сообщений QThread-а и узнать, есть ли там что, или она пустая?
Записан
ssoft
Программист
Offline
Сообщений: 574
Re: Очень многопоточная архитектура приложения.
«
Ответ #13 :
Июль 10, 2018, 07:37 »
Можно использовать Qt::BlockingQueuedConnection при соединении сигнала Worker со слотом MainWorker.
Тогда в очереди будет не более одного сигнала Worker одновременно.
Записан
RedDog
Частый гость
Offline
Сообщений: 221
Re: Очень многопоточная архитектура приложения.
«
Ответ #14 :
Июль 11, 2018, 21:24 »
Вопрос решился следующим образом:
переопределил eventFilter и в нем при событии QEvent::MetaCall делаю инкремент на входящие/исходящие сообщения
В псевдокоде это выглядит примерно тами образом:
Код:
bool MainWorker::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MetaCall)
{
QMetaCallEvent* metaEvent = static_cast<QMetaCallEvent*>(event);
if (nullptr != dynamic_cast<const InputWorker*>(metaEvent->sender()))
{
++m_queueCounter;
}
else if (nullptr != dynamic_cast<const OutputWorker*>(metaEvent->sender()))
{
if (--m_queueCounter == 0);
emit imFreeForJob();
}
}
}
Записан
Страниц: [
1
]
2
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...