11. Flutter Framework
• Flutter engine does not create its own threads or
manage them
Platform Task
Runner
UI Task
Runner
IO Task
Runner
GPU Task
Runner
Embedder
19. How do I make em 🤔
Future<int> startIsolate() async {
}
1. Isolate.spawn(runnable, runnable_param)
//Create a Port for communication
ReceivePort receivePort = ReceivePort();
//Create the isolate
await Isolate.spawn(computeMatrix,
receivePort.sendPort);
//Pick first item in stream
return await receivePort.first;
//Callback
void computeMatrix(SendPort port) {
var result = heavilyComputedValue();
port.send(result)
}
void onButtonClick() {
startIsolate().then((computedValue) {
setState(() {
computedText = "Matrix result is
${computedValue}";
});
});
}
20. How do I make em 🤔
void createRestrictedIsolate(Isolate main){
//Proxy
Isolate restrictedIsolate = new Isolate(main.controlPort);
untrustedCode(restrictedIsolate);
}
1. Isolate.spawn(callback, callback_param)
2. via Constructor
21. How do I make em 🤔
1. Isolate.spawn(callback, callback_param)
3. spawnUri(Uri uri, List<String> args)
Future<void> executeFileContent(Isolate main) async{
var args =List<String>();
args.add("type=monthly_data");
var isolate = await Isolate.spawnUri('./periodic_sync.dart',args)
}
2. via Constructor
22. Processing Large Data
• Flutter copies data on the parent isolate.
• TransferableTypedData creates cross isolate transferrable
buffer.
23. void sendData(SendPort replyPort){
}
void receiveData(ReceivePort receivePort) async {
}
dynamic x = new ByteData(2 * 1024 * 1024);
for (int i = 0; i < 4; i++) {
x.setInt8(i, i);
}
replyPort.send(TransferableTypedData.fromList([x.buffer.asUint8List()]));
var first = await receivePort.first as TransferableTypedData;
var data = first.materialize().asByteData();
24. Benchmarks
• Spawn time for a typical isolate varies between 10-80ms
• Each isolate is allocated an independent heap. Around 5-6 mb
on a higher end phone.
• Isolate creation times on android are almost 8-10x of ios.
27. Isolate Runner
• Allows one to check if the runner is still alive.
• Specify timeouts via. run function
Wrapper around creation of Isolates.
Future<R> run<R, P>(FutureOr<R> function(P argument), P argument,
{Duration timeout}) {
28. Load Balancers
• Create and Manage Isolate runner pool.
var balancer = LoadBalancer.create(POOL_SIZE, IsolateRunner.spawn)
balancer.run(heavyCompute, heavyComputeArg, estimatedLoad)
37. The Final Spell
Observable getFibonnaciValue(int value) {
return Observable.just(value)
.transform(IoScheduler<int, int>(calculateFib));
}
int calculateFib(int n) {
if (n <= 1)
return n;
else
return calculateFib(n - 1) + calculateFib(n - 2);
}
38. The "not so good" parts
• Copy overheads*
• Isolate creation times are sporadic.
• Doesn't guarantee true parallelism all the time. Since they're
backed byVM thread pool.
39. Takeaways
• Avoid isolates for simpler tasks like object transformations.
• Use Isolates for json decoding, encryption and image processing.
• Figure out a pool size that works well for your app. Around 5-6
isolates are good enough for most apps.
• Profile your app.