Öncelikle, nazik sözleriniz için teşekkür ederim. Gerçekten harika bir özellik ve küçük bir parçası olduğum için mutluyum.
Tüm kodum yavaşça eşzamansız hale geliyorsa, neden hepsini varsayılan olarak eşzamansız hale getirmiyorsunuz?
Eh, abartıyorsun; tüm kodunuz eşzamansız hale gelmiyor. İki "düz" tam sayıyı birbirine eklediğinizde, sonucu beklemiyorsunuz. Gelecekte üçüncü bir tam sayı elde etmek için gelecekteki iki tamsayıyı topladığınızda - çünkü bu Task<int>
, gelecekte erişebileceğiniz bir tam sayıdır - tabii ki büyük olasılıkla sonucu bekliyorsunuzdur.
Her şeyi eşzamansız yapmamanın birincil nedeni , eşzamansız / beklemenin amacının, birçok yüksek gecikme işleminin olduğu bir dünyada kod yazmayı kolaylaştırmak olmasıdır . İşlemlerinizin büyük çoğunluğu yüksek gecikme süreleri değildir , bu nedenle bu gecikmeyi azaltan performans vuruşunu almak mantıklı değildir. Aksine, işlemlerinizden önemli birkaçı yüksek gecikmedir ve bu işlemler kod boyunca zombi istilasına neden olan zaman uyumsuzluğuna neden olur.
tek sorun performans ise, kesinlikle bazı akıllı optimizasyonlar gerekli olmadığında ek yükü otomatik olarak kaldırabilir.
Teoride teori ve pratik benzerdir. Pratikte asla değildirler.
Bu tür bir dönüşüme karşı size üç puan vereyim ve ardından bir optimizasyon geçişi vereyim.
Yine ilk nokta şudur: C # / VB / F #'daki asenkron, esasen sınırlı bir devam etme biçimidir . İşlevsel dil topluluğundaki muazzam miktarda araştırma, devamlı geçiş stilinden yoğun bir şekilde yararlanan kodun nasıl optimize edileceğini belirleme yollarını bulmaya gitti. Derleyici ekibinin, "eşzamansız" ın varsayılan olduğu ve eşzamansız olmayan yöntemlerin tanımlanması ve eşzamansız hale getirilmesi gereken bir dünyada muhtemelen çok benzer sorunları çözmesi gerekecektir. C # ekibi, açık araştırma problemlerini üstlenmekle pek ilgilenmiyor, bu yüzden burada büyük noktalar var.
İkinci bir nokta, C # 'nın bu tür optimizasyonları daha izlenebilir kılan "referans şeffaflık" seviyesine sahip olmamasıdır. "Referans şeffaflığı" ile , bir ifadenin değerinin değerlendirildiğinde bağlı olmadığı özelliği kastediyorum . Gibi 2 + 2
ifadeler referans olarak şeffaftır; İsterseniz değerlendirmeyi derleme zamanında yapabilir veya çalışma zamanına erteleyerek aynı cevabı alabilirsiniz. Ancak x ve y zamanla değiştiğix+y
için gibi bir ifade zaman içinde hareket ettirilemez .
Async, bir yan etkinin ne zaman olacağı konusunda akıl yürütmeyi çok daha zor hale getirir. Eşzamansızdan önce,
M();
N();
ve M()
oldu void M() { Q(); R(); }
ve N()
oldu void N() { S(); T(); }
ve R
ve S
üretim yan etkileri, o zaman R'ın yan etkisi S'nin yan etkisi önce olur biliyorum. Ama eğer async void M() { await Q(); R(); }
öyleyse aniden pencereden dışarı çıkar. Önce mi R()
yoksa sonra mı olacağına dair hiçbir garantiniz yok S()
(tabii ki M()
beklenmedikçe; ama tabii ki Task
sonrasına kadar beklenmesine gerek yok N()
.)
Şimdi, hangi sırayla yan etkilerin oluştuğunu artık bilmeme özelliğinin, programınızdaki , optimize edicinin eşzamansız hale getirmeyi başardığı kodlar dışındaki her kod parçası için geçerli olduğunu hayal edin . Temelde artık hangi ifadelerin hangi sırayla değerlendirileceğine dair hiçbir fikriniz yok, bu da tüm ifadelerin referans olarak şeffaf olması gerektiği anlamına geliyor, bu da C # gibi bir dilde zor.
Üçüncü bir nokta da, "eşzamansız neden bu kadar özel?" Diye sormanız gerektiğidir. Her işlemin aslında bir işlem olması gerektiğini tartışacaksanız, Task<T>
"neden olmasın Lazy<T>
?" Sorusunu yanıtlayabilmeniz gerekir. veya "neden olmasın Nullable<T>
?" veya "neden olmasın IEnumerable<T>
?" Çünkü biz de bunu kolayca yapabiliriz. Neden her işlemin boş değer atanabilir hale getirilmesi söz konusu olmasın ? Ya da her işlem tembel olarak hesaplanır ve sonuç daha sonrası için önbelleğe alınır veya her işlemin sonucu, tek bir değer yerine bir değerler dizisidir . Daha sonra, "ah, bu asla boş olmamalı, böylece daha iyi kod üretebilirim" gibi durumları optimize etmeye çalışmalısınız.
Demek istediğim: Task<T>
Bu kadar çalışmayı garanti etmenin aslında o kadar özel olduğu benim için net değil .
Bu tür şeyler ilginizi çekiyorsa, Haskell gibi çok daha güçlü bir bilgi şeffaflığına sahip olan ve her türlü sıra dışı değerlendirmeye izin veren ve otomatik önbelleğe alma yapan işlevsel dilleri araştırmanızı tavsiye ederim. Haskell ayrıca, bahsettiğim "monadik kaldırma" türleri için kendi tip sisteminde çok daha güçlü bir desteğe sahip.