Как выполнить код асинхронно без создания новых потоков - PullRequest
3 голосов
/ 15 апреля 2020

Я использую Qt SQL, который блокирует API, поэтому я должен выполнить SQL код в отдельном потоке (QtConcurrent :: run) и вернуть (Q) в будущем.

примерно так: -

QFuture<QString> future = QtConcurrent::run( []() { /* some SQL code */ } );

auto  watcher = new QFutureWatcher<QString>();

watcher.setFuture(future);

connect(watcher,&QFutureWatcher<QString>::finished,
               [future](){ /* code to execute after future is finished */ });

Но я узнал, что многопоточность стоит дорого. каждое переключение контекста стоит дорого. Таким образом, похоже, что загрузка процессора приводит к потере нового потока только для ожидания результата с сервера MySQL. В любом случае мое приложение будет работать на одноядерной виртуальной машине в Google Cloud. есть ли какой-нибудь способ, которым я могу выполнить код Qt SQL асинхронно без возможности создания нового потока?

Мне также было интересно, как другие API, такие как Qt Networking, реализуют асинхронный API без создания нового потока? или я не прав и они создают новую тему под капотом?

Ответы [ 2 ]

2 голосов
/ 15 апреля 2020

Используя QtConcurrent::run, вы уже решили одну проблему - стоимость создания потока, поскольку он использует пул потоков.

Что касается переключения контекста, сначала вы можете попытаться измерить их с помощью perf stat. И зависит от ситуации, оптимизировать ее. Если это просто простые запросы, то, вероятно, подавляющее большинство переключений контекста происходит из системы, а не из вашего приложения.

Выполнение асинхронных операций c означает, что вы можете выполнить задачу и перейти к текущему коду без ожидания результатов. Но обычно такая задача, т.е. запрос sql, порождает поток / процесс или отправляет запрос в ОС.

Qt Networking make, т.е. запрос на чтение и сигналы ОС (epoll), когда данные поступят. Но в случае одноядерной ОС все равно прервет ваш поток.

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

2 голосов
/ 15 апреля 2020

Многие многопоточные приложения работают на одном ядре. Очистка кеша для запуска на отдельном ядре также стоит дорого. Используйте правильный инструмент для работы. С потоками все в порядке.

Тем не менее, если вы действительно хотите работать в одном потоке, используйте рабочую очередь, чтобы отслеживать ход выполнения асин c. Библиотека libevent делает это для вас, но есть и другие. Вы просто запускаете опрос l oop, добавляете работу в очередь и выполняете обратные вызовы, когда задача требует внимания или завершается.

...