NSOperation vs Grand Central Dispatch


465

İOS için eşzamanlı programlama hakkında bilgi ediniyorum. Şimdiye kadar okudum NSOperation/NSOperationQueue ve GCD. Aşırı veya tersini kullanmanın nedenleri nelerdir ?NSOperationQueueGCD

İkisi gibi Sesler GCDve NSOperationQueueuzak soyut açık yaratma NSThreadskullanıcısından. Ancak iki yaklaşım arasındaki ilişki benim için net değil, bu yüzden takdir edilecek herhangi bir geri bildirim!


10
İyi soru için +1 - sonuçları merak ediyorum. Şimdiye kadar, GCD'nin CPU çekirdeklerine kolayca gönderilebildiğini ve "yeni sıcak bok" haline geldiğini okudum.
Till


Yanıtlar:


517

GCDgöreve dayalı bir eşzamanlılık modelinin çok basit kullanımını sağlayan düşük düzeyli C tabanlı bir API'dir. NSOperationve NSOperationQueuebenzer bir şey yapan Objective-C sınıflarıdır. NSOperationfakat itibariyle ilk tanıtıldı 10.5 ve iOS 2 , NSOperationQueueve arkadaşlar dahili olarak kullanılarak uygulanmaktadır GCD.

Genel olarak, ihtiyaçlarınıza en uygun soyutlama seviyesini kullanmalısınız. Bu , desteklemeyen bir şey yapmanız gerekmediği sürece genellikle NSOperationQueueyerine kullanmanız gerektiği anlamına gelir .GCDNSOperationQueue

Bunun NSOperationQueueGCD'nin "küçültülmüş" bir versiyonu olmadığını unutmayın ; Aslında, çok basit bir şekilde yapabileceğiniz birçok şey var, bu da safla çok NSOperationQueueçalışın GCD. (Örnekler: bir seferde yalnızca N işlemi çalıştıran bant genişliği kısıtlı kuyruklar; işlemler arasında bağımlılıklar oluşturmak. Hem çok basit hem de NSOperationçok zor GCD.) Apple, çok güzel bir nesne dostu API oluşturmak için GCD'den yararlanma konusunda çok çalıştı NSOperation. Yapmamanız için bir nedeniniz yoksa işlerinden yararlanın.

Dikkat : Öte yandan, gerçekten sadece bir blok göndermeniz gerekiyorsa ve sağlayan ek işlevlerden herhangi birine ihtiyacınız yoksa NSOperationQueue, GCD'yi kullanmanın yanlış bir yanı yoktur. Bunun iş için doğru araç olduğundan emin olun.


1
NSOperation özel bir soyut sınıf olmak.
Roshan

