Memory Graph: bu nədir, obyekt qrafı və siklik istinadların aşkarlanması

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

Memory Graph — tətbiqin operativ yaddaşındakı obyektlərin qarşılıqlı istinadları ilə qrafını göstərən Xcode Debug Navigator-un vizual alətidir. Heap dump-dan fərqli olaraq, Memory Graph sadəcə obyekt siyahısını deyil, hər bir düyünün obyekt və hər bir kənarın istinad (strong, weak, unowned) olduğu istiqamətlənmiş istinad qrafını göstərir. Apple WWDC 2018-ə əsasən, alət saniyələr ərzində retain cycles və yaddaş sızmalarını vizual olaraq aşkar etməyə imkan verir, xam yığın dump məlumatlarını təhlil etmək tələb olunmur.

Əsas məqamlar

  • Memory Graph — Xcode yaddaşındakı obyektlərin vizual qrafı, obyektlər arasında istinadları real vaxtda göstərir.
  • Retain cycle qrafda qapalı konturla aşkarlanır — iki və ya daha çox obyekt bir-birinə güclü istinadlarla bağlanır.
  • Backtrace qrafın hər bir kənarı üçün istinadın harada və nə vaxt qurulduğunu göstərir, sızma mənbəyinin tapılmasını asanlaşdırır.
  • Filtrləmə sinif adı və istinad növü (strong/weak) üzrə problemli obyektləri tecrid etməyə imkan verir.
  • İnteqrasiya Xcode-dakı Memory Report ilə yaddaş istehlakının real vaxtda dəyişməsini izləməyə imkan verir.

Memory Graph nədir və necə işləyir

Memory Graph — Xcode Debug Navigator komponentidir (Xcode 10, WWDC 2018-də ortaya çıxıb), debug edilən prosesin yaddaşındakı bütün obyektlərin istiqamətlənmiş qrafını qurur. Qrafın hər bir düyünü sinif nümunəsidir (Objective-C və ya Swift), hər bir kənar digər obyektə istinaddır. Kənarın rəngi istinad növünü göstərir: mavi — strong, yaşıl — weak, boz — unowned. Qraf LLDB və Objective-C runtime məlumatları əsasında qurulur, buna görə düzgün işləməsi üçün tətbiq Debug konfiqurasiyasında simvollar açıq vəziyyətdə yığılmalıdır.

İş prinsipi: tətbiq breakpoint-də dayandırıldıqda, Xcode LLDB vasitəsilə runtime-dan bütün canlı obyektləri və onların istinadlarını sorğulayır. LLDB tam qraf qurmaq üçün objc_getClassList və ayırma regionları üzrə iterasiyadan istifadə edir. ARM64-də (Apple Silicon) yavaşlatma olmadan ayırmanın izlənməsi üçün əlavə aparat vasitələrindən istifadə olunur. Qrafın qurulma müddəti yığın ölçüsündən asılıdır: tipik iOS tətbiqi (50–200 MB) üçün qraf 1–3 saniyəyə qurulur.

Apple-ın məlumatına görə, Memory Graph kodu dəyişdirmədən və ya instrumentasiya əlavə etmədən retain cycles-i vizuallaşdıra bilən yeganə alətdir. Instruments Leaks-dən fərqli olaraq, Memory Graph Xcode daxilində real vaxtda işləyir və profilçinin ayrıca işə salınmasını tələb etmir. Bu, onu inkişaf prosesində yaddaş sızmalarının sürətli diaqnostikası üçün ilk seçim aləti edir.

Memory Graph heap dump-dan nə ilə fərqlənir

Heap dump rəqəmlərlə (shallow size, retained size) bütün obyektlərin cədvəlini verir — kəmiyyət təhlili üçün optimaldır. Memory Graph əlaqələrin vizual mənzərəsini verir — siklik istinadların axtarışı üçün optimaldır. Alətlər bir-birini tamamlayır: əvvəlcə Memory Graph sürətli retain cycles aşkarlanması üçün, sonra Instruments Allocations vasitəsilə heap dump dəqiq retained size ölçülməsi üçün. objc.io-nun təcrübəsinə görə, iki metodun kombinasiyası yaddaş sızması ssenarilərinin 95%-ni əhatə edir.

