Bölge tabanlı bellek yönetimi

**Bölge tabanlı bellek yönetimi**, bilgisayar biliminde, tahsis edilen her nesnenin belirli bir bölgeye (bölüm, alt havuz, zona, arena, alan veya bellek bağlamı olarak da adlandırılır) atandığı bir bellek yönetim türüdür. Bir *bölge*, topluca verimli bir şekilde yeniden tahsis edilebilen veya serbest bırakılabilen, önceden ayrılmış nesnelerden oluşan bir koleksiyondur.

Bölge tabanlı yönetim kullanan bellek ayırıcıları genellikle *alan ayırıcıları* (region allocators) olarak adlandırılır. Eğer bu ayırıcılar yalnızca tek bir işaretçinin artırılmasıyla çalışıyorsa, bu durumda *artırıcı ayırıcılar* (bump allocators) olarak tanımlanırlar.

Yığın (stack) tahsisine benzer şekilde, bölge tabanlı yönetim de düşük işletim yüküyle bellek tahsisi ve serbest bırakma işlemlerini mümkün kılar. Ancak bölgeler, daha fazla esneklik sunarak nesnelerin tahsis edildikleri yığın çerçevesinden daha uzun süre yaşamalarına olanak tanır. Tipik bir uygulamada, bir bölgedeki tüm nesneler genellikle tek bir bitişik bellek adresi aralığında tahsis edilir.

Özellikle  ve onu takip eden sistemlerde, bölge tabanlı bellek yönetimi iki düzeyde uygulanır. Her işlem, bitişik bir bölüm veya bölge içinde yürütülür. Bellek tahsis talepleri bir *alt havuz* (subpool) üzerinden gerçekleştirilir ve tüm bir alt havuz topluca serbest bırakılabilir. Alt havuzlar için bellek, genellikle bitişik olmayan ancak 2 KiB veya 4 KiB’nin katları şeklindeki bloklar hâlinde ayrılır.

## Örnek
Basit bir örnek olarak, bir bağlı liste veri yapısını tahsis eden ve ardından tahsisatını kaldıran aşağıdaki C koduna göz atabilirsiniz:
```c
Bolge *b = bolgeOlustur();  // Bölge oluştur
ListeDugum *bas = NULL;
for (int i = 1; i <= 1000; i++) {
    ListeDugum* yeniDugum = bolgedenAlanAl(b, sizeof(ListeDugum));
    yeniDugum->sonraki = bas;
    bas = yeniDugum;
}
// ...
// (burada listeyi kullan)
// ...
bolgeYokEt(b);  // Bölgeyi yok et
```
Bağlı liste oluşturmak için birçok işlem gerekse de, düğümlerin tahsis edildiği bölgeyi yok ederek tek bir işlemle hızlıca tahsisi kaldırılabilir. Listeyi taramaya gerek yoktur.

## Uygulama
Basit açık bölgeler uygulaması kolaydır; aşağıdaki açıklama Hanson’ın çalışmasına dayanmaktadır. Her bölge, büyük bellek bloklarından oluşan bir bağlı liste olarak uygulanır; her blok, çok sayıda tahsise hizmet verebilecek kadar büyük olmalıdır. Mevcut blok, bloktaki bir sonraki serbest konuma işaret eden bir işaretçi tutar ve blok dolduğunda yeni bir blok tahsis edilerek listeye eklenir. Bölge serbest bırakıldığında, bir sonraki serbest konum işaretçisi ilk bloğun başına sıfırlanır ve blok listesi, bir sonraki tahsis edilen bölge için yeniden kullanılabilir. Alternatif olarak, bir bölge serbest bırakıldığında, blok listesi, diğer bölgelerin daha sonra yeni bloklar tahsis edebileceği küresel bir serbest listeye eklenebilir. Bu basit şemanın her iki durumunda da, bölgelerdeki tek tek nesneleri serbest bırakmak mümkün değildir.

