• 4.09.2026 21:36:23
  • Admin Admin

Flutter mobil uygulama geliştirme ekipleri için Impeller kare zamanını DevTools Timeline, FrameTiming ve katman maliyeti üzerinden ölçme; UI ve raster darboğazlarını ayrı ayrı düzeltme rehberi.

Flutter Mobil Uygulama Geliştirmede Impeller Kare Zamanı Analizi

Flutter mobil uygulama geliştirmede kare bütçesini doğru ayırmak

Flutter mobil uygulama geliştirme sırasında 60 Hz hedefte bir v-sync aralığı yaklaşık 16.67 ms, 120 Hz hedefte yaklaşık 8.33 ms'dir. Bu sürenin tamamı Dart koduna ait değildir: framework/UI işi, raster işi ve platform tarafındaki beklemeler aynı sunum aralığını etkiler. Profil modunda uygulamayı fiziksel cihazda flutter run --profile ile çalıştırın, DevTools Performance ekranında bir kaydı dışa aktarın ve jank karelerini UI mi raster mı sınıflandırın. Debug modu JIT, assertion ve servis trafiği eklediği için bu karşılaştırmada geçerli bir kaynak değildir.

Ölçümü ekranda görünür hale getirmek için FrameTiming callback'i ekleyin. Bu callback, buildDuration ve rasterDuration değerlerini ayrı verdiğinden, örneğin 3 ms build ve 14 ms raster sonucunda Riverpod, Bloc veya başka bir flutter state management katmanını optimize etmek yerine çizim ağacını incelemeniz gerektiğini gösterir. Callback'i sadece profile veya kısıtlı örnekleme ile kullanın; her karede log yazmak kendi başına UI thread maliyeti üretir.

import 'dart:developer' as developer;
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

void installFrameSampler() {
  var frame = 0;
  WidgetsBinding.instance.addTimingsCallback((timings) {
    for (final timing in timings) {
      frame++;
      if (kProfileMode && frame % 120 == 0) {
        developer.log(
          'build=${timing.buildDuration.inMicroseconds}us '
          'raster=${timing.rasterDuration.inMicroseconds}us',
          name: 'frame_budget',
        );
      }
    }
  });
}

Impeller izinde UI ve raster darboğazını ayırma

Son sürümlerde desteklenen hedeflerde Impeller, çizim komutlarını farklı bir renderer hattında işler; yine de bir ekranın hızlı olması garanti değildir. DevTools Timeline kaydında uzun Dart UI kareleri genellikle build, layout veya senkron JSON dönüştürme ile; uzun raster kareleri ise fazla saveLayer, clip, blur, opak olmayan compositing ve büyük resim işlemleriyle ilişkilidir. İzi yorumlarken yalnızca ortalamaya bakmayın: 300 kez açılan bir ekran için p50, p95 ve 16.67 ms üstündeki kare sayısını kaydedin. Tek bir 45 ms p95 raster sıçraması, ortalama 6 ms olsa bile kaydırma sırasında görünür takılma üretir.

Katman ağacını doğrulamak için DevTools Inspector'da Render Tree ve Layer Tree'yi açın; ardından uygulamada debugProfilePaintsEnabled = true ve debugRepaintRainbowEnabled = true bayraklarını yalnızca geliştirme oturumunda etkinleştirin. Tam ekranın her kaydırmada yeniden boyanması, çoğu zaman bir RepaintBoundary eksikliğini gösterir. Buna karşılık her küçük widget'a rastgele RepaintBoundary eklemek de texture/layer sayısını yükseltebilir; değişen alt ağacı sabit arka plandan ayıran sınıra koyun.

import 'package:flutter/rendering.dart';

void enablePaintDiagnostics() {
  debugProfilePaintsEnabled = true;
  debugRepaintRainbowEnabled = true;
}

class ProductImage extends StatelessWidget {
  const ProductImage({super.key, required this.url});
  final String url;

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      child: Image.network(url, fit: BoxFit.cover),
    );
  }
}

Katman maliyetini azaltan somut widget değişiklikleri

Sık rastlanan raster hatası, her liste satırında yarı saydam Container, ClipRRect ve BackdropFilter birleştirmektir. BackdropFilter, arka plan örneklemesi ve ara yüzey gerektirebildiğinden 40 satırlık bir listede kaydırma maliyetiyle çarpılır. DevTools'ta önce aynı test verisiyle 500 px/s sabit scroll kaydı alın; sonra blur'u yalnızca seçili satıra taşıyın veya tasarımı opak renk ve önceden rasterize edilmiş görselle değiştirin. Kararı p95 rasterDuration ile verin, ekran görüntüsüyle değil.

Yuvarlak köşeli bir ağ görselinde clip davranışını açık seçin. Görsel zaten sınırın dışına taşmıyorsa Clip.none, clipping katmanını önler; gerçek kesme gerekiyorsa antiAliasWithSaveLayer yerine antiAlias çoğu kart için yeterlidir. antiAliasWithSaveLayer, geçici offscreen buffer oluşturabildiği için özellikle yüksek çözünürlüklü kartlarda bellek bant genişliği tüketir.

ClipRRect(
  borderRadius: BorderRadius.circular(12),
  clipBehavior: Clip.antiAlias,
  child: Image.network(
    product.thumbnailUrl,
    width: 96,
    height: 96,
    cacheWidth: 192,
    cacheHeight: 192,
    fit: BoxFit.cover,
  ),
)

