- Rust ile C performans karşılaştırması, “tüm koşullar aynı” öncülünün nasıl tanımlandığına bağlı olarak karmaşık bir meseledir
- Inline assembly durumunda iki dil de aynı assembly kodunu üretebildiğinden, dilin kendisinden kaynaklanan bir hız farkı yoktur
- Struct bellek yerleşimi açısından Rust, alanları yeniden sıralayarak daha küçük boyut elde edebilir; ancak
#[repr(C)] niteliğiyle C ile aynı yerleşim de mümkündür
- Çalışma zamanı kontrolleri ve geliştirici davranışları farkı nedeniyle gerçek projelerde kod yapısı ve performans değişebilir
- Sonuç olarak, dilin kendi sınırlarından doğan bir performans farkı yoktur; sonuçlar projeye ve geliştiriciye bağlı olarak değişir
Sorunun ortaya konuluşu ve varsayımın belirsizliği
- Reddit'te sorulan “Aynı koşullarda Rust, C'den daha hızlı olabilir mi?” sorusu çıkış noktasıdır
- “Tüm koşulların aynı olması” ifadesi, diller arasında karşılaştırma yaparken tanımlanması çok zor bir kavramdır
- Performans karşılaştırması yalnızca dil farkına değil, kodun biçimine, geliştirici kararlarına ve derleyici optimizasyonlarına da bağlıdır
Inline assembly karşılaştırması
- Rust, dil düzeyinde inline assembly desteği sunarken C bunu derleyici uzantıları üzerinden gerçekleştirir
- Her iki dilde de
rdtsc komutunu kullanan aynı örnek yazılabilir
rustc 1.87.0 ve clang 20.1.0 ile üretilen assembly çıktısı tamamen aynıdır
- Bu örnek, diller arasındaki performans farkını göstermese de, Rust'un C ile aynı düzeyde düşük seviye kontrol sağlayabildiğini kanıtlar
Struct yerleşimi farkı
- Rust struct'ları, alanları yeniden sıralayarak bellek kullanımını optimize edebilir
- Örnekte Rust struct'ı 16 bayt, aynı C struct'ı ise 24 bayt olarak hesaplanır
- C'de aynı boyutu elde etmek için alan sırasını elle değiştirmek gerekir
- Rust'ta
#[repr(C)] niteliği kullanılırsa C ile aynı bellek yerleşimi zorlanabilir
Sosyal ve geliştirici faktörleri
- Rust'un güvenlik kontrolleri sayesinde geliştiricinin daha agresif optimizasyonlar deneyebildiği durumlar vardır
- Mozilla'nın Stylo projesinde, C++ ile iki paralelleştirme girişimi başarısız olurken Rust ile başarılı bir uygulama ortaya konmuştur
- Aynı projede bile dil ve geliştirici uzmanlığına göre ortaya çıkan kodun performansı ve kararlılığı değişebilir
- Yeni başlayanlarla uzmanlar arasında, ayrıca dil hakimiyetine göre “aynı iş”in sonucu farklı olacağından, basit karşılaştırmalar yapmak zordur
Derleme zamanı ve çalışma zamanı kontrolleri
- Rust'taki birçok güvenlik kontrolü derleme zamanında yapılır, ancak bir kısmı çalışma zamanında kalır
- Örneğin
array[0] erişiminde Rust sınır kontrolü yaparken C yapmaz
- Rust'ta
get_unchecked() kullanılırsa C ile aynı davranış elde edilebilir
- Derleyici güvenliği kanıtlayabiliyorsa, iki dilde de kontroller optimizasyonla kaldırılabilir
- Bu farklar kod yazma biçimini etkiler ve sonuçta performans farkına yol açabilir
Sonuç
- C'nin “en hızlı dil” olduğu varsayılsa bile, Rust'un aynı düzeyde performans sergileyememesi için bir neden yoktur
- Performans farkını belirleyen şey dilin kendisinden çok projenin özellikleri, geliştirici yetkinliği, zaman kısıtları gibi dış değişkenlerdir
- Bu nedenle “Rust, C'den daha hızlı mı?” sorusu, dil karşılaştırmasından çok mühendislik bağlamı meselesi olarak yorumlanmalıdır
9 yorum
Hacker News görüşleri
Özetle, azami hız neredeyse aynı, ama gerçek kodda fark büyük
Özellikle çok iş parçacıklılığı büyük bir değişken. Rust'ta iş parçacığı kullansanız da kullanmasanız da tüm global değişkenlerin thread-safe olması gerekir ve borrow checker bellek erişimini ya paylaşım ya da değişiklik ile sınırlar
Bu yüzden Rust'ta çok iş parçacıklı kod yazmak neredeyse varsayılan gibidir. Buna karşılık C'de iş parçacığı oluşturmanın kendisi, platform uyumluluğu sorunları ya da debug riskleri nedeniyle külfetlidir
C'de thread oluşturmak zor değil ama Rust'taki
std::thread::spawn(move || { ... });kadar rahat değilBellek güvenliğinden çok, dilin eşzamanlılık modeli daha büyük etki yapıyor. Go bellek güvenli olmasa da
go f()ile kolayca paralelleştiriyorKendi deneyimimde Go'da heisenbug ile daha sık karşılaştım
#pragma omp forsatırıyla kolayca paralelleştirme yapılabilirRust'ın trait sistemi sayesinde daha hızlı ve daha esnek soyutlamalar kurulabiliyor
C'de bunu makrolar veya function pointer'larla taklit edebilirsiniz, ama Rust'ta çağıran taraf dinamik dispatch ya da statik dispatch arasında seçim yapabilir
Gömülü ortamlarda function pointer'lar cache'i bozup performansı düşürürken, Rust trait'leri inline optimizasyonuna izin verdiği için çok daha verimlidir
Rust da C de sonuçta byte düzeyinde çalışıyor ve bugünlerde binary patching araçları da geliştiği için kullanımı kolaylaştı
Box<dyn Trait>kullanırsanız çağıran taraf dinamik dispatch'e zorlanırimpl Traitkullanırsanız seçim hakkı çağıran tarafta kalırBana göre Rust, C ve C++ neredeyse aynı düşük seviyeli dil ailesine ait, bu yüzden performans farkı çok küçük
Rust'ın katı aliasing kuralları optimizasyon için avantajlı, C/C++ tarafındaki UB (tanımsız davranış) ise performans uğruna var
Ayrıca Rust ve C++'taki generic yapılar C'ye göre çok daha güçlü; örneğin
qsort()yerine template tabanlı sıralama inline optimizasyona çok daha uygundurDiller arası bu tür hız tartışmalarının çoğunun anlamsız olduğunu düşünüyorum
Performansı belirleyen şey dilden çok derleyici implementasyonu
Rust, C ve C++ hepsi düşük seviyeli diller, ama “hızlı” derken neyin kastedildiği önemli
Uzmanın optimize ettiği kodun azami hızından mı söz ediyoruz, yoksa ortalama bir geliştiricinin bütçe içinde hızlı kod yazma olasılığından mı? Bunlar farklı şeyler
Ama elle optimize edildiğinde diller arasındaki fark neredeyse kaybolur
Yine de Rust'ın hızlı kod yazmayı daha kolaylaştıran bir dil olması bakımından küçük bir avantajı var
Rust'ın avantajının çok iş parçacıklılığı ve stack allocation olduğunu düşünüyordum
Sahiplik modeli sayesinde C/C++'a kıyasla daha fazla şeyi stack üzerine koyabiliyor, böylece malloc/free overhead azalıyor
Bu tür konular duygusal tartışmalara çok açık olduğu için, somut sayılardan ziyade düşünme biçimi farklarını ele almak istedim
Bir dilin “hızı” konuşulurken iki şeye bakmak gerekir
Rust ve C'de runtime check neredeyse olmadığı için Python veya JS'den hızlılar
Ama Rust, aliasing bilgisini daha iyi aktardığı için daha fazla optimizasyon alanı sunabiliyor
Debug modunda Ruby kadar yavaş olabilir, ama release modunda C seviyesinde hız verir
C'ye kıyasla C++ ve Rust'ın compile-time özellikleri daha zengin olduğu için hızlı kod yazmak daha kolay
Örneğin bu kod C'de neredeyse imkânsız
C'de bunun için re2c gibi harici araçlar gerekir
Assembly, C standardının bir parçası olmadığı için Rust ile doğrudan karşılaştırmak zor; Rust'ın doğası aslında GCC projesine daha yakın
Bir dilin “hızlı” olup olmaması sonuçta uygulamaya ve bağlama göre değişir
Dilin kendi hızından çok, derleyici ve donanım kombinasyonu daha büyük etki yaratır
Ortalama olarak hangi dilin en hızlı olduğunu bilmiyorum ama dağılımın en büyük olduğu dil muhtemelen C++ olacaktır.
Gömülü sistemlerde kod yazarken donanımın cache line boyutuna kadar hesaba katıyoruz. Mesele, programcının dil seviyesinde uç optimizasyonu ne kadar ileri götürebildiği ile standart kütüphane ve derleyici performansı gibi görünüyor; sonuçta ikisi de düşük seviyeyi desteklediği için küçük overhead farklarının ihmal edilebilir düzeyde olacağını düşünüyorum. Bu yüzden çok anlamlı bir tartışma değil gibi.. Uç optimizasyon gerekiyorsa eninde sonunda insan müdahalesi gerekiyor. Çünkü derleyici sanıldığı kadar kusursuz değil.
Bence Rust, C'den çok C++'ın yerine geçecek bir aday. C, derleyicinin üreteceği kodu tahmin edebildiğiniz fiilen tek (belki de son) dil…
Zig de fena değil... :(
Yazarken fark ettim, yapay zeka özeti gibi olmuş TT
Bunu bilerek yapmadınız mı, hehe
Bu, derleyicinin yeteneğine bağlı.
Aynı kodu assembly'e çevirip bakarsanız ortaya çıkar.
Görünüşe göre ffmpeg tayfa, Rust'ın C'den daha hızlı olduğunu düşünmüyor gibi haha https://www.memorysafety.org/blog/rav1d-perf-bounty/