Memory Graph ilə retain cycles-in aşkarlanması

Retain cycle — iki və ya daha çox obyektin bir-birini güclü istinadlarla saxlayaraq qapalı kontur yaratdığı vəziyyətdir. ARC belə konturu sərbəst buraxa bilməz, çünki hər bir obyektin retain count-u heç vaxt sıfıra çatmır. Klassik nümunə: ViewController və View, burada View-in closure-a strong reference-i var və closure self-i (ViewController) tutur. Memory Graph belə konturları üzük (dövr) şəklində göstərir, sürətli identifikasiya üçün onları vurğulayır.

Xcode retain cycle aşkar etdikdə, onu narıncı konturla vurğulayır və Debug Navigator-da xəbərdarlıq göstərir. Dövrə kliklədikdə, qapalı kontur yaradan istinad zəncirini görürsünüz. Tərtibatçıya hansı güclü kənarın zəif olmalı olduğunu müəyyən etmək qalır — adətən bu, uşaq obyektdən valideynə olan istinaddır (məsələn, delegate və ya closure).

swift
class ViewController: UIViewController {
    let service = DataService()

    override func viewDidLoad() {
        super.viewDidLoad()
        // ❌ Retain dövrü: ViewController → xidmət → closure → ViewController
        service.fetchData { self.updateUI($0) }
    }

    func updateUI(_ data: Data) {}
}

class DataService {
    var completion: ((Data) -> Void)?

    func fetchData(handler: @escaping (Data) -> Void) {
        self.completion = handler
    }
}

Memory Graph-da üçbucaq görəcəksiniz: ViewController → DataService → closure → ViewController. Həll yolu — self-in zəif tutulması: [weak self]. Düzəlişdən sonra Memory Graph closure-dən ViewController-a yaşıl kənar göstərəcək və retain cycle yox olacaq.

swift
// Düzəldilmiş kod — self-in zəif tutulması
service.fetchData { [weak self] data in
    guard let self else { return }
    self.updateUI(data)
}

Xcode-da Memory Graph Debugger interfeysi

Memory Graph Debugger interfeysi üç paneldən ibarətdir: sol — bütün canlı obyektlərin (siniflərə qruplaşdırılmış) siyahısı nümunə sayı ilə; mərkəz — sürüklənə bilən düyünləri olan vizual qraf; sağ — seçilmiş obyektin və ya kənarın inspektoru. Obyekt siyahısında göstərilir: sinif ikonu, yaddaşdakı nümunə sayı, ümumi retained size və bütün yığına nisbətən faiz. Sinif adı üzrə filtrləmə müntəzəm ifadələri dəstəkləyir.

Qraf üzrə naviqasiya

Qraf düyünləri oxunaqlılığı yaxşılaşdırmaq üçün sürüklənə bilər. Düyünün üzərinə iki dəfə klikləmək obyekt haqqında ətraflı məlumat açır: tipləri və dəyərləri ilə bütün xassələri, hər bir xassə üçün çağırış yığını (backtrace) və retain/release tarixçəsi. Backtrace — əsas funksiyadır: obyektə istinadı hansı kod sətirinin qurduğunu göstərir. Bu, bütün kodu əl ilə nəzərdən keçirmədən sızma mənbəyini tapmağa imkan verir.

Mürəkkəb qraflar üçün Xcode Layout → Hierarchical (ierarxik) və ya Cluster (klaster) vasitəsilə avtomatik düzülüş təmin edir. İerarxik düzülüş kök obyektləri yuxarıda, uşaq obyektləri aşağıda yerləşdirir, zəncirlərin axtarışını asanlaşdırır. Klaster düzülüşü əlaqəli obyektləri qruplaşdırır, bu qraf bir neçə təcrid olunmuş qrup ehtiva etdikdə əlverişlidir. Apple-ın məlumatına görə, əksər tətbiqlər üçün ierarxik düzülüş tövsiyə olunur — intuitivdir və vizual analizə daha az vaxt aparır.

lldb
// Memory Graph tərəfindən istifadə olunan LLDB əmrləri
(lldb) script import lldb.macosx.heap
(lldb) script heap.find_variable("viewController")
0x600000c4b80: ViewController
(lldb) script heap.refs 0x600000c4b80
0x600000c4b80 -> 0x600003a4c00 (DataService)
    ivar: _service, offset: 16

