Proqramlaşdırmada tutma — bu nədir, səbəbləri və optimallaşdırma metodları

Müəllif: IT Sectr Dərc olunub: 2026-07-28 Oxuma vaxtı: 8 dəq

Tutma — bu, mobil tətbiq yavaş və qeyri-sabit işlədikdə istifadəçinin vəziyyəti təsvir etməsidir: bəzən normal cavab verir, bəzən birdən bir neçə saniyə donur. Texniki kontekstdə “tutma” GC pauzaları, sinxron əməliyyatlarla əsas axının bloklanması və qeyri-optimal məlumat strukturları nəticəsində yaranan laqların və mikro-donmaların kombinasiyası deməkdir. Android Performance Benchmarking Guide məlumatına görə, cavab müddətinin 300 ms-dən 100 ms-ə endirilməsi istifadəçi saxlanmasını 25% artırır. Tutmanın diaqnostikası CPU və Memory profilləşdirməsinin zibil yığımı tezliyinin təhlili ilə birləşdirilməsini tələb edir.

Əsas məqamlar

  • Tutma — normal performansla növbələşən qeyri-müntəzəm yavaşlama
  • Əsas səbəblər — tez-tez GC pauzaları, UI axınında sinxron əməliyyatlar, paginasiyasız adapterlərdə böyük həcmdə məlumat
  • Diaqnostika blokadaları tapmaq üçün CPU Profiler və GC tezliyi və müddətini təhlil etmək üçün Memory Profiler tələb edir
  • Həll paginasiyanın (Paging 3) tətbiqi, Room vasitəsilə SQL sorğularının optimallaşdırılması və ağır tapşırıqların WorkManager-ə ötürülməsini əhatə edir
  • Profilaktika — Benchmark Baseline Profiles, AOT kompilasiyası, kodun isti hissələrində alokasiyaların minimallaşdırılması

Mobil proqramlaşdırmada “tutma” nə deməkdir

Tutma — istifadəçilərin subyektiv olaraq yavaş tətbiq işini təsvir etdiyi qeyri-rəsmi termindir. Daimi gecikmə kimi özünü göstərən laqdan fərqli olaraq, tutma qeyri-müntəzəm donmalardır: tətbiq bir neçə saniyə mükəmməl işləyə bilər, sonra 1–3 saniyə “düşünə” bilər.

Hadisənin texniki xarakteristikası

Profilləşdirmə baxımından tutma 100 ms-dən çox pik gecikmələri olan buraxılmış kadrlar seriyası (jank) kimi özünü göstərir. FPS qrafikində bu kəskin enişlər kimi görünür: 60 → 20 → 55 → 10 kadr/saniyə. Vahid aşağı FPS-li laqdan fərqli olaraq, tutma aydın dəyişkənliyə malikdir.

İstifadəçi qavrayışı

Tətbiq tutduqda, istifadəçi yavaşlamaların məntiqini başa düşmür: ekran hamar sürüşə bilər, sonra birdən bir saniyə dayana bilər. Bu, məyusluğa səbəb olur və tətbiqə inamı azaldır. Google məlumatına görə, istifadəçilərin 53%-i yükləmə 3 saniyədən çox çəkərsə, saytı və ya tətbiqi tərk edir.

Tətbiqlərdə qəfil yavaşlamaların səbəbləri

Tutmanın qeyri-müntəzəm xarakteri problemin daimi yüklənmədən deyil, hadisə faktorlarından qaynaqlandığını göstərir. Tipik ssenariləri nəzərdən keçirək.

Obyekt alokasiyası zamanı GC pauzaları

Android-də ART mühitində zibil yığımı tətbiqin bütün axınlarını dayandırır. Əgər kodda çoxlu müvəqqəti obyekt yaradılırsa — məsələn, hər onBindViewHolder çağırışında konkatenasiya ilə yeni String yaradılırsa — GC daha tez-tez işə düşür. Pauza yığın ölçüsü və obyekt nəslindən asılı olaraq 5–50 ms davam edə bilər. İstifadəçi bunu qəfil “düşünmə” kimi hiss edir.

UI axınında sinxron SQL sorğuları

Room Android-də və Core Data iOS-da asinxron sorğuları dəstəkləyir, lakin proqramçılar sadəlik üçün tez-tez getValue() çağırır və ya runBlocking ilə sorğu yerinə yetirirlər. 10 000 sətirli cədvəldə join-lərlə ağır SELECT 200–500 ms çəkə bilər və UI-ni tamamilə bloklaya bilər.

Downscale olmadan şəkil dekodlanması

