20 puan yazan carnoxen 2024-11-27 | 11 yorum | WhatsApp'ta paylaş

Özet

Bu yazı, Rust geliştiricileri ile mevcut Linux geliştiricileri arasındaki anlaşmazlığı izledikten sonra kaleme alındı. Farklı geliştiricilerin farklı kodlama stillerine sahip olması normaldir, ancak Linux projesi geçmişte zaten C++'ı dışlayarak onun kod stili ve yapısından (RAII) kaçınmıştı.

Asahi Lina'nın bahsettiği kodun çalışma biçimi, o program sonlandırılırken fazla yavaştır ve performans odaklı yazılım geliştirmenin en temel yöntemi olan toplu işlemle çelişir. Örneğin, bellek alanlarını kullanarak toplu işlem yapmak birden fazla ömrü tek bir yapıda koordine edebilir; bu yüzden RAII gerekmez.

Burada, iddiamı destekleyen bazı kaynaklar var. Bu kaynakların hepsi toplu işlemin neden iyi olduğunu anlatıyor:

Bu yüzden Linux'un hiçbir zaman RAII'yi benimsememesi gerektiğini düşünüyorum.


Bu yazıyı buraya taşımamın nedeni şu: Kore'deki Rust geliştiricilerinin o yazıyı görüp defalarca çok öfkelendiğini gördüm; bu yüzden buradakilerin ne düşündüğünü merak ettim. Siz ne düşünüyorsunuz?

11 yorum

 
techiemann 2024-12-03

Bu benim görüşüm ama bazı geliştiricilerin elitizmini bir ölçüde anlayabiliyorum. Yazılım "mühendisliği" açısından bakıldığında, özellikle Linux gibi günümüz açık kaynak dünyasında kapalı kaynak tarafıyla da geniş ölçüde el ele verip açık kaynak felsefesinin ilerlemesine katkı sağlamış böyle bir "yazılım" bulmak zor; bu yüzden doğrulanmamış programcıların Rust’u öne sürerek sel gibi içeri dolup mevcut proje bakımının çekirdeğini oluşturanların denetiminden çıkan kodları oraya buraya ekleyerek teknik borcu pervasızca artırıp Linux’un yaşam döngüsünü kısaltmasından endişe ettikleri için daha dışlayıcı, hatta Luddite gibi görünen muhafazakâr bir tutumu benimsiyor olabilirler, değil mi?

Açık kaynağın uzun süre açık kaynak olarak kalabilmesi için pek de "açık" olmayan bir tavır takınması ilginç.

 
nullbus 2024-12-02

Ben de RAII ya da benzer türde kaynak yönetimini sık kullanıyor ve tavsiye ediyorum. Çünkü RAII’nin ne olduğunu bile bilmeden, düşünmeden kullanılsa bile "en azından güvenli" kod ortaya çıkıyor.

Ancak ne yaptığını gerçekten bilmeden kullanılırsa, bir dosyayı yalnızca bir kez açmak yeterliyken onlarca kez açıp kapatan türde verimsiz kodların çoğalması çok olasıdır. Geliştirici performansa sürekli ilgi gösteriyorsa ve böyle bir kültür geliştirme ekibinde temel bir anlayış olarak yerleşmişse, RAII ile de fazlasıyla yeterli düzeyde performans elde edilebileceğini düşünüyorum.

 
aer0700 2024-11-30
  1. RAII: Her nesne ortadan kalktığında free çalıştırmak
  2. Toplu çalıştırma? free edilmesi gerekenleri bir araya toplayıp bulk olarak çalıştırmak?
    Linux'ta 2'nin 1'den daha hızlı çalışmasını sağlayan bir özellik? API gibi bir şey var mı?
    Ben doğal olarak hep 1'le yaşadığım için, tam anlayamıyorum.
 
kandk 2024-11-29

Geliştirmeyi tamamlayıp valgrind ile bellek sızıntısı aradığım geliştirme deneyimine tekrar dönmek istemiyorum.

 
kandk 2024-11-29

Tam olarak emin değilim ama RAII kullanmayacağız demek, kasıtlı bellek sızıntılarından yararlanarak (kapatma) performansını artıracağız demek gibi geliyor; bunun doğru yaklaşım olup olmadığından emin değilim.
Nasıl olsa belleği elle iyi yöneten bir geliştirici RAII’yi de iyi kullanır; RAII olmadan geliştirme yapamayan bir geliştirici de belleği elle yönetemez, dolayısıyla RAII kullanmamak için bir sebep varmış gibi görünmüyor.

 
foriequal0 2024-11-29

