- Unity'nin kullandığı Mono runtime'ı, modern .NET'e kıyasla belirgin biçimde daha yavaş yürütme performansı gösteriyor; aynı C# kodunda 15 kata kadar fark görülebiliyor
- Gerçek oyun kodunda Mono tabanlı Unity çalıştırması 100 saniye, aynı kodun .NET üzerinde çalıştırılması ise 38 saniye olarak ölçüldü; bu da hata ayıklama ve test verimliliğini ciddi biçimde etkiliyor
- Release modunda da Mono 30 saniye, .NET 12 saniye ile, optimize edilmiş ortamda bile 2,5 katın üzerinde performans farkı korunuyor
- Bunun nedeni Mono'nun verimsiz JIT derlemesi ve inlining başarısızlığı, aşırı bellek kopyalama gibi sorunları; bu durum .NET'in modern CoreCLR JIT optimizasyonları ile tezat oluşturuyor
- Unity, CoreCLR tabanlı .NET modernizasyonunu tamamladığında hem oyunlarda hem editörde büyük performans artışı mümkün olabilir; bu da tüm Unity projelerindeki gizli performans vergisinin ortadan kalkması anlamına gelebilir
Unity'nin Mono kullanmasının arka planı
- Unity, 2006'dan beri C# kodunu çalıştırmak için Mono framework'ünü kullanıyor
- O dönemde Mono, tek çok platformlu .NET implementasyonuydu ve açık kaynak olduğu için Unity tarafından değiştirilebiliyordu
- 2014'ten sonra Microsoft, .NET Core'u açık kaynak yaptı ve 2016'da .NET Core 1.0'ı yayımladı
- Sonrasında Roslyn derleyicisi, yeni JIT, performans iyileştirmeleri gibi alanlarda .NET ekosistemi hızla gelişti
- 2018'de Unity mühendisleri, CoreCLR portlama çalışması yürüttüklerini açıkladı ve Mono'ya kıyasla 2 ila 10 kat performans artışı beklediklerini belirtti
- Ancak 2025 sonu itibarıyla hâlâ CoreCLR tabanlı oyun çalıştırma mümkün değil
Mono ile .NET arasındaki performans farkı
- Unity projesindeki simülasyon kodu, Unity dışında .NET ile çalıştırılarak doğrudan karşılaştırıldı
- Unity/Mono ortamı: 100 saniye, .NET ortamı: 38 saniye (Debug modu ölçümü)
- Release modunda da fark korunuyor: Mono 30 saniye, .NET 12 saniye
- .NET, 4K×4K haritayı 3 saniyenin altında üretmek gibi çok iş parçacıklı optimizasyonlarda öne çıkıyor
- Ana nedenlerden biri Mono'nun verimsiz kod üretimi; basit döngülerde bile 15 kat hız farkı oluşabiliyor
Assembly karşılaştırması: Mono vs .NET
- Aynı test koduyla üretilen x64 assembly karşılaştırmasında
- .NET JIT, döngü değişmezlerini döngü dışına taşıyor (hoisting) ve yalnızca gerekli register işlemlerini yapıyor
- Mono ise onlarca
mov komutuyla bellek kopyalamayı tekrar ediyor; verimsiz inlining nedeniyle performans düşüyor
int.MaxValue tekrarlı döngüsünün çalışma süresi
- .NET: 750ms, Mono: 11.500ms, Unity Editor(Debug): 67.000ms
- Mono, döngü içinde gereksiz bellek taşıma ve karşılaştırma işlemlerini tekrar tekrar yürütüyor
CoreCLR kullanımının anlamı
- CoreCLR, modern JIT, Span<T> API, SIMD optimizasyonu, donanım komutu desteği gibi çağdaş özellikler sunuyor
- Bu özellikler ek olarak 2 katın üzerinde performans artışı potansiyeli taşıyor
- Unity'nin Burst derleyicisi, LLVM tabanlı olarak native kod üretiyor ancak C# özellikleri konusunda kısıtlamalara sahip
- CoreCLR'nin modern JIT'i, Burst'e benzer performans sunarken dil kısıtları daha az olabilir
- CoreCLR, AOT (ön derleme) desteğiyle başlangıç hızını iyileştirme ve JIT'in kısıtlı olduğu platformları (ör. iOS) destekleme imkânı sağlıyor
- Ancak Unity, hâlâ IL2CPP'yi sürdürme politikasını koruyor
Sonuç: Unity'nin .NET modernizasyonuna ihtiyacı var
- Mono, modern .NET'e kıyasla 1,5 ila 3 kat veya daha fazla daha yavaş çalışma performansı gösteriyor; bu da tüm Unity projeleri için gizli bir maliyet oluşturuyor
- CoreCLR kullanımında beklenen etkiler
- Runtime performansında artış, daha hızlı yinelemeli build'ler, GC iyileştirmeleri, domain reload'un kaldırılması, managed code oranının artması
- Unity 6.x yol haritasında .NET Modernization yer alıyor, ancak bunun 2026 sonrası için planlandığı belirtiliyor
- CoreCLR desteği tamamlandığında hem Unity geliştiricileri hem oyuncular için gerçek bir performans dönüşümü sağlanabilir
- Şu an için Mono'nun sınırları, Unity ekosisteminin tamamında bir performans darboğazı olmaya devam ediyor
13 yorum
Ah... Görünüşe göre Mono hâlâ legacy .NET Framework tabanlı...
Oyun değil ama, yaklaşık 100 bin satırlık .NET4.8 + LINQ to SQL + WinForm finans uygulamasını .NET10 + Entity Framework'e taşıyorum ve çok daha hızlandığını hissedebiliyorum. Hatta 10 saniye süren hesaplama işleri 3 saniyeye kadar düştü!
NuGet uyumluluğu da eklenirse güzel olurdu (Unity'yi pek bilmediğim için mi böyle düşünüyorum acaba?)
Resmi olarak desteklenmiyor ama...
NuGetForUnitydiye bir açık kaynak proje var.Teoride,
.NET Standard 2.0hedeflenerek hazırlanmış NuGet paketleri Unity ortamında da içe aktarılıp kullanılabiliyor... ama yine de epey kullanışsız yanları var gibi görünüyor.https://learn.microsoft.com/ko-kr/dotnet/…
Doğru bir nokta ama editör performansını neden özellikle karşılaştırdıklarını pek anlayamadım... Hiç değilse bir debug build getirip onunla karşılaştırsalardı? Yoksa o zaman ikna gücü daha da mı düşerdi? Öte yandan, IL2CPP de Mono da artık devri geçmiş teknolojiler gibi duruyor.
Büyük projelerde editör performansı da anlamlıdır; çünkü geliştirme deneyimini ciddi biçimde aşağı çeker. Editörün açılması yavaş, asset import işlemi yavaş, debugging/test döngüsü de yavaş...
Ah... evet, bu da elbette önemli. Ben ilk okuduğumda, yazının yazarı daha çok kod yürütme hızının temel meselelerini tartışmak istiyor gibi görünmüştü. Dediğiniz gibi Unity'nin editörü de yavaş, import da yavaş ve genel olarak test döngüsü de yavaş; bu da gerçekten doğru...
Unity ile ilgili bir yazı görmek beni çok mutlu etti.
Keyifle okudum.
Başarıyla uygulanırsa, her yerde görülen indie oyun optimizasyonlarının muhtemelen iyileşmesi bekleniyor...
Mono’nun mutlaka CoreCLR ile modernize edilmesi için bir başka nedenin de, Unity’nin Mono’nun performansını iyileştirmeye yatırım yapacak ne imkâna ne de isteğe pek sahip olmayacağı olduğunu düşünüyorum. .NET Framework döneminden kalan mirasın bir an önce tasfiye edilmesi gerektiğini düşünüyorum. :-D
Ayrıca .NET 10 itibarıyla, geçmişte IL2CPP ile çözmek istedikleri sorunun farklı bir yönde gelişse de tam olarak ele alınıyor olması (
Native AOT) da değerlendirilse iyi olur diye düşünüyorum.Elbette burada, arada düzenlenebilir C++ kodu üretilmemesi bir sınırlama; ancak sonuç olarak Just-In-Time oluşmayan yerel ikili üretimi, .NET 8 ile başlayıp .NET 10'a gelindiğinde daha da olgunlaştı.
Bu nedenle CoreCLR ile modernleşmeyi sürekli ertelemenin Unity için iyi bir tercih olmayacağını düşünüyorum. Ya da tamamen farklı bir dile veya altyapıya geçmek daha geçerli bir seçenek de olabilir!
> Unity'nin Mono'nun performansını iyileştirmeye yatırım yapacak ne koşulları ne de isteği yüksek olur.
Buna da son derece katılıyorum...
Hacker News yorumları
Yazıda, Unity geliştirme deneyimi az olan biri tarafından yazılmış gibi duran birkaç kısım vardı
Özetle, Unity geliştiricilerinin bu güncellemeyi heyecanla beklemesinin nedeni performans artışından çok modern dil özelliklerine erişimdir. Ayrıca runtime sırasında GC'yi en aza indirmek ya da unmanaged memory ve DOTS ile bunu aşmak yaygındır
IL2CPP, .NET IL'yi C++'a dönüştüren düşük kaliteli bir kod üreticisinden ibaret ve optimizasyon için derleyiciye bağımlı
Bunu Unity blogundaki IL2CPP iç yapısı yazısından görebilirsiniz
Burst/HPC# de ECS ya da SoA gibi trendleri takip ediyor, ancak performansı iyi yazılmış C++ ya da CoreCLR C#'ın gerisinde kalıyor
Üstelik bu teknolojiler kapalı ve Unity'ye özel, dışarıda kullanılamıyor. Unity pazarlamasını her zaman yavaş Mono ile karşılaştırmalı benchmark'lar üzerinden yapıyor
Sonunda Unity de CoreCLR'ı kabul etmek zorunda kaldı ve o zaman mevcut karmaşık kod yerine sıradan C# kodunun daha hızlı olduğu gerçeğiyle yüzleşecek
IL2CPP kullanmama nedenimiz, runtime DLL yükleme, reflection, FieldOffset struct packing gibi şeylerle uyumlu olmaması
Mod geliştiricileri IL injection ile özellikleri genişletebildiği için sonuçta geliştirme hızı artıyor
Burst ve HPC#'ı, karmaşıklıkları ve kısıtları nedeniyle tercih etmiyoruz. Mono ile .NET arasındaki performans farkı yüzünden bu daha da can sıkıcı
Editör profiling'i de gerçek build'e benzer oranlarda performans iyileştirmesi gösterdiği için faydalıydı. Bunun yerine Unity'nin varsayılan profiler'ı doğru olmadığı için kendimizin yaptığı izleme sistemini kullanıyoruz
GC hâlâ bir sorun. String işleme ya da UI her frame'de garbage üretiyor. CoreCLR'a geçildiğinde daha iyi API'ler ve moving GC sayesinde memory fragmentation sorunları azaltılabilir
Asset Store harika, ancak motorun kendisi yeterince rafine edilmemiş gibi hissettiriyor.
Mono tabanlı scripting'i CoreCLR'a taşımak yapısal olarak karmaşık
Unity'nin Core tarafını gerçekten iyileştirmesi için Blender 3.x'teki gibi editörün tamamını yeniden tasarlaması gerekir.
Şu an 1999'dan kalma bir UI gibi hissettiriyor
Sayısız eklenti ve araç “0.x-preview” aşamasında kalıyor, 5-10 yıl sonra ya çalışmıyor ya da yeni varlıkların altında kayboluyor
Bu yüzden artık yalnızca 1.0 ve üstü sürümleri kullanıyorum. Aksi hâlde terk edilmiş bir eklentiye bağımlı kalıp sonunda her şeyi yeniden port etmek zorunda kalıyorsunuz
Unity de, geliştirici de, kullanıcı da bundan zarar görüyor
İçeride kendi oyun geliştirme başarısızlıkları nedeniyle gerçek oyun üretimi hissiyatından yoksun
Sadece istenen özellikleri ekliyorlar, ama tutarlı bir vizyonları yok
Performans önemliyse Vulkan'ı doğrudan çağırmak daha iyi, taşınabilirlik önemliyse WebGPU kullanılmalı
Tarayıcıya göre uygulama farklı olduğu için ek yük oluşuyor, ama OS sürücüsü seviyesinde WebGPU sunulursa bu çözülebilir
Buna karşılık Godot, istediğinizi özgürce kurabilmeniz için basit ve anlamlı yapı taşları sunuyor
Asset Store da aynı şekilde sürüm uyumluluğu sorunları nedeniyle bakımı zor, çoğu da terk edilmiş asset hâline geliyor
Unity kullanışlı asset'leri satın aldığında bile düzgün entegre etmiyor, rakip asset'ler ise ortadan kayboluyor
Buna karşılık Unreal Engine bu tür özellikleri motorun içine gömülü düzeyde sunuyor
Unity'nin IL2CPP'ye daha iyi bir GC getirme planı da yok
CoreCLR tabanlı editör geldiğinde hatta editör build'den daha hızlı bile olabilir
İlgili tartışma: Unity CoreCLR ve .NET modernizasyonu
Incremental GC iyi çalışırsa stutter sorunu da o kadar büyük olmaz
C# artık varsayılan olarak çok daha hızlı olduğu için Unity'nin bu geçişe tüm gücüyle odaklanması gerekiyor
Ekibimiz .NET Framework 4.7.2'den .NET 6'ya geçmek için birkaç ay harcadı, sonrasındaki LTS yükseltmeleri ise birkaç saatlik iş kadar kolaydı
Sürekli erteleniyor ve liderler ayrılıyor
Alternatif olarak .NET 10 tabanlı Stride engine öneriliyor. Unity'deki gibi boundary overhead yok
Godot açık kaynaklı ama C# desteği kararsız ve Web build yoksa game jam için uygun değil
GPU desteği olan gerçek bir sandbox çözümüne ihtiyaç var
Öncelikler sürekli değişiyor, gereksinimler revize ediliyor ve iş tekrar tekrar yapılıyor
Geliştiriciler hâlâ çok iyi, ama istikrarlı bir yürütme gücü eksik
Bu tür büyük çaplı rewrite'lar, CEO açısından da yüksek riskli kararlar
Sonuçta performans ciddi biçimde arttı ve motor bağımlılığının azalması sayesinde kodun bakımı da kolaylaştı
Unity kavramlarını sadece gerekli yerlere açığa çıkarıp, testlerle sınırları zorunlu kılarak mantıksal ayrımın değerini bizzat gördüm
Root erişimi mümkünse ve WireGuard ya da Tailscale gibi ağ araçlarıyla birleştirilirse taşınabilir bir sunucu olarak da mükemmel olur
.NET 10'daki yeni GC ile oyun stutter'ı da neredeyse tamamen ortadan kalkacaktır
Şu anda ana PC'mden Sunlight + Moonlight ile oyunu stream edip telefonda oynuyorum.
Yüksek yenileme hızlı OLED ekran sayesinde pil tüketimi de düşük
.NET SDK değil ama Mono runtime uygulamanın içine gömülü olduğu için hissiyat olarak benzer
Mono'nun çapraz platform avantajı zaten ortadan kalkmışken, neden IL2CPP gibi karmaşık hack'leri sürdürdüklerini anlamıyorum
Yıllar içinde biriken standart dışı değişiklikler yüzünden, büyük bir şirket değilseniz bunu yeniden optimize etmek de zor
Böyle bir proje için 1-2 yıl yeterli olurdu diye düşünüyorum