Kamera şəklinin (12 Mp, 4000x3000 px) miqyaslanmadan yüklənməsi Bitmap-ə dekodlanmaq üçün 200 ms-ə qədər çəkir. Şəkillər asinxron yüklənirsə, lakin məhdudiyyətli axın hovuzu olmadan, 5–6 dekodlamanın eyni vaxtda işə salınması CPU-nu həddən artıq yükləyərək miqrasiya edən yavaşlamalara səbəb ola bilər.

  • Android — dövrlərdə sətir konkatenasiyası, isti yollarda obyekt yaradılması, inSampleSize olmadan Bitmap
  • iOS — çox sayda obyektlə avtoburaxılış hovuzları, miqyaslanmadan imageWithContentsOfFile, sinxron URLSession
  • Cross-platform — UI axınında JSON parsingsi, əsas axında server cavabını gözləyərək məlumat yüklənməsi

Android və iOS-da donmaları necə diaqnoz etmək

Qeyri-müntəzəm yavaşlamaların diaqnostikası daimi laqların diaqnostikasından çətindir, çünki problem hər işə salınmada təkrarlanmaya bilər. Uzun müddət ərzində statistika toplanması tələb olunur.

Memory Profiler ilə GC hadisələrinin qeydi

Android Studio Memory Profiler təkcə yaddaş istifadəsini deyil, həm də GC hadisələrini göstərir: tezlik, tip (Concurrent, Full), müddət. Əgər GC sakit vəziyyətdə 5 saniyədə 1 dəfədən çox baş verirsə — bu, həddindən artıq alokasiya əlamətidir. Tutma anında heap dump qeydi hansı obyektlərin yaddaşı tutduğunu görməyə imkan verir.

Xcode Instruments ilə Allocation Tracking

iOS-da obyektlərin yaradılmasını və buraxılmasını izləmək üçün Instruments-də Allocations şablonundan istifadə edin. Generasiyaları (Generations) aktivləşdirin — onlar hərəkətlər arasında yığın şəkillərini çəkməyə və hansı obyektlərin yaddaşda qaldığını görməyə imkan verir. Buraxılmayan Persistent objects — yaddaş yığılması və sonrakı pauzaların mənbəyidir.

Android-də JankStats API

JankStats — real vaxtda buraxılmış kadr metrikalarını toplayan Android kitabxanasıdır. Hər jank-ı cari ssenariyə (məsələn, “siyahının sürüşdürülməsi”, “ekranın açılması”) bağlayır ki, bu da tutmanın hansı hərəkətdə baş verdiyini anlamağa imkan verir.

Android-də donmaları izləmək üçün JankStats inteqrasiyası nümunəsi:

kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var jankStats: JankStats

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        jankStats = JankStats.create(this.window.decorView) { frameData ->
            if (frameData.isJank()) {
                Log.w("Tutma", "Müddət=${frameData.durationMs}ms")
            }
        }
    }
}

Yavaş işləmənin aradan qaldırılması metodları

Tutmanın aradan qaldırılması hər səbəblə hədəflənmiş iş tələb edir. Universal həll yoxdur — konkret performans profillərinin təhlili lazımdır.

Paging 3 vasitəsilə paginasiyanın tətbiqi

Siyahıda 1000+ element varsa və hamısı birdən yüklənirsə — bu zəmanətli tutmadır. Android-də Paging 3 və iOS-da NSFetchedResultsController məlumatları sürüşdürmə zamanı hissə-hissə yükləyir. İstifadəçi yalnız ilk 10–20 elementi görür, qalanları fonda yüklənir.

SQL sorğularının və indekslərin optimallaşdırılması

Room Android Studio-da Inspection Tool vasitəsilə sorğuları profilləşdirməyə imkan verir: icra müddəti, qaytarılan sətirlərin sayı və sorğu planı görünür. WHERE və ORDER BY sütunlarına indekslərin əlavə edilməsi sorğu müddətini 300 ms-dən 5 ms-ə endirə bilər. iOS-da analoji yoxlama Instruments-də Core Data Profiler tərəfindən aparılır.

Tapşırıqların WorkManager-ə ötürülməsi

Fon sinxronizasiyaları, fayl yükləmələri, məlumat emalı — bütün bunlar WorkManager (Android) və ya Background Tasks (iOS) vasitəsilə yerinə yetirilməlidir. Sinxronizasiya UI axınında işə salınarsa, tətbiq icra müddətində tutacaq. WorkManager batareya və şəbəkə vəziyyəti nəzərə alınmaqla fon axınında icraya zəmanət verir.

Android-də WorkManager vasitəsilə fon sinxronizasiyası nümunəsi:

kotlin
class SyncWorker(context: Context, params: WorkerParameters)
    : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            Log.d("Sync", "Fon iplikdə məlumatların sinxronizasiyası")
            syncData()
            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}

İşlənmə mərhələsində tutmanın profilaktikası

Tutmanın qarşısını kod yazma mərhələsində, yaddaş və axınlarla effektiv iş prinsiplərinə riayət etməklə almaq olar.

Baseline Profiles AOT kompilasiyası üçün