Bu şemanın tahsis edilen bayt başına toplam maliyeti çok düşüktür; neredeyse tüm tahsisler yalnızca bir karşılaştırma ve bir sonraki serbest konum işaretçisinin güncellenmesini içerir. Bir bölgenin serbest bırakılması sabit zamanlı bir işlemdir ve nadiren yapılır. Tipik çöp toplama sistemlerinden farklı olarak, verilerin türüyle etiketlenmesine gerek yoktur.

## Tarih ve kavramlar
Bölgelerin temel kavramı çok eskidir ve ilk olarak 1967 yılında Douglas T. Ross’un AED Serbest Depolama Paketi’nde ortaya çıkmıştır; bu pakette bellek, her biri kendi tahsis edicisine sahip olan ve bir kerede tamamen serbest bırakılabilen, bölgeler olarak kullanılabilen bir bölgeler hiyerarşisine bölünmüştü. 1976 yılında  standardı ALAN veri türünü içermiştir. 1990 yılında Hanson, C dilinde açık bölgelerin (ki bunlara arena adını vermiştir) tahsis edilen bayt başına zaman performansında, bilinen en hızlı yığıt tahsis mekanizmasından bile üstün olabileceğini göstermiştir. Açık bölgeler, Apache HTTP Sunucusu (bunlara havuzlar adını verir) ve PostgreSQL veritabanı yönetim sistemi (bunlara bellek bağlamları adını verir) gibi bazı erken C tabanlı yazılım projelerinin tasarımında önemli bir rol oynamıştır. Geleneksel yığıt tahsisine benzer şekilde, bu şemalar bellek güvenliği sağlamaz; bir programcının, serbest bırakılmış bir bölgeye sarkan işaretçi yoluyla erişmesi veya bir bölgeyi serbest bırakmayı unutması, bellek sızıntısına neden olabilir.

## Bölge çıkarımları
1988 yılında, araştırmacılar güvenli bellek tahsisi sağlamak amacıyla bölgelerin kullanımına ilişkin yöntemleri araştırmaya başlayarak *bölge çıkarımı* (region inference) kavramını ortaya koymuşlardır. Bu yöntem, bölgelerin oluşturulması ve serbest bırakılması işlemleri ile statik bellek tahsis ifadelerinin belirli bölgelere atanmasının derleme zamanında derleyici tarafından otomatik olarak gerçekleştirilmesini içerir. Derleyici, bu işlemleri *sarkan işaretçiler* (dangling pointers) veya *bellek sızıntıları* (memory leaks) oluşmayacak şekilde garanti altına alacak biçimde yürütür.

Bu alandaki erken çalışmalardan biri Ruggieri ve Murtagh tarafından gerçekleştirilmiştir. Bu çalışmada, her fonksiyonun başında bir bölge oluşturulmakta ve fonksiyonun sonunda bu bölge serbest bırakılmaktadır. Her bir statik tahsis ifadesi için ömür (lifetime) analizini belirlemek amacıyla *veri akış analizi* (data-flow analysis) kullanılmış; ardından, bu ifadeler ömürlerini kapsayan en kısa ömürlü bölgeye atanmıştır.

1994 yılında, bu yaklaşım Tofte ve Talpin tarafından önemli ölçüde genişletilmiştir. Çalışmaları, *tip çıkarımı* (type inference), *polimorfik bölge tipleri* ve *bölge hesabı* (region calculus) gibi kavramlara dayanan alternatif bir algoritmayı temel alarak, işlevsel bir programlama dili olan *Standard ML*’de *tip polimorfizmi* ve *yüksek dereceli fonksiyonlar* (higher-order functions) ile birlikte kullanılabilecek şekilde genelleştirilmiştir. Bu öncü çalışmada, bölgeleri içeren *lambda hesabı* (lambda calculus) uzantısına dayalı bir sistem tanıtılmış ve iki temel yapı eklenmiştir:ρ'de e1: e1 ifadesinin sonucunu hesaplayın ve ρ bölgesinde saklayın; e2 end içinde ρ bölgesine izin ver: Bir bölge oluşturun ve ρ'ye bağlayın; e2'yi değerlendirin; ardından bölgeyi ayırın.Bu sözdizimsel yapı nedeniyle bölgeler *iç* içe geçmiştir, yani r 2, r 1'den sonra oluşturulursa, r 1'den önce de ayrılması gerekir; Sonuç bir bölge *yığınıdır*. Dahası, bölgeler oluşturuldukları aynı işlev içinde ayrılmalıdır. Bu kısıtlamalar Aiken ve diğerleri tarafından gevşetilmiştir.