Qrafın təhlili: sızmaların tapılması və aradan qaldırılması

Memory Graph analizinə sistematik yanaşma bir neçə mərhələni əhatə edir. Mərhələ 1: tətbiqi işə salın, potensial sızmaya səbəb olan ssenarini yerinə yetirin (ekranı açın/bağlayın, şəbəkə sorğusu edin). Mərhələ 2: Debug Navigator-da Memory Graph düyməsini basın — Xcode qraf quracaq. Mərhələ 3: sol paneldə narıncı retain cycles xəbərdarlıqlarını yoxlayın. Mərhələ 4: şübhəli obyektlər üçün Show only cycles seçimindən istifadə edin — yalnız siklik istinadlara daxil olan düyünlər göstəriləcək.

Mənbəni tapmaq üçün backtrace-dən istifadə

Retain cycle tapıldıqda, dövr kənarına klikləyin və inspektor panelini açın. Backtrace bölməsində bu istinadın qurulduğu andakı çağırış yığını göstərilir. Məsələn, kənar closure-dən self-ə aparırsa, backtrace closure-in hansı metoddə və hansı kod sətirində yaradıldığını göstərəcək. Bu, təxmin etmək ehtiyacını aradan qaldırır — problemli istinadın yaradılma nöqtəsini dərhal görürsünüz. WWDC Labs-ın məlumatına görə, backtrace analizi retain cycle diaqnostikası müddətini 15–20 dəqiqədən 2–3 dəqiqəyə qədər azaldır.

swift
class ProfileViewController: UIViewController {
    var profileView: ProfileView!

    override func viewDidLoad() {
        super.viewDidLoad()
        profileView = ProfileView()
        // Memory Graph retain dövrünü burada göstərəcək
        profileView.onTap = { [unowned self] in
            // ⚠️ unowned nil self-də crash-a səbəb ola bilər
            self.navigateToDetail()
        }
    }

    func navigateToDetail() { }
}

// ✅ Düzgün: [weak self] + guard let self
profileView.onTap = { [weak self] in
    guard let self else { return }
    self.navigateToDetail()
}

Lazımsız obyektlərin filtrlənməsi

Memory Graph minlərlə obyekt göstərə bilər, axtarışı çətinləşdirir. Sol paneldə filtrlərdən istifadə edin: sinif adını daxil edin (məsələn, ProfileViewController), yalnız bu sinfin nümunələrini göstərmək üçün. Sonra sərbəst buraxılmalı olan nümunəni seçin (ekran bağlıdırsa, lakin obyekt qalıbsa). Show Reachable From tətbiq edin — yalnız bu obyekt üçün əhəmiyyətli olan istinadlar göstəriləcək, qrafın qalan hissəsi gizlənəcək.

Memory Graph-dən istifadə üçün praktiki məsləhətlər

Təcrübəli tərtibatçılar Memory Graph-dən təkcə sızmaların axtarışı üçün deyil, həm də proaktiv yaddaş nəzarəti üçün istifadə edirlər. Memory Graph-i yoxlayın hər bir böyük arxitektura dəyişikliyindən sonra — yeni delegate, closure və ya NotificationCenter abunəsi əlavə etdikdə. Tipik ssenarini yerinə yetirmək və obyektlərin düzgün sərbəst buraxıldığına, retain cycles-in olmadığına əmin olmaq kifayətdir. Bu 2–3 dəqiqə çəkir, lakin sonrakı saatlarla debug etmənin qarşısını alır.

Memory Report ilə kombinasiya

Memory Report Xcode-da (Debug Navigator vərəqəsi) real vaxtda yaddaş istehlakı qrafikini göstərir. Memory Graph ilə birlikdə istifadə edin: yaddaş istehlakı kəskin artdıqda Memory Graph-i açın. Məsələn, şəkillər yükləyən hüceyrələrlə uzun siyahını sürüşdürərkən, Memory Graph hansı obyektlərin yaradıldığını və hansının sərbəst buraxıldığını göstərəcək. Obyektlərin sayı azalmadan artırsa — bu potensial sızmadır, crash-a səbəb olmadan əvvəl görünür. Apple-ın məlumatına görə, Memory Graph + Memory Report kombinasiyası Xcode 12-dən başlayaraq bütün iOS tərtibatçıları üçün tövsiyə olunan iş axınıdır.

