OutOfMemoryException (OOM)

Daha önceki bir yazımda .NET ortamındaki uygulamaların hafıza kullanım limitlerinden bahsetmiştim. Gün geçtikçe daha çok uygulama 64bit ortamda koşmaya başlıyor, ve bu da yazılımcılara belirli bir rahatlık sağlıyor. Ancak bu rahatlık, bazen istenmeyen sonuçlara neden olabiliyor.

Son birkaç ay içerisinde çok sayıda OutOfMemoryException problemi üzerinde çalıştım. Bunlardan çoğu da 64bit sunucu üzerinde 64bit ASP.NET uygulamalarıydı. Böyle bir ortamda aslında OOM almak çok kolay değildir. 64bit bir .NET uygulaması, 64bit sunucuda hafıza kullanımında oldukça yüksek rakamlara çıkabilir:

Limit = ( RAM + Page File Ebatı ) * 60%

Örneğin 8 GB RAM''e sahip bir sunucuda, page file ebatı da 12 GB ise:

Limit = ( 8 + 12 ) 60% = 12 GB

Bu kolay ulaşabileceğimiz bir rakam değildir - gerçi ben 35 GB'a ulaşan "worker process"le karşılaştım ama bu kesinlikle istisnaydı.

Bahsettiğimiz limitlere ulaşmadan çok önce OOM alınan senaryolarla karşilaştım son dönemde çokça. Bunların nedeni ise, ebatı 2GB olan nesneler olarak karşımıza çıktı. Bu çok fazla bilinmez, çünkü zaten 32bit ortamlarda bu limite ulaşmak imkansızdır, ancak bir .NET uygulaması içerisinde yaratılabilecek nesneler 2GB'tan büyük olamazlar. Eğer bir nedenle uygulamanız içerisinde bu ebatta bir nesne yaratılmaya kalkışılırsa, bunun sonucu da OOM olmaktadır - hafıza kullanım limitlerinden çok uzak olsak da.

Limitlere ulaşmadan OOM almanın bir diğer nedeni de, sunucu hafıza'sının "fragmante" olması olabilir. Örneğin, oldukça büyük, belki birkaç yüz MB kadar, bir nesne yaratmak istediniz. GC, hafızadan bu ebatta tek parça bir alan almak ister. Eğer hafızamız çok fazla fragmante olmuşsa bu ebatta bir alan bulamayabilir, ve toplam boş alanımız bundan çok daha fazla olsa da OOM alabiliriz.

Sonuç olarak, ortamımız ve uygulamamız 64bit olsa dahi, uygulamamızı geliştirirken hafıza kullanımına dikkat etmemiz gerekir. Uygulamamız OOM almasa bile, hafıza kullanımı .NET uygulamalarında performansa direkt etki eder.

CENK İŞCAN