Bu genişletilmiş lambda hesaplaması, Standard ML programlarını makine koduna derlemek için kanıtlanabilir şekilde bellek güvenliğine sahip bir ara gösterim olarak hizmet vermesi amacıyla tasarlanmıştır. Ancak, büyük programlarda iyi sonuçlar üretecek bir çevirici (translator) geliştirmek, özyineli (recursive) çağrılar, kuyruk çağrıları (tail calls) ile yalnızca tek bir değer içeren bölgelerin ortadan kaldırılması gibi çeşitli pratik sınırlamaları çözmeyi gerektiren yeni analizlerin uygulanmasını zorunlu kılmıştır.. Bu çalışma 1995 yılında tamamlandı  ve ml'nin çöp toplama yerine bölge tahsisine dayalı bir versiyonu olan ML Kitine entegre edildi. Bu, orta ölçekli test programlarında ikisi arasında doğrudan bir karşılaştırmaya izin vererek, programın ne kadar "bölge dostu" olduğuna bağlı olarak çok çeşitli sonuçlar verdi ("10 kat daha hızlı ve dört kat daha yavaş"); Ancak derleme süreleri dakika sırasına göre idi. ML Kiti sonunda iki eklemeyle büyük uygulamalara ölçeklendirildi: modüllerin ayrı derlenmesi için bir şema ve bölge çıkarımını çöp toplama izlemeyle birleştiren hibrit bir teknik.

## Yeni dil ortamlarına genelleştirme
ML Kit'in geliştirilmesini takiben, bölgeler diğer dil ortamlarına da genellenmeye başlanmıştır.

* C programlama dilinin çeşitli uzantıları:
** Pek çok özelliğinin yanı sıra açık bellek bölgeleri (explicit regions) desteği de sunan güvenli C diyalekti Cyclone, mevcut C uygulamalarının bu sisteme geçirilmesinin etkilerini değerlendirmektedir.
** RC adlı, C diline getirilen bir uzantı  , açıkça yönetilen bellek bölgelerini kullanmakta; ancak, hiçbir bölgenin erken serbest bırakılmadığından emin olmak amacıyla bu bölgeler üzerinde başvuru sayımı (reference counting) da uygulayarak bellek güvenliğini garanti altına almaktadır. Bölgeler, iç referansların değiştirilmesi durumunda başvuru sayaçlarının güncellenmesini gerektirmediğinden, başvuru sayımının getirdiği ek yükü azaltır. RC, bazı başvuru sayımı güncellemelerinin ortadan kaldırılmasına olanak tanıyan, bölgelere yönelik açık bir statik tür sistemi de içermektedir.
** C dilinin bir kısıtlaması olan Control-C ise, programların sadece bellek bölgelerini (ve aynı anda yalnızca tek bir bölgeyi) kullanmasına izin vererek, bellek güvenliğini statik olarak sağlamayı amaçlayan bir tasarıma sahiptir.
* Bölgeler, Java'nın bir alt kümesi için uygulandı, ve Gerçek zamanlı Java'da bellek yönetiminin kritik bir bileşeni haline geldi; bu, nesne kapsüllemesini göstermek ve bölge tahsisinde çalışma zamanı kontrollerini ortadan kaldırmak için bunları sahiplik türleriyle birleştirdi. Daha yakın zamanlarda, gömülü gerçek zamanlı Java uygulamalarındaki bölgeleri çıkarmak için derleme zamanı statik analizini, çalışma zamanı bölgesi ayırma ilkesini ve programcı ipuçlarını birleştiren yarı otomatik bir sistem önerildi. Bölgeler, zaman yüklerinin statik olarak öngörülebilir olması nedeniyle gerçek zamanlı bilgi işlem için uygundur ve artımlı bellek toplayıcılarının karmaşıklığına gerek kalmaz.gerek kalmaz.
* Java 21, bellek alanlarını ayırmak ve serbest bırakmak için bir Java API'si ekledi. Bu API'nin belirtilen amacı, yerel kütüphanelerle güvenli entegrasyonu iyileştirerek JVM bellek sızıntılarını önlemek ve yerel kodun JVM bellek bozulması riskini azaltmaktır.
* Prolog  ve Mercury gibi mantık programlama dilleri için, Tofte ve Talpin'in bölge çıkarım modelini geri izleme ve kesmeleri destekleyecek şekilde genişleterek uygulanmışlardır.
* Bölge tabanlı depolama yönetimi, paralel programlama dili ParaSail  boyunca kullanılır. ParaSail'de açık işaretçiler bulunmadığından, referans sayımına gerek yoktur.