3
@Sandy Aslında tam tersi, GCD NSOperation tarafından kullanılır (en azından iOS ve OS X'in sonraki sürümlerinde).
garrettmoon

1
@BJ Homer Seri dağıtım kuyruğuna ulaşmak için depeancy'ye görev ekleyebiliriz. Operasyon kuyruğunun bundan nasıl avantajlı olduğunu doğrulayın
Raj Aggrawal

3
@RajAggrawal Evet, işe yarıyor… ama sonra bir seri kuyruğuna takıldınız. NSOperation "bu üçü tamamlandıktan sonra, ancak diğer tüm şeylerle eşzamanlı olarak bu işlemi yürütebilir". İşlem bağımlılıkları, farklı kuyruklardaki işlemler arasında bile var olabilir. Çoğu insan buna ihtiyaç duymaz, ancak eğer yaparsanız, NSOperation daha iyi bir seçim olacaktır.
BJ Homer

369

İlgili bir soruya cevabım doğrultusunda, BJ ile aynı fikirde olmayacağım ve GCD'ye ihtiyacınız olmayan bir şey sağlamadığı sürece öncelikle NSOperation / NSOperationQueue üzerinden GCD'ye bakmanızı öneririm.

GCD'den önce, eşzamanlılığı yönetmek için uygulamalarımda çok sayıda NSOperations / NSOperationQueues kullandım. Bununla birlikte, GCD'yi düzenli olarak kullanmaya başladığımdan beri, neredeyse tamamen NSOperations ve NSOperationQueues'ı bloklar ve dağıtım kuyruklarıyla değiştirdim. Bu, her iki teknolojiyi de pratikte nasıl kullandığımdan ve üzerinde gerçekleştirdiğim profilden geldi.

İlk olarak, NSOperations ve NSOperationQueues kullanırken önemsiz miktarda ek yük var. Bunlar Kakao nesneleridir ve tahsis edilmeleri ve yeniden yerleştirilmeleri gerekir. 60 FPS'de 3 boyutlu bir sahne oluşturan yazdığım bir iOS uygulamasında, oluşturulan her kareyi kapsüllemek için NSOperations kullanıyordum. Bunu profillediğimde, bu NSOperations'ın oluşturulması ve sökülmesi, çalışan uygulamadaki CPU döngülerinin önemli bir bölümünü oluşturuyordu ve işleri yavaşlatıyordu. Bunları basit bloklar ve bir GCD seri kuyruğu ile değiştirdim ve bu ek yük kayboldu ve kayda değer ölçüde daha iyi oluşturma performansı sağladı. Bu, NSOperations'ı kullanmanın yükünü fark ettiğim tek yer değildi ve bunu hem Mac hem de iOS'ta gördüm.

İkincisi, NSOperations kullanırken eşleşmesi zor olan blok tabanlı gönderim kodunun şıklığı var. Bir bloğa birkaç satır kod sarmak ve seri veya eşzamanlı bir kuyrukta gerçekleştirilmek üzere göndermek son derece kullanışlıdır, burada bunu yapmak için özel bir NSOperation veya NSInvocationOperation oluşturmanın çok daha fazla destekleyici kod gerektirmesi gerekir. Bir NSBlockOperation kullanabileceğinizi biliyorum, ancak GCD'ye bir şey gönderiyor olabilirsiniz. Bu kodu, uygulamanızdaki ilgili işlemlerle birlikte bloklar halinde sarmak, bence bu görevleri kapsayan ayrı yöntemlere veya özel NSOperations'a sahip olmaktan daha iyi kod organizasyonuna yol açar.

NSOperations ve NSOperationQueues hala çok iyi kullanımlara sahiptir. GCD'nin NSOperationQueues'ın oldukça karmaşık bağımlılık grafikleri ayarlayabileceği gerçek bir bağımlılık kavramı yoktur. Birkaç durumda NSOperationQueues kullanıyorum.

Genel olarak, genellikle görevi yerine getiren en yüksek soyutlama düzeyini kullanmayı savunurken, bu, GCD'nin alt düzey API'sı için tartıştığım bir durumdur. Bu konu hakkında konuştuğum iOS ve Mac geliştiricileri arasında, çoğunluğu desteksiz işletim sistemi sürümlerini (iOS 4.0 ve Snow Leopard öncesi olanlar) hedeflemedikçe NSOperations üzerinden GCD kullanmayı tercih ediyor.


20
Ben sadece orta derecede katılmıyorum; Biraz sade GCD kullanıyorum. Ama bu cevapta NSBlockOperation'ı çok fazla indirdiğinizi düşünüyorum. NSOperationQueue'nun tüm bağımlılıkları (bağımlılıklar, hata ayıklama, vb.) Blok işlemleri için de geçerlidir.
BJ Homer

4
@BJHomer - NSBlockOperation'dan kaçınmanın benim durumumda daha çok kişisel bir tercih olduğunu düşünüyorum, ancak genel olarak kullanımlarından kaynaklanan yükü birkaç uygulamayı aşağı çektiğini gördükten sonra NSOperations'tan uzaklaştım. Blok kullanacaksam, bağımlılık desteğine ihtiyaç duyduğum nadir istisna dışında, GCD'de her şeyi yapmaya eğilimliyim.
Brad Larson

1
+1, bu analiz için teşekkürler. Apple her ikisini de savunuyor gibi görünüyor (WWDC 2012'nin eşzamanlı UI oturumunda olduğu gibi), bu çok takdir ediliyor.
orip

1
@VolureDarkAngel - GCD, bu tür gönderileri ele alma konusunda son derece hızlıdır. Yavaş G / Ç erişimleri veya bu tür bir şey nedeniyle bir yığın güncellemeyi bir kuyruğa yedeklemediğiniz sürece, açıkladığınız gibi bir durumda darboğazınız olmamalıdır. Yine de bu muhtemelen böyle değil.
Brad Larson

1
asma22 - Parçalar halinde yapılabilen hesaplamaları yapmak yaygındır, ancak bir aşamanın son hesaplaması, önceki birkaç aşamadan elde edilen sonuçlara ihtiyaç duyabilir. Bu durumda, daha sonraki işlemin önceki işlemlere bağlı olmasını sağlayabilirsiniz ve zamanlama, son işlem gerçekleştirilmeden önce tamamlanacak şekilde yönetilir.
Brad Larson

101

GCDdüşük seviyeli C tabanlı bir API'dir.
NSOperationve NSOperationQueueObjective-C sınıflarıdır.
NSOperationQueuenesnel C sarıcıdır GCD. NSOperation kullanıyorsanız, dolaylı olarak Grand Central Dispatch kullanıyorsunuz .

NSOperation'a göre GCD avantajı:
i. uygulama
için GCDuygulanması çok hafif olduğu
NSOperationQueuekarmaşıktır ve ağır

GCD'ye kıyasla NSOperation avantajları:

ben. Kontrol
Çalışırken Duraklatılabilir, İptal Edebilir, SürdürülebilirNSOperation

ii. Bağımlılıklar
Eğer ikisi arasında bir bağımlılık ayarlayabilirsiniz NSOperations
tüm bağımlılıklarını bitmiş için geçerli dönünceye kadar operasyon başladı olmayacaktır.

iii. İşlem Durumu,
işlem veya işlem kuyruğunun durumunu izleyebilir. hazır, yürütme veya bitirme

iv. Maksimum İşlem Sayısı
Aynı anda çalışabilecek maksimum kuyrukta işlem sayısını belirleyebilirsiniz

Ne zaman gitmeli GCDveyaNSOperation
kuyruk üzerinde daha fazla kontrol (yukarıda belirtilenlerin tümü) kullanmak NSOperation istediğinizde ve daha az ek yükü istediğiniz basit durumlar için (çok az ek çalışma ile "arka plana" biraz iş yapmak istiyorsunuz)GCD

ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/ http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html http : //nshipster.com/nsoperation/


Söylendiği gibi, Maksimum Operasyon sayısı NSOperationQueue'da belirtilebilir, O zaman GCD'de maksimum operasyon sayısı (sevk kuyrukları) ne olabilir? Bir projem olduğunu varsayalım, o zaman kaç işlem (gönderme kuyrukları) yapabilirim. ya da onların yapabileceğimiz herhangi bir maksimum limiti vardır.
Roshan Sah

Buradaki sistem koşullarına bağlıdır ayrıntılı bilgi: stackoverflow.com/questions/14995801/…
Sangram Shivankar

DispatchWorkItem'i kullanarak GCD'deki görevi de iptal edebiliriz ve ayrıca askıya alabilir ve devam edebiliriz
Ankit garg

@Ankitgarg Çağrı DispatchWorkItem üzerinde iptal işlemi, henüz çalıştırılmamışsa görevlerin yürütülmesini durdurur, ancak zaten yürütülmekte olan bir şeyi durdurmaz. ve nasıl bir DispatchWorkItem duraklatmak / devam ettirmek ??
abhimuralidharan

34

GCD yerine NSOperation'ı tercih etmenin bir başka nedeni, NSOperation'ın iptal mekanizmasıdır. Örneğin, düzinelerce fotoğraf gösteren 500 piksel gibi bir Uygulama, NSOperation'ı kullanarak tablo görünümünü veya koleksiyon görünümünü kaydırdığımızda görünmez görüntü hücrelerinin isteklerini iptal edebiliriz, bu Uygulama performansını büyük ölçüde artırabilir ve bellek ayak izini azaltabilir. GCD bunu kolayca destekleyemez.

Ayrıca NSOperation ile KVO mümkün olabilir.

İşte Eschaton'dan okumaya değer bir makale.


4
Bu ne iptal ediyor resim yükleme ağ operasyonu ise, o zaman gerek yok fazlalaştı NSOperationolarak, bunun için NSURLSessionTask.cancelve NSURLSession.invalidateAndCancelbu işlevsellik sağlar. Genel olarak, NSURLSessionbir an işlevselliğini bazı sağlar NSOperationQueue, gibi NSURLSessionTaskbirNSOperation
algal

@algal Burada açıklandığı gibi ( stackoverflow.com/questions/21918722/… ), NSURLSession NSOperationQueue'yu bir yapı taşı olarak kullanıyor gibi görünüyor.
kalan nawarathne

33

GCD gerçekten de NSOperationQueue'dan daha düşük seviyededir, başlıca avantajı, uygulamanın çok hafif olması ve kilitsiz algoritmalara ve performansa odaklanmasıdır.

NSOperationQueue, GCD'de bulunmayan tesisler sağlar, ancak önemsiz bir maliyetle gelirler, NSOperationQueue'nun uygulanması karmaşık ve ağırdır, çok fazla kilitleme içerir ve GCD'yi dahili olarak sadece çok az bir şekilde kullanır.

NSOperationQueue tarafından sağlanan olanaklara elbette ihtiyacınız varsa, ancak GCD ihtiyaçlarınız için yeterliyse, daha iyi performans, önemli ölçüde daha düşük CPU ve güç maliyeti ve daha fazla esneklik için doğrudan kullanmanızı tavsiye ederim.


24

Hem NSQueueOperations hem de GCD, UI Uygulama Ana Sırtını serbest bırakarak ayrı iş parçacıkları üzerinde arka planda ağır hesaplama görevinin yürütülmesine izin verir.

Peki, önceki gönderiye dayanarak NSOperations'ın addDependency özelliğine sahip olduğunu görüyoruz, böylece işleminizi sırayla sıraya alabilirsiniz.

Ama aynı zamanda dispatch_queue_create kullanarak kuyrukta işlemlerinizi çalıştırmak oluşturabilirsiniz GCD seri Kuyrukları hakkında okudum. Bu, bir dizi işlemin birbiri ardına sıralı bir şekilde yürütülmesine izin verecektir.

GQ'dan NSQueueOperation Avantajları:

  1. Bağımlılık eklemenize izin verir ve bağımlılığı kaldırmanıza izin verir, böylece bir işlem için bağımlılığı kullanarak sıralı olarak çalışabilir ve diğer işlemler için GCD bu şekilde çalışmaya izin vermez.

  2. Bir işlemi kuyruktaysa iptal etmek kolaydır, çalışıyorsa durdurulabilir.

  3. Maksimum eşzamanlı işlem sayısını tanımlayabilirsiniz.

  4. Kuyrukta oldukları işlemi askıya alabilirsiniz

  5. Sırada bekleyen kaç işlem olduğunu bulabilirsiniz.


6

GCD'nin kullanımı çok kolaydır - arka planda bir şey yapmak istiyorsanız, tek yapmanız gereken kodu yazmak ve bir arka plan kuyruğuna göndermektir. Aynı şeyi NSOperation ile yapmak birçok ek iştir.

NSOperation'ın avantajı, (a) mesaj gönderebileceğiniz gerçek bir nesneniz olması ve (b) bir NSOperation'ı iptal edebilmenizdir. Bu önemsiz değil. NSOperation'ı alt sınıfa ayırmanız gerekir, iptal işleminin ve bir görevi doğru şekilde bitirmenin her ikisinin de doğru çalışması için kodunuzu doğru yazmanız gerekir. Yani basit şeyler için GCD kullanırsınız ve daha karmaşık şeyler için bir NSOperation alt sınıfı yaratırsınız. (NSInvocationOperation ve NSBlockOperation alt sınıfları vardır, ancak yaptıkları her şey GCD ile daha kolay yapılır, bu yüzden bunları kullanmak için iyi bir neden yoktur).


3

NSOperations, sadece Grand Central Dispatch üzerine kurulmuş bir API'dir. Dolayısıyla, NSOperations'ı kullanırken, hala Grand Central Dispatch kullanıyorsunuz. Sadece NSOperations size hoşunuza gidebilecek bazı fantezi özellikler sunuyor. Bazı işlemleri diğer işlemlere bağımlı hale getirebilir, öğeleri bölündükten sonra kuyrukları yeniden sıralayabilirsiniz ve bunun gibi diğer şeyleri yapabilirsiniz. Aslında, ImageGrabber zaten NSOperations ve operasyon kuyruklarını kullanıyor! ASIHTTPRequest bunları başlık altında kullanır ve isterseniz farklı davranış için kullandığı işlem kuyruğunu yapılandırabilirsiniz. Peki hangisini kullanmalısınız? Uygulamanız için hangisi mantıklıysa. Bu uygulama için oldukça basit, bu yüzden doğrudan Grand Central Dispatch'i kullandık, NSOperation'ın fantezi özelliklerine gerek yok. Ancak uygulamanız için onlara ihtiyacınız varsa, kullanmaktan çekinmeyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.