cacheWidth ve cacheHeight değerlerini cihaz piksel oranına göre hedef görünür boyutun yaklaşık 2 katı seçin; örnekte 96 logical pixel kart için 192 piksel, 2x yoğunluk varsayımıdır. ImageCache durumunu DevTools Memory ekranı ve PaintingBinding.instance.imageCache sayaçlarıyla doğrulayın. Çok küçük decode boyutu bulanıklık, çok büyük decode ise GPU upload ve heap baskısı üretir; bu yüzden aynı cihazda önce cacheWidth olmadan, sonra hedef boyutla 50 kartlık hızlı kaydırmayı karşılaştırın.

Flutter state management değişimlerini render maliyetinden izole etmek

flutter state management seçimi tek başına kare süresini açıklamaz; kritik soru, state değişiminin kaç render object'i yeniden build ettiği ve değişen değerlerin render katmanına nasıl aktarıldığıdır. Örneğin saniyede bir güncellenen fiyat etiketi için tüm ürün kartını provider dinleyicisine bağlamak yerine sadece metni select edin. Riverpod kullanılıyorsa provider.select, immutable state içinden tek alan değişmediğinde consumer rebuild'ini keser.

final cartProvider = NotifierProvider<CartNotifier, CartState>(CartNotifier.new);

class CartBadge extends ConsumerWidget {
  const CartBadge({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(cartProvider.select((state) => state.itemCount));
    return Text('$count');
  }
}

Bu değişikliği doğrulamak için DevTools Performance kaydında kullanıcı akışını iki kez aynı sırayla oynatın: ürün listesinde 100 kez sepete ekleme ve ardından 10 saniye kaydırma. Önce-sonra tabloda build sayısı, UI p95, raster p95 ve 16.67 ms üstü kareleri saklayın. Flutter Inspector'daki Track Widget Rebuilds seçeneği, provider.select sonrasında yalnızca CartBadge'in işaretlenmesi gerektiğini görsel olarak doğrular. Ancak select callback'inden her seferinde yeni List veya Map üretmek eşitlik kontrolünü boşa çıkarabilir; scalar, immutable value object veya referansı korunmuş alan seçin.

Cross platform mobil uygulama geliştirme için tekrarlanabilir benchmark

cross platform mobil uygulama geliştirme ekibinde Android ve iOS sonuçlarını tek bir ortalamada birleştirmeyin. Aynı commit, aynı fixture veri seti, aynı ekran parlaklığı ve mümkün olduğunca benzer termal koşullarda ayrı baseline oluşturun. En az 30 tekrar yapın; ilk 5 tekrar shader, görsel cache ve disk cache ısınmasını içerdiği için soğuk ve sıcak senaryoları ayrı raporlayın. Otomasyonu integration_test ile başlatıp profile APK veya eşdeğer profil yapılandırması üzerinde koşturmak, elle yapılan kaydırma hızının değişkenliğini azaltır.

flutter eğitimi veya flutter kursu kapsamında bu yaklaşımı öğretirken hedef, DevTools ekran görüntüsü ezberletmek değil, hipotez kurup ölçmektir: raster p95 yüksekse Layer Tree ve paint profile; UI p95 yüksekse rebuild tracker ve CPU sample; her ikisi düşük ama sunum gecikiyorsa platform trace gerekir. dart programlama eğitimi tarafında da JSON parse, sıralama veya filtreleme gibi CPU işlerini Timeline task ile etiketlemek, pahalı kodun kare sınırına denk gelip gelmediğini gösterir.

import 'dart:developer' as developer;

Future<List<Product>> decodeProducts(String body) async {
  final task = developer.TimelineTask()..start('decode_products');
  try {
    return parseProducts(body);
  } finally {
    task.finish();
  }
}

İlgili Eğitim

Flutter Eğitimi

Sık Sorulan Sorular

Flutter mobil uygulama geliştirmede Impeller jank sorunu nasıl ölçülür?

Uygulamayı fiziksel cihazda flutter run --profile ile açın, DevTools Performance kaydını alın ve FrameTiming ile buildDuration ile rasterDuration değerlerini ayırın. 30 tekrar için p95 değerini ve 16.67 ms üzerindeki kare sayısını kaydedin; raster p95 yüksekse Layer Tree, UI p95 yüksekse rebuild ve CPU sample inceleyin.

Flutter state management değişikliği gerçekten kare süresini düşürdü mü nasıl anlarım?

Aynı kullanıcı senaryosunu değişiklik öncesi ve sonrası çalıştırın. DevTools Track Widget Rebuilds ile yeniden build olan widget sayısını, Timeline ile UI p95'i ve FrameTiming ile jank kare sayısını karşılaştırın. Provider.select veya BlocSelector kullanırken seçicinin yeni bir koleksiyon üretmediğini de kontrol edin.

Cross platform mobil uygulama geliştirmede Android ve iOS frame süreleri neden farklıdır?

Renderer yolu, sürücü davranışı, cihaz yenileme hızı, ekran piksel yoğunluğu ve termal kısıtlama farklıdır. Her platform için ayrı profile build, ayrı cihaz baseline'ı ve ayrı soğuk-sıcak ölçüm serisi kullanın; Android sonucunu iOS sonucuyla ortalamak yerine platform başına p50, p95 ve jank sayısı raporlayın.

Flutter eğitimi sırasında ClipRRect performansı nasıl test edilir?

DevTools Timeline'da 50 veya daha fazla kart içeren sabit bir listeyi aynı hızda kaydırın. Önce Clip.antiAliasWithSaveLayer, sonra Clip.antiAlias ile raster p95'i ölçün. Görsel taşmıyorsa Clip.none varyantını da deneyin; Layer Tree'de gereksiz clip veya offscreen layer oluşup oluşmadığını doğrulayın.

AI / LLM Discovery

Bu makale Opendart Akademi Flutter eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt