Flutter’da Isolateler: Paralel İşleme ve Performans İyileştirmesi

Alptuğ Yaman
Etiya
Published in
3 min readJul 8, 2023

Flutter, hızlı ve etkileyici kullanıcı arayüzleri oluşturmak için popüler bir SDK. Ancak bazen yoğun hesaplama gerektiren işlemler veya uzun süren işlemler, kullanıcı arayüzünün yanıt verimliliğini etkileyebilir. İşte bu noktada isolateler devreye girer. Isolateler, Flutter uygulamalarında paralel işlemler gerçekleştirmemize olanak sağlar ve performansı artırabilir. Bu makalede, Flutter isolatelerini anlamak, kullanmak ve performans iyileştirmeleri sağlamak için nasıl kullanabileceğimizi inceleyeceğiz.

Isolateler, Flutter uygulamasının çalışma zamanında bağımsız olarak çalışabilen iş parçacıklarıdır. Her isolate, kendi bellek alanına sahip ve diğer isolatelerle paylaşım yapmadan çalışır. Bu izolasyon, her bir isolatein hatalardan etkilenmeden çalışabilmesini sağlar. Örneğin, bir isolate hata yaparsa, diğer isolateler bundan etkilenmez.

Örneğin, bir isolate oluşturalım ve basit bir hesaplama işlemi gerçekleştirelim:

import 'dart:isolate';

void isolateEntry(SendPort sendPort) {
// Isolate içindeki hesaplama işlemi
int result = 0;
for (int i = 0; i < 1000000000; i++) {
result += i;
}

// Sonucu ana iş parçacığına gönderelim
sendPort.send(result);
}

void main() async {
ReceivePort receivePort = ReceivePort();
await Isolate.spawn(isolateEntry, receivePort.sendPort);

// Isolateten gelen sonucu alalım
receivePort.listen((message) {
print('Isolate işlemi tamamlandı. Sonuç: $message');
});
}

Bu örnekte, Isolate.spawn fonksiyonu kullanılarak bir isolate oluşturulur. isolateEntry adlı bir fonksiyon, isolate içinde çalışacak olan işlemleri gerçekleştirir. Isolate işlemi tamamlandığında, sonucu ana iş parçacığına göndermek için sendPort kullanılır.

Flutter, isolateleri desteklemek için Dart dilinin sağladığı fonksiyonları kullanır. Bu fonksiyonlar, isolatelerin oluşturulması, başlatılması ve durdurulması gibi işlemleri yönetmemizi sağlar. Ayrıca, isolateler arasında veri iletişimi sağlayan haberleşme kanallarını kullanabiliriz.

Örneğin, bir isolate oluşturalım ve ana iş parçacığından isolate ile haberleşelim:

import 'dart:isolate';

void isolateEntry(SendPort sendPort) {
// Isolate içindeki işlemler
// ...

// Sonucu ana iş parçacığına göndermek için sendPort kullanılır
sendPort.send(result);
}

void main() async {
ReceivePort receivePort = ReceivePort();
SendPort sendPort = receivePort.sendPort;

// Ana iş parçacığından isolate oluşturulur
Isolate.spawn(isolateEntry, sendPort);

// Isolateten gelen sonucu alalım
receivePort.listen((message) {
// Sonuçla bir şeyler yapalım
});
}

Örnek olarak, bir veritabanı işlemi gerçekleştirirken, birden fazla isolate kullanarak işlem süresini azaltmak istiyoruz. İlk isolate, veritabanından verileri alırken ikinci isolate bu verileri işler ve üçüncü isolate sonuçları kaydeder. Her bir isolate, haberleşme kanalları aracılığıyla veri paylaşımı yapar ve senkronizasyonu sağlar.

import 'dart:isolate';

void dbFetchIsolate(SendPort sendPort) {
// Veritabanından verileri alma işlemi
// ...

// İşlenmiş verileri ikinci isolata göndermek için sendPort kullanılır
sendPort.send(processedData);
}

void dataProcessingIsolate(SendPort sendPort) {
// İşleme işlemleri
// ...

// Sonuçları üçüncü isolata göndermek için sendPort kullanılır
sendPort.send(result);
}

void dbSaveIsolate(SendPort sendPort) {
// Veritabanına kaydetme işlemi
// ...

// Sonucu ana iş parçacığına göndermek için sendPort kullanılır
sendPort.send(success);
}

void main() async {
// Haberleşme için kullanılacak kanallar oluşturulur
ReceivePort fetchPort = ReceivePort();
ReceivePort processPort = ReceivePort();
ReceivePort savePort = ReceivePort();

// İlk isolat veritabanından verileri alır
Isolate.spawn(dbFetchIsolate, fetchPort.sendPort);

// İkinci isolat verileri işler
fetchPort.listen((data) {
Isolate.spawn(dataProcessingIsolate, processPort.sendPort);
});

// Üçüncü isolat sonuçları kaydeder
processPort.listen((result) {
Isolate.spawn(dbSaveIsolate, savePort.sendPort);
});

// Kaydetme işlemi tamamlandığında geri bildirim alınır
savePort.listen((success) {
print('Veri kaydedildi: $success');
});
}

Isolatelerin en büyük avantajlarından biri, uygulama performansını artırma yetenekleridir. Yoğun hesaplama gerektiren işlemleri isolatelere taşıyarak, ana iş parçacığının (main thread) bloke olmasını engelleyebiliriz. Örneğin, bir görüntü işleme operasyonu gerçekleştirmek için bir isolate kullanabilir ve bu işlem sırasında kullanıcı arayüzünün yanıt vermesini sağlayabiliriz.

Flutter ekibi tarafından oluşturulmuş isolate örneğinden ilham alarak, performans üzerindeki etkisini göstermek amacıyla oluşturduğum küçük bir isolate örneğini paylaşıyorum.

Isolate kullanımının performanstaki etkisine dair iki görsel. İlkinde isolate kullanılmadığında ekranda oluşan donmayı görüyorsunuz. İkinci görselde ise isolate kullanıldığında ekrandaki işlemin sorunsuz şekilde devam ettiğini görüyorsunuz.

Örneğe ait kaynak koda buradan ulaşabilirsiniz.

Isolateler, Flutter geliştiricilerine paralel işleme ve performans iyileştirmeleri sağlayan güçlü bir araçtır. Bu makalede, isolatelerin temel prensiplerini, kullanımını ve performans açısından nasıl optimize edilebileceğini inceledik. Ayrıca, compute fonksiyonu gibi kullanışlı API'ler ve isolateler arasındaki veri paylaşımı için haberleşme kanalları gibi ileri seviye kullanımları da ele aldık.

Bu makalede ele aldığım konular, isolateler hakkında genel bir anlayış sağlamayı amaçlamaktadır. Isolateleri etkili bir şekilde kullanarak, Flutter uygulamalarımızı daha hızlı ve daha etkileyici hale getirebiliriz. Bu örnekler ile, isolatelerin kullanımının nasıl gerçekleştirileceği ve uygulamalarda nasıl fayda sağlayabileceğimiz hakkında bilgi vermek istedim.

Umarım bu makale size yardımcı olur. Herhangi bir sorunuz varsa, lütfen bana bildirin. İyi okumalar dilerim!

--

--