深入了解Flutter的isolate(3) --- Flutter的thread model(线程模型)

    xiaoxiao2022-07-12  174

    转载:https://juejin.im/post/5c3844fae51d4551ec60988e

    0x00 前言

    Flutter中有一个很重要的概念就是isolate,isolate是由一个线程实现的,实现isolate的线程由Flutter创建和管理,除了实现isolate的线程,Flutter还有其余的线程,本篇文章探讨Flutte的threading model(线程模型)。

    0x01 Flutter Architecture overview

     

     

    从图中可以看出Flutter有3部分组成:

     

    Framework(Dart):我们在写Flutter应用中,直接接触的Engine(C/C++):引擎层,提供核心技术,例如:Skia(2D图形渲染库);Dart(一个用于垃圾收集的面向对象语言的VM,DartVM有自己的线程池);shell(不同的平台有不同的shell,例如有Android和iOS的shell)Embedder(Platform Specific):嵌入层,为Engine创建和管理线程,作用是把Engine的task runners(任务运行器) 运行在嵌入层管理的线程上。

    0x02 Flutter的task runners的分类

    上面讲了task runners要运行的线程上,这里的task runners有四种,而且都是运行在不同的线程上(可以运行在同一个线程上,但是出于性能的因素,不建议这么做)。

    task runners分为四种:

    Platform Task RunnerUI Task RunnerGPU Task RunnerIO Task Runner

    1. Platform Task Runner

    Platform Task Runner运行所在的线程 对应 平台的线程

    AndroidiOS主线程主线程

    功能 嵌入层和Engine层的交互,处理平台(Android/iOS)的消息

    为什么一定要是平台的主线程? 因为Platform Task Runner的功能是要处理平台的消息,但是平台的API都是只能在主线程调用,所以Platform Task Runner运行所在的平台的线程必须是主线程

    一个Flutter Engine对应一个Platform Thread(一个Flutter应用启动的时候会创建一个Engine实例,Engine创建的时候会创建一个Platform线程供Platform Task Runner使用)

    阻塞Platform Thread不会直接导致Flutter应用的卡顿(跟iOS android主线程不同)。尽管如此,也不建议在这个Runner执行繁重的操作,长时间卡住Platform Thread应用有可能会被系统Watchdog强杀。

    2. UI Task Runner

    UI Task Runner运行所在的线程 对应到 平台的线程

    AndroidiOS子线程子线程

    这里很容易让大家误会,因为一看名字,UI Task Runner,第一反应,UI ? 那肯定是在主线程里的,其实并不是,UI Task Runner运行所在的线程 对应到 平台的线程,其实是子线程

    功能

    1)用于执行Dart root isolate代码

    2)渲染逻辑,告诉Engine最终的渲染

    3)处理来自Native Plugins的消息

    4)timers

    5)microtasks

    6)异步 I/O 操作(sockets, file handles, 等)

    Root isolate就是运行在这个线程上,所以isolate就可以理解为单线程,有event loop的架构

    阻塞这个线程会直接导致Flutter应用卡顿掉帧

    为了防止阻塞这个线程,我们可以创建其他的isolate,创建的isolate没有绑定Flutter的功能,只能做数据运算,不能调用Flutter的功能,而且创建的isolate的生命周期受Root isolate控制,Root isolate停止,其他的isolate也会停止,而且创建的isolate运行的线程,是DartVM里的线程池提供的

    3.GPU Task Runner

    GPU Task Runner运行所在的线程 对应到 平台的线程

    AndroidiOS子线程子线程

    功能

    GPU Task Runner主要用于执行设备GPU的指令。在UI Task Runner 创建layer tree,在GPU Task Runner将Layer Tree提供的信息转化为平台可执行的GPU指令。

    UI Task Runner和GPU Task Runner跑在不同的线程。GPU Runner会根据目前帧执行的进度去向UI Task Runner要求下一帧的数据,在任务繁重的时候可能会告诉UI Task Runner延迟任务。这种调度机制确保GPU Task Runner不至于过载,同时也避免了UI Task Runner不必要的消耗。

    在此线程耗时太久的话,会造成Flutter应用卡顿,所以在GPU Task Runner尽量不要做耗时的任务,例如加载图片的时候,去读取图片数据,就不应该放在GPU Task Runner,而是放在接下来要讲的IO Task Runner

    建议为每一个Engine实例都新建一个专用的GPU Task Runner线程。

    4. IO Task Runner

    IO Task Runner运行所在的线程 对应到 平台的线程

    AndroidiOS子线程子线程

    功能

    1)主要功能是从图片存储(比如磁盘)中读取压缩的图片格式,将图片数据进行处理为GPU Runner的渲染做好准备。IO Runner首先要读取压缩的图片二进制数据(比如PNG,JPEG),将其解压转换成GPU能够处理的格式然后将数据上传到GPU。 2)加载其他资源文件

    在IO Task Runner不会阻塞Flutter,虽然在加载图片和资源的时候可能会延迟,但是还是建议为IO Task Runner单独开一个线程。

    0x03 各个平台的线程配置

    1.iOS

    为每个引擎实例的UI,GPU和IO任务运行程序创建专用线程。所有引擎实例共享相同的Platform Thread和Platform Task Runner。

    2.Android

    为每个引擎实例的UI,GPU和IO任务运行程序创建专用线程。所有引擎实例共享相同的Platform Thread和Platform Task Runner。

    3.Fuchsia

    每一个Engine实例都为UI,GPU,IO,Platform Runner创建各自新的线程。

    4.Flutter Tester (used by flutter test)

    UI,GPU,IO和Platform任务运行器使用相同的主线程。

    最新回复(0)