dart隔离线程踩坑记录
最近解决应用性能问题的时候,尝试使用了compute方法将性能密集型部分放在独立线程中执行来减少对UI线程的停顿式阻塞:
flutter默认创建一个项目后,初始只有一个ui线程,通过async和await执行的任务都是位于同一个线程中时间片轮转调度执行的。ui渲染的时间是每秒60帧率,所以一般每帧的内容需要在16.67ms中计算完毕交给gpu光栅进行渲染。
所以不像操作系统可以借助保护模式或者是时钟中断等方法,flutter默认的项目架构仅有一个ui线程,遇到系统调用阻塞或者是cpu/io密集型任务的阻塞时,时间片轮转就也被卡住了,导致整个ui线程也似了。
针对特定平台,例如安卓,我们可以使用多线程能力分离计算任务到单独的线程来保证ui的交互响应速度不受影响。flutter提供了isolated模型作为绑定线程的实体,以及线程创建、线程间通信的标准模型。
然后,isolated直接使用比较麻烦,所以flutter提供了一个叫做compute的封装。它允许直接传入任务,并用await等待执行结果。但是这里有个坑,就是这个compute按理来说提供方法和参数就行了,但是这个参数嘛,因为是在进程之间传递所以有个问题,就是如果序列化失败,那compute就会创建线程失败。此时,它的默认行为是在主线程中执行传入的任务:所以该卡还是卡。
要想绕过这个限制,那就没法用这个compute了。得自己使用更底层的Isolate去实现这个api然后自己传入数据进行计算。具体怎么写嘛,我那个x-nav的lib/utils/data_loader.dart
就做了一个这样的实现。
虽然现在这依托正在大规模重构。。但是这部分多线程异步加载逻辑应该是不会删掉了。