Baseline Profiles — Android-in əvvəlcədən (AOT) kompilə etdiyi sinif və metodların siyahısıdır. Profil olmadan hər yeni ekran ilk açılışda kompilə olunur və 100–500 ms gecikməyə səbəb olur. Əsas ekranlar üçün Baseline Profile hazırlayın və baseline-profile-gradle-plugin vasitəsilə Gradle-də generasiyanı aktivləşdirin.

İsti yollarda alokasiyaların minimallaşdırılması

Hot path — hər kadrda icra olunan koddur: onBindViewHolder, draw, layoutSubviews. Bu metodlarda obyekt yaratmaqdan çəkinin: obyekt hovuzundan istifadə edin, konkatenasiya əvəzinə StringBuilder, formatlanmış sətirləri və formatları keşləyin. Hər əlavə alokasiya növbəti GC-ni yaxınlaşdırır.

CI-da Baseline Profiles vasitəsilə profilləşdirmə

CI pipeline-na siyahı sürüşdürmə və ekran açma ssenarisi ilə Macrobenchmark işə salınmasını əlavə edin. Hədd təyin edin: kadr vaxtının 99-cu persentili 16 ms-dən çox olmamalıdır. Hədd aşılırsa, optimallaşdırmaya qədər build rədd edilir.

  • Android — Baseline Profiles, Macrobenchmark, JankStats, penaltyDeath ilə StrictMode
  • iOS — MetricKit, os_signpost, XCTMetric, Debug sxemində Main Thread Checker
  • Ümumi yanaşma — müntəzəm profilləşdirmə, isti yollarda alokasiyalara diqqət yetirən kod nəzərdən keçirmə

Tez-tez verilən suallar

Tutma adi laqdan nə ilə fərqlənir?

Laq — daimi gecikmədir (məsələn, hər toxunuşda 200 ms). Tutma — qeyri-müntəzəm: tətbiq normal işləyir, sonra birdən 1–3 saniyə yavaşlayır, sonra yenə normal. Səbəb — GC pauzaları və ya verilənlər bazasına sinxron sorğular kimi hadisə faktorları.

Android-də GC pauzalarının tezliyini necə ölçmək?

Android Studio-da Memory Profiler istifadə edin: Memory nişanı GC hadisələrini müddəti ilə göstərir. İstehsalat monitorinqi üçün xüsusi treyslərlə Firebase Performance Monitoring qoşun. iOS-da Malloc Debug aktivləşdirin və Instruments-də alokasiya nəsillərini qeyd edin.

Tutma şəbəkə sorğularından qaynaqlana bilərmi?

Dolayı — bəli. Server cavabı gecikmə ilə gəlirsə və UI onu sinxron gözləyirsə, tətbiq donur. Sorğu asinxrondursa, lakin cavab emalı UI axınında aparılırsa — bu da tutmaya səbəb olacaq. Həll — korutinlər və gedişat göstəriciləri ilə asinxron emal.

Kotlin Multiplatform performansa necə təsir edir?

Düzgün istifadə edilmədikdə KMP qarşılıqlı işləmə üçün artıq sarğı obyektləri yarada bilər. iOS-da bu, alokasiya tezliyini və nəticədə ARC pauzalarını artırır. @ObjCName istifadə edin, expect/actual optimallaşdırın və UI-nin isti yollarından paylaşılan koda tez-tez müraciətlərdən çəkinin.

Android-də yığın ölçüsünü artırmaq kömək edirmi?

android:largeHeap="true" ilə yığını artırmaq GC-ni təxirə salır, lakin alokasiya səbəbini aradan qaldırmır. GC nəhayət işə düşəndə pauza daha uzun olacaq, çünki daha çox obyekti keçmək lazımdır. Həll — yığını genişləndirmək deyil, alokasiyaların sayını azaltmaqdır.

Nəticə

  • Tutma — hadisə faktorları (GC pauzaları, sinxron sorğular, şəkil dekodlanması) nəticəsində yaranan qeyri-müntəzəm yavaşlama
  • Diaqnostika Memory Profiler, Android-də JankStats və iOS-da Instruments-də Allocation Tracking tələb edir
  • Əsas səbəblər — tez-tez GC pauzaları, paginasiyanın olmaması, qeyri-optimal SQL sorğuları və UI axınında sinxron emal
  • Həll — Paging 3, WorkManager, verilənlər bazası indekslərinin optimallaşdırılması, şəkillərin miqyaslanması və alokasiyaların minimallaşdırılması
  • Profilaktika — Baseline Profiles, Macrobenchmark, StrictMode, isti yolların yoxlanılması ilə kod nəzərdən keçirmə
  • Alətlər — JankStats, Firebase Performance, MetricKit istehsalat donma monitorinqi üçün
  • Tövsiyə: CI-da 99-cu persentil kadrlar üçün 16 ms həddi ilə müntəzəm Macrobenchmark işə salınmasını tətbiq edin

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun