Érdekes

Swift Gyenge Hivatkozások

Eredeti Mike Ash az https://www.mikeash.com/pyblog/friday-qa-2015-12-11-swift-weak-references.html

Abban az esetben, ha már a Marson, egy barlangban, csukva a szemed, a füled, a Swift már nyílt forráskódú. Ez lehetővé teszi a kényelmes, hogy vizsgálja meg az egyik érdekes jellemzője Swift megvalósítás: milyen gyenge referenciák munka.

Gyenge Hivatkozások
A szemetet gyűjtött vagy referencia jelezni nyelv, egy erős referencia, amely tartja a céltárgy életben. Egy gyenge referencia van, amelyik nem. Egy tárgy nem lehet elpusztítani, amíg vannak erős utalások, de el lehet pusztítani, míg a gyenge referenciák.

Amikor azt mondjuk, hogy “gyenge referencia,” általában azt jelenti, hogy egy nullázás gyenge referencia. Ez az, amikor a cél a gyenge referencia megsemmisült, a gyenge referencia nil lesz. Az is lehetséges, hogy nem nullázás gyenge referenciák, ami csapda, baleset, vagy hivatkozhat orr démonok. Ez az, amit kapsz, ha használod unsafe_unretained az Objective-C, vagy unowned a Swift. (Megjegyzendő, hogy Objective-C ad nekünk az orr-démonok változat, míg a Swift-gondoskodik a baleset megbízhatóan.)

Nullázás gyenge referenciák hasznos segítség, ők pedig rendkívül hasznos a referencia számít nyelven. Lehetővé teszik, hogy a körkörös hivatkozásokat létezik létrehozása nélkül megtartja a ciklusok, majd anélkül, hogy kézzel törni vissza hivatkozásokat. Vannak olyan hasznos, hogy végre a saját verzióját a gyenge referenciák vissza, mielőtt az Apple bemutatta ARC nyelv-szint gyenge referenciák rendelkezésre kívül szemetet gyűjtött kódot.

Hogyan Működik?
A tipikus megvalósítási a nullázás gyenge referenciák, hogy listát készít a gyenge referenciák, hogy minden objektum. Amikor egy gyenge referencia jön létre, hogy egy tárgyat, hogy a referencia hozzáadódik a listához. Ha ez a hivatkozás a beosztást, vagy megy ki a hatálya, a listáról. Amikor egy objektum megsemmisül, mind a hivatkozásoknak a listáját vagy nullázni. Többszálú környezetben (pl. mind ezekben a napokban), a végrehajtás kell szinkronizálni megszerzése egy gyenge referencia pusztítani egy tárgy, hogy elkerüljék a verseny feltételeit, ha egy szál kiadások az utolsó erős referencia -, hogy egy tárgy, ugyanakkor egy másik szál megpróbálja betölteni egy gyenge referencia.

A végrehajtás egyes gyenge referencia egy teljes értékű tárgy. A lista a gyenge referenciák csak egy sor gyenge referencia tárgyakat. Ez hozzáteszi, néhány hatékonysági, mert az extra indirekciónak, memória használata, de jó, hogy megvan a hivatkozások teljes tárgyakat.

Az Apple Objective-C végrehajtása, minden gyenge referencia egy egyszerű mutató, hogy a céltárgy. Inkább, mint az írás-olvasás a tanácsot közvetlenül, a fordító használja segítő funkciók. Tárolásakor, hogy egy gyenge mutató, az áruház funkció nyilvántartások a mutató helyét, mint egy gyenge hivatkozás a cél. Ha olvasod a gyenge mutató, a read függvény integrálja a referencia számlálás rendszert, amely biztosítja, hogy soha nem tér vissza a mutatót egy objektum, hogy nem kötelező.

Nullázás Akció
Építsünk egy kis kódot, így meg tudjuk nézni a dolgokat megtörténni.

Azt akarjuk, hogy tudja dobni a tartalmát egy tárgy emléke. Ez a funkció kerül a régió, a memória, megtöri a mutató méretű darabokat, majd kiderült, hogy az egész dolog egy kényelmes hexadecimális karakterlánc:

    func contents(ptr: UnsafePointer<Void>, _ length: Int) -> String {
        let wordPtr = UnsafePointer<UInt>(ptr)
        let words = length / sizeof(UInt.self)
        let wordChars = sizeof(UInt.self) * 2

        let buffer = UnsafeBufferPointer<UInt>(start: wordPtr, count: words)
        let wordStrings = buffer.map({ word -> String in
            var wordString = String(word, radix: 16)
            while wordString.characters.count < wordChars {
                wordString = "0" + wordString
            }
            return wordString
        })
        return wordStrings.joinWithSeparator(" ")
    }

A következő funkció létrehoz egy dömper funkció objektum. A hívás egyszer egy objektumot, majd visszatér egy olyan funkció, hogy fogja kidobni a tartalom, ez a tárgy. Belsőleg, takarít egy UnsafePointer, hogy a tárgy használata helyett egy normális referencia. Ez biztosítja, hogy ez nem befolyásolja a nyelvi referencia számolja a rendszer. Azt is lehetővé teszi számunkra, hogy a szeméttelepen a memória egy tárgy után megsemmisült, ami jól jöhet később.

    func dumperFunc(obj: AnyObject) -> (Void -> String) {
        let objString = String(obj)
        let ptr = unsafeBitCast(obj, UnsafePointer<Void>.self)
        let length = class_getInstanceSize(obj.dynamicType)
        return {
            let bytes = contents(ptr, length)
            return "\(objString) \(ptr): \(bytes)"
        }
    }

Itt van egy osztály, hogy létezik, hogy a hold egy gyenge referencia, így tudjuk ellenőrizni. Én hozzá dummy változók mindkét oldalon, hogy egyértelmű legyen, ahol a gyenge referencia él a memóriakép:

    class WeakReferer {
        var dummy1 = 0x1234321012343210
        weak var target: WeakTarget?
        var dummy2: UInt = 0xabcdefabcdefabcd
    }

Tegyünk egy próbát! Kezdjük azzal, ami egy referer es dömping:

    let referer = WeakReferer()
    let refererDump = dumperFunc(referer)
    print(refererDump())

Nyomtatja:

    WeakReferer 0x00007f8a3861b920: 0000000107ab24a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd

Láthatjuk, hogy az isa az elején, majd egy másik belső területeken. dummy1 foglal el a 4-án darab, dummy2 foglal 6-án. Láthatjuk, hogy a gyenge referencia közöttük nulla, mint az várható volt.

Mondjuk pont egy tárgyat, aminek látszik. Majd itt do blokk, így tudjuk irányítani, ha a célpont megy ki a hatálya, megsemmisült:

    do {
        let target = NSObject()
        referer.target = target
        print(target)
        print(refererDump())
    }

Nyomtatja:

    <NSObject: 0x7fda6a21c6a0>
    WeakReferer 0x00007fda6a000ad0: 00000001050a44a0 0000000200000004 1234321012343210 00007fda6a21c6a0 abcdefabcdefabcd

Ahogy az várható volt, a mutató a cél tárolása közvetlenül a gyenge referencia. Dobjuk után újra a célpont megsemmisül a végén do blokk:

    print(refererDump())
    WeakReferer 0x00007ffe32300060: 000000010cfb44a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd

Egyre nullázni. Tökéletes!

Csak a móka kedvéért, ismételjük meg a kísérletet a tiszta Swift tárgy, mint a cél. Nem szép, hogy hozza Objective-C a képbe, ha nem szükséges. Itt egy tiszta Swift cél:

    class WeakTarget {}

Próbáljuk ki:

    let referer = WeakReferer()
    let refererDump = dumperFunc(referer)
    print(refererDump())
    do {
        class WeakTarget {}
        let target = WeakTarget()
        referer.target = target
        print(refererDump())
    }
    print(refererDump())

A cél indul ki nullázni, mint az várható volt, akkor kap címzett:

    WeakReferer 0x00007fbe95000270: 00000001071d24a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd
    WeakReferer 0x00007fbe95000270: 00000001071d24a0 0000000200000004 1234321012343210 00007fbe95121ce0 abcdefabcdefabcd

Akkor ha a célpont eltűnik, a referencia kell nullázni:

    WeakReferer 0x00007fbe95000270: 00000001071d24a0 0000000200000004 1234321012343210 00007fbe95121ce0 abcdefabcdefabcd

Ó drága. Nem nullázni. Lehet, hogy a cél nem semmisült meg. Valami kell, életben kell tartani! Ellenőrizzük újra:

    class WeakTarget {
        deinit { print("WeakTarget deinit") }
    }

Fut a kód újra kapunk:

    WeakReferer 0x00007fd29a61fa10: 0000000107ae44a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd
    WeakReferer 0x00007fd29a61fa10: 0000000107ae44a0 0000000200000004 1234321012343210 00007fd29a42a920 abcdefabcdefabcd
    WeakTarget deinit
    WeakReferer 0x00007fd29a61fa10: 0000000107ae44a0 0000000200000004 1234321012343210 00007fd29a42a920 abcdefabcdefabcd

Így megy el, de a gyenge referencia-nem teljesen. Mit szólnál, találtunk egy hiba Swift! Egészen elképesztő, hogy nem volt javítva, ennyi idő után. Nem gondolja, hogy valaki észrevette volna. Menjünk előre, majd létrehoz egy szép baleset elérésével a referencia, akkor indíthatunk egy bug a Swift-projekt:

    let referer = WeakReferer()
    let refererDump = dumperFunc(referer)
    print(refererDump())
    do {
        class WeakTarget {
            deinit { print("WeakTarget deinit") }
        }
        let target = WeakTarget()
        referer.target = target
        print(refererDump())
    }
    print(refererDump())
    print(referer.target)

Itt jön az összeomlás:

    WeakReferer 0x00007ff7aa20d060: 00000001047a04a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd
    WeakReferer 0x00007ff7aa20d060: 00000001047a04a0 0000000200000004 1234321012343210 00007ff7aa2157f0 abcdefabcdefabcd
    WeakTarget deinit
    WeakReferer 0x00007ff7aa20d060: 00000001047a04a0 0000000200000004 1234321012343210 00007ff7aa2157f0 abcdefabcdefabcd
    nil

Ó drága a négyzeten! Hol a bumm? Úgy volt, hogy lesz egy világrengető bumm! A kimeneti azt mondja, minden rendben működik, miután az összes, de világosan láthatjuk, hogy a szeméttelepen, hogy nem működik.

Hadd vizsgálja meg mindent nagyon alaposan. Itt egy módosított változata WeakTarget egy dummy változó, hogy szebb, hogy a szeméttelepen a tartalmát:

    class WeakTarget {
        var dummy = 0x0123456789abcdef

        deinit {
            print("Weak target deinit")
        }
    }

Itt van néhány új kód fut keresztül ugyanaz az eljárás, guba mind a tárgyakat, minden lépésnél:

    let referer = WeakReferer()
    let refererDump = dumperFunc(referer)
    print(refererDump())
    let targetDump: Void -> String
    do {
        let target = WeakTarget()
        targetDump = dumperFunc(target)
        print(targetDump())

        referer.target = target

        print(refererDump())
        print(targetDump())
    }
    print(refererDump())
    print(targetDump())
    print(referer.target)
    print(refererDump())
    print(targetDump())

Menjünk végig a kimenet. A referer indul ki az élet, mint korábban, egy nullázni cél területen:

    WeakReferer 0x00007fe174802520: 000000010faa64a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd

A cél indul ki az élet, mint egy normális tárgy, különböző fejléc mezők, majd a bábu mező:

    WeakTarget 0x00007fe17341d270: 000000010faa63e0 0000000200000004 0123456789abcdef

Amikor hozzárendelése a cél mezőben láthatjuk, hogy a mutató értéke tudjon tölteni:

    WeakReferer 0x00007fe174802520: 000000010faa64a0 0000000200000004 1234321012343210 00007fe17341d270 abcdefabcdefabcd

A cél sokkal, mint korábban, de a fejléc mezők ment 2:

    WeakTarget 0x00007fe17341d270: 000000010faa63e0 0000000400000004 0123456789abcdef

A cél elpusztul, mint várható:

    Weak target deinit

Látjuk, hogy a referer tárgy még mindig van egy mutató hogy a cél:

    WeakReferer 0x00007fe174802520: 000000010faa64a0 0000000200000004 1234321012343210 00007fe17341d270 abcdefabcdefabcd

A cél maga még mindig úgy néz ki, nagyon is él, bár egy másik fejléc mező ment le 2 képest, hogy utoljára láttuk:

    WeakTarget 0x00007fe17341d270: 000000010faa63e0 0000000200000002 0123456789abcdef

Elérése a cél területen termel nil bár nem teljesen:

    nil

Dömping a referer megint azt mutatja, hogy a puszta cselekmény elérése a cél mező megváltozott. Most találtam ki:

    WeakReferer 0x00007fe174802520: 000000010faa64a0 0000000200000004 1234321012343210 0000000000000000 abcdefabcdefabcd

A cél most már teljesen lekoptak:

    WeakTarget 0x00007fe17341d270: 200007fe17342a04 300007fe17342811 ffffffffffff0002

Egyre érdekesebb. Láttuk, fejléc mezők növelésére, valamint csökkentése egy kicsit, lássuk, ha tudjuk, hogy ez történik:

    let target = WeakTarget()
    let targetDump = dumperFunc(target)
    do {
        print(targetDump())
        weak var a = target
        print(targetDump())
        weak var b = target
        print(targetDump())
        weak var c = target
        print(targetDump())
        weak var d = target
        print(targetDump())
        weak var e = target
        print(targetDump())

        var f = target
        print(targetDump())
        var g = target
        print(targetDump())
        var h = target
        print(targetDump())
        var i = target
        print(targetDump())
        var j = target
        print(targetDump())
        var k = target
        print(targetDump())
    }
    print(targetDump())

Nyomtatja:

    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000200000004 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000400000004 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000600000004 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000800000004 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000a00000004 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c00000004 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c00000008 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c0000000c 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c00000010 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c00000014 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c00000018 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000c0000001c 0123456789abcdef
    WeakTarget 0x00007fd883205df0: 00000001093a4840 0000000200000004 0123456789abcdef

Láthatjuk, hogy az első szám a fejléc mező felmegy 2 minden új gyenge referencia. A második szám felmegy 4 minden új erős referencia.

Összefoglalva, mi az amit eddig láttunk:

  • Gyenge mutatók nézel ki, mint a hagyományos mutatók a memóriában.
  • Amikor egy gyenge célpont deinit fut a cél nem kötelező, de a gyenge mutató nem nullázni.
  • Amikor a gyenge mutató érhető el, miután a célpont deinit fut, nullázni a hozzáférést, valamint a gyenge cél nem kötelező.
  • A gyenge cél tartalmaz egy referencia szám a gyenge referenciák, külön a gróf referenciák.

Swift Kód
Most, hogy a Swift nyílt forráskódú, tudjuk, hogy hol kell vonatkozik ez a megfigyelt viselkedés, hogy a forráskódot.

A Swift standard könyvtár képviseli tárgyat juttatott, a heap egy HeapObject típus található stdlib/public/SwiftShims/HeapObject.h. Úgy néz ki, mint:

    struct HeapObject {
    /// This is always a valid pointer to a metadata object.
    struct HeapMetadata const *metadata;

    SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
    // FIXME: allocate two words of metadata on 32-bit platforms

    #ifdef __cplusplus
    HeapObject() = default;

    // Initialize a HeapObject header as appropriate for a newly-allocated object.
    constexpr HeapObject(HeapMetadata const *newMetadata) 
        : metadata(newMetadata)
        , refCount(StrongRefCount::Initialized)
        , weakRefCount(WeakRefCount::Initialized)
    { }
    #endif
    };

Mező metadata a Swift egyenértékű az isa területen Objective-C, sőt ez kompatibilis. Aztán ott vannak ezek a NON_OBJC_MEMBERS meghatározott a makró:

    #define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS       \
      StrongRefCount refCount;                      \
      WeakRefCount weakRefCount

Nos, nézd meg hogy! A két referencia számít.

(Bónusz kérdés: miért van az erős gróf első, míg a dob felett a gyenge gróf volt az első?)

A referencia számít kezelik egy csomó funkciók található stdlib/public/runtime/HeapObject.cpp. Például, itt van swift_retain:

    void swift::swift_retain(HeapObject *object) {
    SWIFT_RETAIN();
        _swift_retain(object);
    }
    static void _swift_retain_(HeapObject *object) {
        _swift_retain_inlined(object);
    }
    auto swift::_swift_retain = _swift_retain_;

Van egy csomó indirekciónak, de végül a hívásokat át, hogy ez a beépített függvény fejlécében:

    static inline void _swift_retain_inlined(HeapObject *object) {
      if (object) {
        object->refCount.increment();
      }
    }

Ahogy az várható volt, lépésekben a referencia számít. Itt a végrehajtása a increment:

    void increment() {
      __atomic_fetch_add(&refCount, RC_ONE, __ATOMIC_RELAXED);
    }

RC_ONE származik egy enum:

    enum : uint32_t {
      RC_PINNED_FLAG = 0x1,
      RC_DEALLOCATING_FLAG = 0x2,

      RC_FLAGS_COUNT = 2,
      RC_FLAGS_MASK = 3,
      RC_COUNT_MASK = ~RC_FLAGS_MASK,

      RC_ONE = RC_FLAGS_MASK + 1
    };