free'nin ne kadar zaman harcadığını merak ettiğim için, gerçek iş yüklerinden oldukça farklı olsa da basitçe bir kod yazıp test ettim. (Rust release build ile, std::alloc::alloc ve std::fs::File kullandım.)
Farklı boyutlarda 10.000.000 adet bellek bloğu, toplam yaklaşık 2,5 GB ayırıp yalnızca serbest bırakma süresini ölçtüğümde 1,87 saniye sürdü. Parça başına 187 ns ediyor.
Buna karşılık dosya tarafında, yalnızca yaklaşık 10.000 handle açık tutup kapatmanın ne kadar sürdüğünü ölçtüğümde yaklaşık 9 saniye çıktı. Dosya başına 900 us sürmüş oluyor.
(Bu Windows PC'de antivirüs yüzünden mi bilmiyorum ama dosya işlemleri özellikle yavaş. Başka bir Windows dizüstünde sırasıyla 400 ns/200 us, başka bir Linux PC'de ise 50 ns/600 ns gördüm.)

RAII'ye alternatif olarak bulk işleme ya da çıkışta OS'ye güvenip kaynakları sızdırma yöntemi sıkça anılıyor; bellek için bu kolayca mümkün görünüyor.
Ama dosya ya da soket gibi kaynaklar için bir bulk toplama API'si görmedim ve kaynağı sızdırırsanız kullanıcı kodundaki süre azalabilir ama azalan miktar kadar bu kez kernel'in süreci sonlandırmak için harcadığı süre artıyor; dolayısıyla performans kazancı pek olmuyor.

Bellek RAII'si görece o kadar da yavaş değil; arena kullanımını imkansız kılan bir teknik de değil ve gerekirse kasıtlı sızıntıyı engelleyen bir şey de değil, bu yüzden RAII'den kaçınmak için güçlü bir gerekçe olmakta zorlanıyor gibi geliyor.
Daha da yavaş olan dosya RAII'si söz konusu olduğunda ise, bulk işleme yolu da yokken ve maliyetten kaçınmanın da bir yolu yokken, RAII alternatiflerinin ne kadar daha iyi olduğunu merak ediyorum.


Biraz konu dışı ama, RAII ve lifetime hakkındaki itirazların yalnızca malloc/free ile temsil edilen bellek kaynaklarıyla sınırlı tartışıldığı izlenimini alıyorum.
RAII ve lifetime yalnızca bellek tahsisi için değil; dosya, soket, lock gibi OS kaynaklarının yanı sıra object pool, connection pool gibi
edinme ve iade etme adımları olan, edinilmiş durumdayken münhasır erişim denetimi gerektiren çoğu kaynağın modellenmesinde de genel olarak faydalıdır.

Bu kaynaklar da malloc/free ile aynı yapıyı paylaştığı için leak, use after free, double free gibi aynı yapısal sorunları paylaşır;
ve bu ortak yapı sayesinde RAII ile lifetime'ın yalnızca bellek değil, bu tür kaynakların sorunlarını da aynı anda çözdüğü noktasının daha fazla öne çıkarılması gerektiğini düşünüyorum.
Örneğin Rust, dosya handle'ları için de use after close ve double close'u compile time'da önler:
https://play.rust-lang.org/?version=stable&mode=debug&edition=…

