计算型任务:线程池VS独立线程

问题

当我们面对以计算为主(对应以IO为主)的任务时,是选用线程池还是独立线程呢?

分析

这里举几个具体的示例:

这里有个前提,即提供的计算能力要超过需求,不管是单核性能还是多核性能

Chrome的webrtc音频采集

这里采用的是页面所在进程的主线程中的异步任务来实现的,其本质类似于只具有单线程的线程池。只不过是在每一帧显示事件循环的每个循环执行完所有既定任务后,统一再来执行这些异步任务。在每一帧运行的任务中,会执行音频采集及视频采集工作。

我们曾经遇到过一个问题,就是在主线程js部分或视频采集部分经过了较为复杂的处理(如二次采集与裁剪)导致单帧的循环耗时较长(>20ms),在Windows机器上会造成音频采集未能及时执行,加上Chrome默认音频采集的时间戳是按照采集次数乘以固定值来计算,所以如果错过了采集的数据,会导致音频时间戳比视频时间戳越来越慢的问题。

从这里得出一个经验,即执行实时性较强的任务,选择独立线程更为合适。如音视频采集,因为硬件或支持库需要及时被调用,如果使用线程池,如果线程池无法做到及时调度,容易被线程池内其他任务所阻塞导致问题。

这里同样得出一个经验,即执行耗时较长的任务,选择独立线程更为合适。因为如果放到线程池里,可能导致其他任务的执行时间受较大的影响。此时如果使用线程池,由于任务执行占用CPU时间较长,合理的线程池中线程数量与每个任务单独开启线程相比,少开启线程来减少资源占用的优势已经不大,且使用线程池必须把任务的上下文进行包装,这也增加了开发的成本。

视频编解码

这里建议采用独立线程来实现。主要考虑两种情况,一种是软编软解,另一种是硬编硬解。两种情况毫无疑问均会导致较长的时间占用。要么是直接占用CPU,单核或多核10ms左右甚至更长,另一种是CPU处于不干活但是要等待系统硬解API返回,基本也得10ms甚至更高。所以在耗时如此长的情况下,直接放入线程池,会显著影响线程池中其他任务的执行时间。

音视频滤镜

这里建议放在线程池里实现。因为单个任务占用的计算时间较短,单独启动和结束线程开销可以比肩执行开销,这么做不合适。

选择

影响选择的因素有很多,这里只考虑实时性和耗时两个因素。实时性要求高,偏好选择独立线程。耗时长,偏好选择独立线程;耗时短,偏好选择线程池。实际选择并非只受理论分析影响,而是要考虑工程实现,有时可能仅仅因为把计算任务需要反复使用的上下文包裹成可以进入队列的元素的难度和风险以及耗时而放弃使用线程池实现。