Láthatjuk, hogy miért a gróf ment fel 4 minden új erős referencia. Az első két bit a mező a használt zászlók. Visszatekintve a guba, láthatjuk, hogy azok a zászlók akcióban. Itt egy gyenge cél előtt, illetve után az utolsó erős referencia ment el:

    WeakTarget 0x00007fe17341d270: 000000010faa63e0 0000000400000004 0123456789abcdef
    Weak target deinit
    WeakTarget 0x00007fe17341d270: 000000010faa63e0 0000000200000002 0123456789abcdef

A mező ment a 4 jelöli referencia szám 1, nincs es 2, utaló hivatkozási száma nulla, RC_DEALLOCATING_FLAG beállítva. Ez a poszt-deinit tárgy kerül valamilyen DEALLOCATING a pokol tornáca.

(Mellesleg, mi RC_PINNED_FLAG? Megböktem keresztül a kód alap, de nem tudott kitalálni semmit azon túl, hogy ez azt jelzi, hogy “rögzített tárgy”, ami már elég nyilvánvaló, hogy a neve. Ha kitalálom, vagy egy megalapozott hiszem, kérjük, hozzászólásod.)

Nézzük meg a gyenge referencia szám végrehajtását, amíg itt vagyunk. Ez hasonló az enum:

    enum : uint32_t {
      // There isn't really a flag here.
      // Making weak RC_ONE == strong RC_ONE saves an
      // instruction in allocation on arm64.
      RC_UNUSED_FLAG = 1,

      RC_FLAGS_COUNT = 1,
      RC_FLAGS_MASK = 1,
      RC_COUNT_MASK = ~RC_FLAGS_MASK,

      RC_ONE = RC_FLAGS_MASK + 1
    };

Ez az, ahol a 2 származik: fenntartott hely, egy zászló, ami jelenleg kihasználatlan. Furcsa módon, a hozzászólás ezen a kód jelenik meg, hogy helytelen, mint RC_ONE itt az egyenlő 2-vel, mivel az erős RC_ONE egyenlő 4. Azt hiszem, ha egyenlő, akkor változott meg a hozzászólás nem volt frissítve. Csak azt bizonyítja, hogy a hozzászólások haszontalan, nem kellett valaha is írtam.

Hogyan működik ez a nyakkendő, a terhelés gyenge referenciák? Ez kezeli a funkció neve swift_weakLoadStrong:

    HeapObject *swift::swift_weakLoadStrong(WeakReference *ref) {
      auto object = ref->Value;
      if (object == nullptr) return nullptr;
      if (object->refCount.isDeallocating()) {
        swift_weakRelease(object);
        ref->Value = nullptr;
        return nullptr;
      }
      return swift_tryRetain(object);
    }

Ebből világos, hogy a lusta nullázás működik. Betöltésekor egy gyenge referencia, ha a célpont deallocating, nulla a referencia. Egyébként próbáld meg megőrizni a cél, majd vissza. Ásni egy kicsit tovább, láthatjuk, hogy az swift_weakRelease deallocates a tárgy memória, ha ez az utolsó referencia:

    void swift::swift_weakRelease(HeapObject *object) {
      if (!object) return;

      if (object->weakRefCount.decrementShouldDeallocate()) {
        // Only class objects can be weak-retained and weak-released.
        auto metadata = object->metadata;
        assert(metadata->isClassObject());
        auto classMetadata = static_cast<const ClassMetadata*>(metadata);
        assert(classMetadata->isTypeMetadata());
        swift_slowDealloc(object, classMetadata->getInstanceSize(),
                          classMetadata->getInstanceAlignMask());
      }
    }

(Megjegyzés: ha a kódot a repository, az elnevezés változott, hogy használja a “ensz tulajdonosa” ahelyett, hogy “gyenge” a legtöbb esetben. Az elnevezés a fenti a jelenlegi, mint a legújabb pillanatfelvétel, mint az időben az írás, de a fejlesztés folytatódik. Megtekintheti az adattár, mint a 2.2 pillanatkép látni, mint én itt, vagy megragad a legújabb, de legyen tisztában az elnevezés változik, esetleg végrehajtás változik.)