Başlıca GC dilleri belleği GC ile yönetse de sonuçta dosya handle'ı, soket gibi deterministik yönetim gerektiren kaynaklar için
RAII benzeri yapılar (Java'nın try-with-resources statement'ı, C#'ın using statement'ı, Python'un with statement'ı gibi) ya da benzer yapılar (Go'nun defer'i gibi)
eklemek zorunda kalıyor ve sonuçta tek bir dil içinde birden çok kaynak yönetim modu ortaya çıkıyor; bana kalırsa bu yaklaşım yerine buradaki model biraz daha iyi gibi.

 
crosh 2024-11-28
  1. Linux’te C++’ı dışlayarak RAII’den kaçınıldığı doğru, ancak bunun Linux’un C++’tan RAII’den kaçınmak için uzak durduğuna dair yeterli bir kanıt olduğunu düşünmüyorum. Paylaştığınız Linus mektubunda RAII kelimesi geçmiyor.
  2. Açık konuşmak gerekirse, “Asahi Lina’nın...” diye başlayan paragraftan itibaren verilen bağlantıların hepsi onlarca dakikalık YouTube videoları, bu yüzden takip etmesi zor. RAII’nin gerekli olmadığı durumlara dair teknik ve örnek temelli açıklamalar verebilirseniz tartışma daha da canlanacaktır.

Örneğin, bellek alanı kullanarak toplu işlem yapmak, birden fazla yaşam süresini tek bir yaşam süresi altında ayarlayabildiği için RAII gerektirmez.

Bununla arena’yı kastediyorsanız, Rust’ta da elbette arena vardır; ayrıca lifetime kullanarak arena’yı ortadan kaldırdıktan sonra, yani “toplu serbest bırakma” yapıldıktan sonra arena’nın öğelerine erişimi yasaklamak da mümkündür. Lütfen https://crates.io/keywords/arena adresine bakın.

 
ztaka 2024-11-28

Ben Zig veya Rust'tan sonra da daha çok dil çıkmasını isterim. Ama şu ana kadar Rust kadar uygun bir dil görmedim. Hatta böyle diller arasındaki tartışmalardan ortaya çıkan geliştiriciler arası bilginin daha faydalı olduğunu düşünüyorum. Haha..

 
shoyuvanilla 2024-11-28

Ben de ağırlıklı olarak Rust kullanan bir geliştiriciyim; öfkelenmedim ama biraz uç bir örnek getirilmiş gibi geliyor ("o programı kapatırken fazla yavaş" denilerek bağlantı verilen videoda da, Rust projesindeki örneklerle doğrudan ilişkili olmayan, Visual Studio kapanırken her bir ayrı bileşenin yıkıcısının çağrılması yüzünden aşırı uzun sürmesi örneği veriliyor).

Performans açısından birden fazla bileşenin temizliğinin tek seferde yapılması gereken durumlarda, her bir bileşen için Drop uygulamak yerine bu bileşenlerin ömrünü elinde tutan tipte temizliği topluca gerçekleştiren bir Drop uygulaması tercih edilebilir gibi görünüyor. İlgili bileşenlerin yalnızca o tipin API’si üzerinden oluşturulabilmesini sağlayan bir güvenlik önlemi konursa daha da iyi olur.

Elbette yukarıdaki yazının yazarının kaygısı muhtemelen şu: RAII kullanma pratiği Linux kod tabanına girerse, çok geniş bir kod tabanındaki karmaşıklık içinde performans açısından oldukça örtük riskler taşıyan kodlar birikerek uzun vadede Visual Studio’dakine benzer bir durum ortaya çıkabilir. Bu, gerçekten de yeterince kaygı verici bir nokta gibi görünüyor. Yine de diğer yorumda da söylendiği gibi, RAII’nin sağladığı güvenlik de var; bu yüzden seçimin bir ölçüde trade-off olduğunu düşünüyorum.

 
cosine20 2024-11-28

İki taraf da haklı şeyler söylüyor.

Bir benzetme yapmak gerekirse, online oyun LoL'deki Azir karakteri için split push düzeni, takım savaşlarında alan kontrolü ve ultisinin değeri açısından ezici derecede iyi, yüksek seviye bir şampiyon olduğu yönünde bir algı var; ama bu ancak son derece yüksek ustalık gerektiren profesyonel maçlarda geçerli ve sıradan oyuncu seviyesinde koridor aşaması fazla zayıf, temel gücü de düşük olduğu için sadece en alt seviye bir şampiyon.

Asahi Lina gibi programlama ve işletim sistemi bilgisi üst %10'luk dilimin üzerinde olan kişilerin bakış açısından RAII dışındaki seçenekler elbette daha iyi olabilir, ancak kalan %90'ın uğraştığı alanlarda RAII ya da Rust kadar iyi bir şey olmadığını düşünüyorum.

Ancak bellek kararlılığı/güvenliğini garanti etmenin büyük nedenlerinden biri güvenlik sorunları olduğu için... trade-off'un kaçınılmaz olduğunu düşünüyorum.

 
joonhwan 2024-11-28

RAII olmadan, deneyimi görece daha az olan geliştiricilerin hatayı bolca üretir hâle geleceği gibi görünüyor

OS değil de uygulama programı seviyesinde en azından...