Чтобы воскресить этот старый поток, я просто выполнил простой тестовый код:
#include <thread>
int main(int argc, char** argv)
{
for (volatile int i = 0; i < 500000; i++)
std::thread([](){}).detach();
return 0;
}
Я скомпилировал это с g++ test.cpp -std=c++11 -lpthread -O3 -o test
. Затем я запускал его три раза подряд на старом (ядро 2.6.18) сильно загруженном (перестраивание базы данных) медленном ноутбуке (Intel Core i5-2540M). Результаты трех последовательных прогонов: 5,647 с, 5,515 с и 5,561 с. Таким образом, мы наблюдаем чуть более 10 микросекунд на поток на этой машине, возможно, намного меньше на вашей.
Это совсем немного, учитывая, что максимальный последовательный порт составляет около 1 бита на 10 микросекунд. Теперь, конечно, существуют различные дополнительные потери потоков, которые можно получить, используя переданные / захваченные аргументы (хотя сами вызовы функций могут навязывать некоторые), замедление кэширования между ядрами (если несколько потоков на разных ядрах сражаются за одну и ту же память одновременно), и т. д. Но в целом я очень сомневаюсь, что представленный вами сценарий использования окажет негативное влияние на производительность (и может дать преимущества, в зависимости от), несмотря на то, что вы уже превентивно назвали концепцию «действительно ужасным кодом», даже не зная, сколько времени требуется для запустить поток.
Хорошая идея или нет, во многом зависит от деталей вашей ситуации. За что еще отвечает вызывающий поток? Что именно участвует в подготовке и выписывании пакетов? Как часто они выписываются (с каким распределением: равномерным, кластерным и т. Д.?) И какова их структура? Сколько ядер у системы? И т.д. В зависимости от деталей, оптимальное решение может быть где угодно: от «вообще нет потоков» до «общего пула потоков» до «потока для каждого пакета».
Обратите внимание, что пулы потоков не являются волшебными и в некоторых случаях могут быть замедлением по сравнению с уникальными потоками, поскольку одним из самых больших замедлений с потоками является синхронизация кэшированной памяти, используемой несколькими потоками одновременно, и пулов потоков по их очень природа поиска и обработки обновлений из другого потока должна делать это. Таким образом, либо ваш основной поток, либо дочерний поток обработки могут застрять в ожидании, если процессор не уверен, изменил ли другой процесс часть памяти. Напротив, в идеальной ситуации уникальный поток обработки для данной задачи должен делить память со своей вызывающей задачей только один раз (когда она запускается), а затем они никогда больше не мешают друг другу.