LiteSetup 轻量级安装程序框架——多线程优化
LiteSetup 项目中,主要有两方面可以进行多线程优化:UI 与核心代码的分离,以及核心代码中压缩环节的多线程处理。
问题一:UI 与核心代码同线程导致假死
最初 UI 和核心代码运行在同一个线程中,容易出现界面假死现象。解决方案是将核心代码单独放到一个独立线程中执行,问题随之解决。伪代码如下:
...
void Compress()
{
std::thread t(...
{
...
});
t.detach();
}
...
问题二:单线程压缩速度不足
核心代码独立为一个线程后,压缩过程仍然只能利用一个 CPU 逻辑核心,速度不理想。
测试数据:打包约 450MB 的 ra2 资源,压缩占用时间 20s,IO 读写分别为 7s 和 0.2s。
可见性能瓶颈集中在压缩处理环节。
多线程压缩优化方案
优化思路如下:
- 压缩部分开启多线程支持——读取文件片段后立即启动一个线程进行压缩,完成后将结果添加到缓存队列,由管理线程统一调度。
- 为防止内存疯涨,限制当前文件缓存大小。例如缓存超过 100MB 时立刻执行写入。
- 当压缩线程数降为 0,表示压缩全部完成,随即将缓存中剩余数据写入文件,并处理后续事件。
整个流程中,压缩环节是多线程并行的;文件写入由某个压缩线程完成后触发;文件读取则在核心线程中完成。最后通过轮询判断压缩是否全部结束。
优化效果对比
测试数据涵盖完整的压缩流程(文件读取、数据压缩、文件写入):
优化前:整个打包过程耗时 25s。
优化后:整个打包过程缩短至 9s。
引入多线程后效率提升显著。虽然线程开销使等效时间有所增加(单线程压缩时间与多线程各线程压缩时间之和的差值为 36.912 - 23.461 = 13 秒),但总体效率提升约 3 倍。
部分核心代码
进一步优化方向
初步方案已取得不错的效果,但线程效率比仍有提升空间,可从以下几个方向继续优化:
- 通过线程池管理线程的创建与销毁,提高单个线程的利用效率。
- 文件写入(dump)环节引入多线程机制——原方案在某个压缩线程中执行写入,可能导致其他已完成压缩但尚未写入缓存的线程挂起等待。
- 适当增大 FileReader 的文件块大小,减少线程切换代价,以内存换取时间。
- 适当放宽 dump 文件的大小限制,加快整体写入速度。