Mindezt összerakva
Láttunk mindent, fentről lefelé. Mi a magas szintű nézet, hogy a Swift gyenge referenciák tényleg működik?

  1. Gyenge referenciák, csak tanácsot, hogy a céltárgy.
  2. Gyenge referenciák külön nem nyomon követhető, ahogy vannak, a Objektum-C .
  3. Ehelyett az egyes Swift tárgy gyenge referencia szám mellett az erős referencia szám.
  4. Swift különválasztja tárgy deinitialization a tárgy deallocation. Egy objektum lehet deinitialized, felszabadítva a külső források nélkül deallocating a memória által elfoglalt, maga a tárgy.
  5. Amikor egy Swift objektum erős hivatkozási szám eléri a nullát, míg a gyenge gróf még mindig nagyobb, mint nulla, akkor a tárgy deinitialized de nem kötelező.
  6. Ez azt jelenti, hogy gyenge mutatók egy kötelező tárgy még érvényes mutatók lehet dereferenced ütközés nélkül vagy terhelés szemetet adatok. Csupán lényeg, hogy egy tárgy egy zombi állapotban.
  7. Amikor egy gyenge referencia van töltve, a runtime ellenőrzi a célpont állam. Ha a célpont egy zombi, akkor nulla a gyenge referencia, csökken a gyenge referencia szám, visszatér  nil.
  8. Amikor gyenge referenciák, hogy egy zombi tárgy vagy nullázni, a zombi nem kötelező.

Ez a design egy érdekes következményei képest Objektum-C megközelítés:

  • Nincs lista a gyenge referenciák fenn sehol. Ez leegyszerűsíti a kód, valamint javítja a teljesítményt.
  • Nincs verseny feltétel között nullázás egy gyenge referencia-egy szál, rakodás, hogy gyenge referencia egy másik szál. Ez azt jelenti, hogy betöltése egy gyenge referencia pusztítani egy gyengén-hivatkozott objektum lehet tenni megszerzése nélkül a zár. Ez javítja a teljesítményt.
  • Gyenge referenciák, hogy egy tárgy lesz, mert az objektum emlék marad kiosztott még azután is, nincsenek erős utalások, amíg az összes gyenge referenciák sem töltve vagy meg kell semmisíteni. Ez átmenetileg növeli a memória használat. Vegye figyelembe, hogy a hatás kicsi, mert amíg a célpont tárgy emléke továbbra is kiosztott, csak a memória az esetben is. A külső források (beleértve a tároló Array vagy Dictionary tulajdonságok) felszabadult, amikor az utolsó erős referencia elmúlik. Egy gyenge referencia okozhat egy példány marad osztják, de nem egy egész fa tárgyak.
  • Extra memória szükséges tárolni a gyenge referencia szám minden objektum. A gyakorlatban úgy tűnik, hogy ez lényegtelen, a 64-bites. A fejléc mezők szeretné, hogy elfoglalja egész számú mutató méretű darabokat, az erős, illetve gyenge referencia számít megosztani. Ha a gyenge referencia szám nem volt ott, az erős hivatkozási szám csak elfoglalni mind a 64 bit önmagában. Lehetséges, hogy az erős referencia egyébként is beköltözött az isa segítségével nem mutató isa, de nem vagyok benne biztos, hogy ez milyen fontos vagy, hogyan fog végződni a hosszú távú. A 32-bites, úgy tűnik, a gyenge gróf növeli a tárgy méretben négy bájt. Annak fontosságát, hogy a 32 bites csökken, a nap ugyanakkor.
  • Mert elérése gyenge mutató olyan olcsó, ugyanaz a mechanizmus lehet használni, hogy végre megbízható szemantika a unowned. A motorháztető alatt, unowned pontosan úgy weak, mint gyenge, kivéve, hogy nem hangosan, ha a cél ment el inkább, mint visszatérő nulla. Az Objective-C, __unsafe_unretained végre, mint egy nyers mutató a nem definiált viselkedést, ha a hozzáférési késő, mert állítólag gyorsan betöltése egy gyenge mutató kissé lassú.

Következtetés
Swift gyenge mutatók használata egy érdekes megközelítés, amely pontossága, sebessége, valamint az alacsony memória fölött. Nyomon gyenge referencia szám minden egyes tárgy, függetlenítés tárgy deinitialization a objct deallocation, gyenge referenciák lehet oldani mindkét biztonságosan, gyorsan. A rendelkezésre álló forrás kódot a standard könyvtár lehetővé teszi számunkra látni, hogy pontosan mi is folyik a forrás szintje, könyörgés helyett keresztül disassemblies, memória guba olyan gyakran. Természetesen, mint látható a fenti, nehéz megtörni ezt a szokást, teljes mértékben.

 

Vissza a főoldalra