objective-c
// Objective-C-də delegasiya vasitəsilə sızma nümunəsi
@interface DownloadManager : NSObject
@property (strong) id delegate; // ❌ Weak olmalıdır!
@end

@implementation DownloadManager
// Memory Graph retain dövrünü göstərəcək:
// ViewController → DownloadManager.delegate → ViewController
@end

// Düzəliş: weak property
@property (weak) id delegate;

Closure-ların profilləşdirilməsi

Xüsusi diqqət closures-a yetirin — Swift-də retain cycles-in ən çox yayılmış mənbəyi. Obyektin xassəsi kimi saxlanılan closure daxilində self tutulduqda klassik dövr yaranır. Memory Graph bunu closure ( {} simvolu ilə düyün) kimi göstərir, tutulan obyektlərlə mavi kənarlarla birləşdirilir. Bütün closures-ları mütəmadi yoxlayın, xüsusən də asinxron çağırışlarda, GCD, Combine və SwiftUI-də istifadə olunanları. Point-Free statistikasına görə, Swift layihələrində sızmaların 90%-i self-i tutan closures ilə bağlıdır.

Tez-tez verilən suallar

Memory Graph yalnız Objective-C üçün işləyir, yoxsa Swift üçün də?

Memory Graph hər iki dil üçün işləyir, çünki Objective-C runtime-dan istifadə edir. ObjC ilə uyğun Swift obyektləri (NSObject varisləri, @objc ilə işarələnmiş) tam göstərilir. ObjC körpüsü olmayan təmiz Swift strukturları və sinifləri məhdud görünür.

Niyə Memory Graph bəzi obyektləri göstərmir?

Obyektlər Objective-C runtime-da qeydiyyatdan keçməlidir. Swift value types (struct, enum) göstərilmir. Sinfin NSObject-dən varis olduğuna və ya Memory Graph-da görünməsi üçün @objc atributundan istifadə etdiyinə əmin olun.

Qrafdakı kənar rənglərini necə şərh etməli?

Mavi — strong reference, obyekti saxlayır. Yaşıl — weak reference, həyat dövrünə təsir etmir. Boz — unowned reference. Retain cycle yalnız mavi kənarlardan əmələ gəlir.

Memory Graph tətbiqi yavaşıdırmı?

Qrafın qurulması tətbiqi 1–3 saniyə dayandırır və Xcode-un yaddaş istehlakını müvəqqəti olaraq 200–500 MB artıra bilər. Tətbiqin özü yavaşlamır, çünki yoxlama breakpoint-də pauza zamanı baş verir.

Memory Graph-i təhlil üçün ixrac etmək olarmı?

Xcode qrafın birbaşa ixracını dəstəkləmir. Sənədləşdirmə üçün ekran görüntüsü və ya lldb skripti heap.find_variable istifadə edin. Ətraflı təhlil üçün Instruments Allocations-dan heap dump ilə istifadə edin.

Nəticə

  • Memory Graph — yaddaşdakı obyektlərin istinadları ilə qrafını göstərən Xcode-un vizual aləti.
  • Retain cycle mavi (strong) kənarlardan qapalı kontur kimi göstərilir — Xcode onu narıncı rəngdə vurğulayır.
  • Backtrace qrafın hər bir kənarı üçün problemli istinadın yaradıldığı dəqiq kod yerini göstərir.
  • Filtrləmə siniflər və istinad növləri üzrə minlərlə obyekti olan qrafda sızmaları tecrid etməyə imkan verir.
  • Closure-lar Swift-də retain cycles-in əsas mənbəyidir, Memory Graph onları {} düyünləri kimi göstərir.
  • Weak və unowned dövrü qırmaq üçün həll yollarıdır, lakin nil-də təhlükəsizliyə görə weak üstünlük təşkil edir.
  • Mütəmadi Memory Graph yoxlaması arxitektura dəyişikliklərindən sonra layihədə yaddaş reqresiyasının qarşısını alır.

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