Flutter中使用Isolate主要分为3种方式:
-
UI主线程
-
compute
-
LoadBalancer
下面我们通过下面的几种任务来计算整个耗时
3种任务:
-
String => Map
-
Map => Person Model
-
Person Model => Map
在分别计算在4种数据量下的情况:
LoadBalancer 中多出3个打印:jsonDecode,PersonDemo.fromJson,person.toJson,是纯计算耗时的打印,不考虑数据拷贝
| 方式 | UI 主线程 | compute | LoadBalancer |
|---|---|---|---|
| 100条 | |||
| 10000条 | |||
| 100000条 | |||
| 1000000条 |
总结:
-
在非UI的Isolate中执行耗时任务不会卡顿UI
-
但是数据写入Isolate或者写出Isolate会导致何其交互的UI Isolate卡顿
-
compute只会存在数据隔离读入一次的情况
-
LoadBalancer存在数据隔离的读入和写入,需要double的内存
所以:
-
如果是计算为主的任务,建议使用非UI的Isolate中计算
-
如果是高频率的计算任务,建议使用LoadBalancer
-
如果是比较占内存的计算任务,建议使用compute
-
如果内存耗时远高于计算,建议还是UI的Isolate中计算,可以考虑任务队列
PS:耗时排序
jsonEncode > jsonDecode > Map => Model > Model => Map
class PersonDemo {
late String name;
late int age;
late int height;
late String desc;
late List<String> otherStringList;
late List<int> otherIntList;
late Map<String,int> otherIntMap;
late Map<String,String> otherStringMap;
PersonDemo.fromJson(Map<String, dynamic> json) {
name = json['name'];
age = json['age'];
height = json['height'];
desc = json['desc'];
otherStringList = json['otherStringList'].cast<String>();
otherIntList = json['otherIntList'].cast<int>();
otherIntMap = json['otherIntMap'].cast<String,int>();
otherStringMap = json['otherStringMap'].cast<String,String>();
}
Map<String, dynamic> toJson() {
return {
'name': name,
'age': age,
'height': height,
'desc': desc,
'otherStringList': otherStringList,
'otherIntList': otherIntList,
'otherIntMap': otherIntMap,
'otherStringMap': otherStringMap,
};
}
}
///提供一个大量耗时的对比demo,用于比较字符串转JSON Map和Map转模型的耗时差异
///type 0:主线程 Map 1:compute Map 2:loadBalance
Future<void> testSpeedTime(int type) async {
// 生成100...个待转换的JSON字符串
List<Map<String, dynamic>> jsonStringMap = [];
for (int i = 0; i < 100000; i++) {
int age = Random().nextInt(100);
int height = Random().nextInt(200);
Map<String, dynamic> jsonMap = {
'name': 'Person $i',
'age': age,
'height': height,
'desc': 'This is Person $i',
'otherStringList': ['String 1', 'String 2'],
'otherIntList': [1, 2],
'otherIntMap': {'1': 2, '3': 4},
'otherStringMap': {'key1': 'value1', 'key2': 'value2'},
};
jsonStringMap.add(jsonMap);
}
String jsonString = jsonEncode(jsonStringMap);
// 字符串转JSON Map
Stopwatch watch = Stopwatch()..start();
List<dynamic> jsonList;
if (type == 1) {
jsonList = await compute(jsonDecode, jsonString) as List<dynamic>;
} else if (type == 2) {
jsonList = (await AsyncQueueManager().runTask(
AsyncQueueType.jsonSerialize,
(argument) {
Stopwatch watch2 = Stopwatch()..start();
final temp = jsonDecode(jsonString);
print('jsonDecode: ${watch2.elapsedMilliseconds}ms');
return temp;
},
null,
)) as List;
} else {
jsonList = jsonDecode(jsonString);
}
print('String to JSON Map: ${watch.elapsedMilliseconds}ms');
// JSON Map转Person列表
watch.reset();
List<PersonDemo> persons;
if (type == 1) {
persons =
await compute((List<dynamic> jsonList) => jsonList.map((json) => PersonDemo.fromJson(json)).toList(), jsonList);
} else if (type == 2) {
persons = (await AsyncQueueManager().runTask(
AsyncQueueType.jsonSerialize,
(argument) {
Stopwatch watch2 = Stopwatch()..start();
final temp = jsonList.map((json) => PersonDemo.fromJson(json)).toList();
print('PersonDemo.fromJson: ${watch2.elapsedMilliseconds}ms');
return temp;
},
null,
));
} else {
persons = jsonList.map((json) => PersonDemo.fromJson(json)).toList();
}
print('JSON Map to Person List: ${watch.elapsedMilliseconds}ms length:${persons.length}');
watch.reset();
List<Map<String, dynamic>> jsonStringList;
if (type == 1) {
jsonStringList =
await compute((List<PersonDemo> persons) => persons.map((person) => person.toJson()).toList(), persons);
} else if (type == 2) {
jsonStringList = (await AsyncQueueManager().runTask(
AsyncQueueType.jsonSerialize,
(argument) {
Stopwatch watch2 = Stopwatch()..start();
final temp = persons.map((person) => person.toJson()).toList();
print('person.toJson: ${watch2.elapsedMilliseconds}ms');
return temp;
},
null,
));
} else {
jsonStringList = persons.map((person) => person.toJson()).toList();
}
print('Person List to JSON Map: ${watch.elapsedMilliseconds}ms length:${jsonStringList.length}');
watch.reset();
String jsonPersonString;
if (type == 1) {
jsonPersonString = await compute(jsonEncode, jsonStringList);
} else if (type == 2) {
jsonPersonString = (await AsyncQueueManager().runTask(
AsyncQueueType.jsonSerialize,
(argument) {
Stopwatch watch2 = Stopwatch()..start();
final temp = jsonEncode(jsonStringList);
print('person.jsonEncode: ${watch2.elapsedMilliseconds}ms');
return temp;
},
null,
));
} else {
jsonPersonString = jsonEncode(jsonStringList);
}
print('Person List to JSON String: ${watch.elapsedMilliseconds}ms');
}
参考文章:
Flutter/Dart中的异步编程之Isolate | 码客 (psvmc.cn)
flutter入门之理解Isolate及compute - 简书 (jianshu.com)