## Dezavantajlar (Eksiklikler)
Bölgeleri kullanan sistemler, bölgeler serbest bırakılmadan önce çok büyüdüğünde ve büyük oranda ölü veri içerdiğinde sorunlarla karşılaşabilir; bunlar genellikle "sızıntı" olarak adlandırılır (her ne kadar sonunda serbest bırakılsalar da). Sızıntıları ortadan kaldırmak, genellikle yeni ve daha kısa ömürlü bölgeler oluşturarak programı yeniden yapılandırmayı gerektirebilir. Bu tür sorunların hata ayıklaması, özellikle bölge çıkarımı kullanan sistemlerde zordur; çünkü programcı, temel çıkarım algoritmasını anlamalı veya sorunu teşhis etmek için ayrıntılı ara temsili incelemelidir. İzleme tabanlı çöp toplayıcılar, bu tür verileri program değişikliği gerektirmeden daha zamanında serbest bırakmada daha etkilidir; bu, hibrit bölge/çöp toplama sistemlerinin bir gerekçesiydi. Öte yandan, izleme tabanlı bellek toplayıcılar da, bir daha asla kullanılmayacak verilere referanslar tutulduğunda ince sızıntılar gösterebilir.

Bölge tabanlı bellek yönetimi, bölge sayısı nispeten az olduğunda ve her bölge çok sayıda nesne içerdiğinde en iyi şekilde çalışır; çok sayıda seyrek bölge içeren programlar, iç parçalanmaya yol açarak bellek israfına ve bölge yönetimi için zaman yüküne neden olur. Yine, bölge çıkarımı varlığında bu sorunun teşhisi daha zor olabilir.

## Hibrit yöntemler
Yukarıda belirtildiği üzere, RC (Referans Sayımı), bölgeler ve referans sayımının bir hibritini kullanır; bu, bölgeler içindeki referanslar değiştirildiğinde sayımların güncellenmesini gerektirmediği için referans sayımının yükünü sınırlar. Benzer şekilde, bazı işaret-bölge hibrit yöntemleri, izleme tabanlı bellek toplayıcılarını bölgelerle birleştirir; bunlar, yığını bölgelere ayırarak çalışır, canlı nesneler içeren bölgeleri işaretleyen bir işaret-temizleme geçişi gerçekleştirir ve ardından işaretlenmemiş bölgeleri serbest bırakır. Bunların etkili kalabilmesi için sürekli birleştirme (defragmentation) gerektirir..

## Kaynakça