Название: Очень многопоточная архитектура приложения. Отправлено: RedDog от Май 07, 2018, 20:04 Есть некоторое приложение, с большим количеством разнообразных логик: БД, сеть, бизнес-логики N штук, логирование 4 вида.
До некоторого времени разрабатывалось по принципу: "в любой не понятной ситуации создавай отдельный QThread и суй в него свою очередную логику". Итого, имеем: на БД создается в районе 50 нитей (много подключений, каждое в своем потоке), на сеть около 10 (здесь пул потоков, одна нить несколько подключений обслуживает), вся остальная логика еще на полтинничек тянет. Делалось это с той целью, что бы одна "логическая единица" не мешала и не лочила работы других, потому как сервер и должен обслуживать клиентов в почти онлайн-режиме. Вопрос вот в чем: стоит ли продолжать в таком духе и когда пора остановится? Про пулы потоков в курсе, но есть сложности в определении свободной нити, что бы не лочить при тяжелых вычислениях. Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Май 15, 2018, 21:13 Я извиняюсь, может вопрос не так задал?
Или все же нормальная практика делать для отдельной логики отдельную нить? Название: Re: Очень многопоточная архитектура приложения. Отправлено: ssoft от Май 15, 2018, 22:12 Я извиняюсь, может вопрос не так задал? Или все же нормальная практика делать для отдельной логики отдельную нить? Какой ответ Вы хотите получить? Если программа работает и хорошо себя чувствует, то, возможно, такой подход оправдан, так как прост и относительно надежен. Это с практической точки зрения. Если смотреть с технической или академической точки зрения, то чем больше потоков, тем хуже себя чувствует диспетчер ОС. Если у Вас задачи связанны с высокой производительностью и большими нагрузками, то имхо такой подход неприемлем, лучше посмотреть в сторону корутин буста, на std::future или еще куда-нибудь. В общем, ответ зависит от критериев разумности в рамках решения конкретной задачи. Название: Re: Очень многопоточная архитектура приложения. Отправлено: vic57 от Май 15, 2018, 23:03 Я извиняюсь, может вопрос не так задал? сервер по любому должен крутиться, а для БД может лучше async?Или все же нормальная практика делать для отдельной логики отдельную нить? https://xydan.livejournal.com/8595.html Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Май 16, 2018, 18:48 Какой ответ Вы хотите получить? Пофантазируем...Если программа работает и хорошо себя чувствует, то, возможно, такой подход оправдан, так как прост и относительно надежен. Это с практической точки зрения. Если смотреть с технической или академической точки зрения, то чем больше потоков, тем хуже себя чувствует диспетчер ОС. Если у Вас задачи связанны с высокой производительностью и большими нагрузками, то имхо такой подход неприемлем, лучше посмотреть в сторону корутин буста, на std::future или еще куда-нибудь. В общем, ответ зависит от критериев разумности в рамках решения конкретной задачи. К примеру есть 8 нитей (QList<QThread>). Есть 32 объекта (SomeWorker), которые должны обрабатывать свои слоты, не мешаясь друг другу. В начальный момент времени я по какой то логике на каждую нить вешаю по 4 объекта. Рандомно объекты начинают нагружаться. Настает момент времени, когда на одной нитке объекты начинают мешать друг другу, следовательно какой то из объектов желательно в соседнюю перекинуть. Задача в том, как найти наименее нагруженную нитку? Пока смутно маячит решение в SomeWorker делать а-ля флажок (в каждом слоте?) работает конкретный экземпляр или "курит". Тогда зная весь массив SomeWorker-ов можно пробежаться и найти нитку с наименьшим/наибольшим кол-вом работающих. Можно ввести "веса" нагрузки для каждого SomeWorker-а. Тогда берем наиболее загруженный поток, выдергиваем из него N SomeWorker-ов и кидаем в наименее загруженный. Ну вот как то так... М.б. у кого то еще какие мысли будут. Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Май 16, 2018, 18:51 а для БД может лучше async? Каждое подключение к БД работает в своем Qt-шном потоке.Кстати, логика работы в БД во всей архитектуре, самая быстрая получается, дольше манарегы разгребают, все что из БД выкачалось. Название: Re: Очень многопоточная архитектура приложения. Отправлено: Авварон от Май 16, 2018, 18:56 Идея такая - есть несколько рабочих потоков (пусть будет 4) разгребают сообщения. Если обработка занимает мало времени, то они обрабатывают напрямую и кидают сигнал дальше.
Если обработка долгая, то ставим задачу в тред пул, вешаем вотчера, асинхронно ждем сигнала от вотчера. В целом, можно любую задачу класть в пул, но будут накладные расходы на задачах, которые проще обработать так. Можно накрутить свой фреймворк поверх QFuture/QFutureInterface который бы исполнял задачу в том же потоке в зависимости от "веса" и сделать это универсально. Идея такая. Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Май 16, 2018, 19:08 Идея такая - есть несколько рабочих потоков (пусть будет 4) разгребают сообщения. Тут сложность в реализации, а именно 100500 логических единиц абсолютно разной направленности, с вообще не похожей архитектурой, и их слить в единый АПИ по генерации сообщений (по всей видимости однотипных), как мне видится, не реально.Название: Re: Очень многопоточная архитектура приложения. Отправлено: Авварон от Май 16, 2018, 19:13 void run(std::function<void()>) да поможет вам
Название: Re: Очень многопоточная архитектура приложения. Отправлено: Igors от Май 17, 2018, 05:53 В начальный момент времени я по какой то логике на каждую нить вешаю по 4 объекта. А просто очередь задач (возможно с приоритетом)? При поступлении задачи кладете ее в очередь и сигнальчик всем ниткам. Каждая нитка достает задачу их очереди и выполняет ее, Нет задач - возвращается в run до след сигналаРандомно объекты начинают нагружаться. Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Май 17, 2018, 19:13 А просто очередь задач (возможно с приоритетом)? Будете смеяться, но такая логика уже есть, и она сидит в своем потоке, и шлет сообщения остальным.PS: вся сложность, что проект довольно большой, около 2000 цпп файлов, и рефакторинг, как я вижу, надо проводить "по верхам", т.е наследоваться от QThread и еще некоторый враппер объектов, которые по потокам раскидываются. Есть некоторые мысли на этот счет, если вырастут в некий прототип, то выложу на рассмотрение. Название: Re: Очень многопоточная архитектура приложения. Отправлено: ssoft от Май 18, 2018, 08:31 Есть некоторые мысли на этот счет, если вырастут в некий прототип, то выложу на рассмотрение. Если требуется рефакторинг по "верхам", то прототип тут уже известен - Worker'ы вместо Thread'ов, работающие в пуле потоков. Оставим Worker'у свою очередь сообщений, добавим признак, что сообщение отправлено в очередь пула потоков для обработки. Далее такая логика с соответствующими блокировками:
Такой подход обеспечит отсутствие параллельной работы в рамках каждого Worker'а (за исключением части с очередью сообщений), что здесь и требуется. ОДНАКО! Большинство средств Qt реализованы таким образом, что работать с экземплярами объектов можно только в том потоке, с которым ини связаны! Это относится к сети, GUI, м.б. к SQL и т.п. Поэтому вышеописанный подход напрямую не заработает, придется костыли выдумывать и т.п. Если ПО нормально функционирует и обеспечивает необходимые характеристики, то мой совет - не нужно ничего менять. Добавляйте новый функционал по новым правилам, а старый модифицируйте только по мере необходимости. Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Июль 09, 2018, 19:00 Попутный вопрос возник:
Есть некий WorkerMain живущий в своем QThread-е, подписанный на 100500 различных других Worker, которые тоже по ниткам раскиданы. Необходимо циклично обрабатывать сигналы Worker-ов, таким образом, что бы не было оверхеда в WorkerMain. Для этого берутся все Worker-ы и испускают по одному сигналу. Следующий сигнал они не могут испускать, пока очередь сообщений WorkerMain не станет пуста. Вопрос вот в чем: как достучаться до очереди сообщений QThread-а и узнать, есть ли там что, или она пустая? Название: Re: Очень многопоточная архитектура приложения. Отправлено: ssoft от Июль 10, 2018, 07:37 Можно использовать Qt::BlockingQueuedConnection при соединении сигнала Worker со слотом MainWorker.
Тогда в очереди будет не более одного сигнала Worker одновременно. Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Июль 11, 2018, 21:24 Вопрос решился следующим образом:
переопределил eventFilter и в нем при событии QEvent::MetaCall делаю инкремент на входящие/исходящие сообщения В псевдокоде это выглядит примерно тами образом: Код: bool MainWorker::eventFilter(QObject *obj, QEvent *event) Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Сентябрь 03, 2018, 10:16 Заметил разное поведение приложения на разных ОСях.
При одинаковых условиях нагрузки под Вин серерером 2016 проц нагружен на 20-30%, под Дебианом на 70-80%, соответственно на последнем гораздо быстрее все работает. Куда посмотреть? Есть предположение, что синхронизация на мютексах под виндой медленнее работает. Название: Re: Очень многопоточная архитектура приложения. Отправлено: zhbr от Сентябрь 03, 2018, 14:56 может приоритеты процессов/ниток?
и в догонку: вы уверены что условия одинаковые? просто на вин сервере обычно ещё сервисы какие-то крутятся. я так понимаю под одинаковыми условиями понимается - на одном и том же физически компьютере, но в разных загруженных ОС? Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Сентябрь 03, 2018, 15:17 Исходники собраны одни и те же, насильно приоритеты ниток в коде не меняются.
Железки физически разные, но характеристики одинаковые по ядрам и частоте. Диски с примерно одинаковой скоростью. На виндовой тачке только памяти побольше 32гига против 16гиг линуксовой. На обоих локальный постгрес стоит с идентичными настройками. В винде проц и диск никакие службы не грузят. Название: Re: Очень многопоточная архитектура приложения. Отправлено: zhbr от Сентябрь 04, 2018, 08:15 а какие компиляторы использовались?
Название: Re: Очень многопоточная архитектура приложения. Отправлено: RedDog от Сентябрь 04, 2018, 09:52 Под виндой студийный 2015 х64, под линем гцц 4.9.2 тоже 64.
Qt 5.8 штатной поставки с их сайта, ничего не пересобиралось. ps: провёл тест - те же бинарники на 10-й винде, показывают такую же производительность, как и на дебиане. Из чего можно сделать вывод, что серверная винда как то по особому распределяет контексты потоков, и/или с локерами по другому работает. pps: от начала этой темы удалось перевести львиную долю отдельных ниток в пулы, кол-во потоков на все приложение значительно уменьшилось. |