Bellek parçalanması nedir?


206

"Hafıza parçalanması" teriminin C ++ dinamik hafıza tahsisi bağlamında birkaç kez kullanıldığını duydum. Bellek parçalanmasıyla nasıl başa çıkılacağı konusunda bazı sorular buldum, ancak kendisiyle ilgilenen doğrudan bir soru bulamıyorum. Yani:

  • Bellek parçalanması nedir?
  • Bellek parçalanmasının uygulamam için bir sorun olup olmadığını nasıl anlarım? Ne tür bir programın acı çekmesi muhtemeldir?
  • Bellek parçalanmasıyla başa çıkmanın yaygın yolları nelerdir?

Ayrıca:

  • Dinamik ayırmaların çok fazla bellek parçalanmasını artırabildiğini duydum. Bu doğru mu? C ++ bağlamında, tüm standart kapları (std :: string, std :: vector, vb.) Dinamik bellek ayırma kullandığını anlıyorum. Bunlar bir program boyunca kullanılırsa (özellikle std :: string), bellek parçalanması bir sorun olabilir mi?
  • STL-heavy uygulamasında bellek parçalanması ile nasıl başa çıkılabilir?

1
Harika cevaplar, herkese teşekkürler!
AshleysBrain

4
Zaten çok sayıda harika yanıt var, ancak burada bellek parçalanmasının büyük bir sorun olduğu gerçek bir uygulamadan (Firefox) bazı resimler var: blog.pavlov.net/2007/11/10/memory-fragmentation
Marius Gedminas

2
@MariusGedminas artık çalışmıyor Bu yüzden link ile birlikte kısa bir özet sunmak ya da soruyu link ile özet ile cevaplamak önemlidir
katta

Tabii ama yarım on yıldan fazla oldu
rsethc

3
Aşağıda Marius tarafından yayınlanan bağlantılar için güncellenmiş bir konumdur: pavlovdotnet.wordpress.com/2007/11/10/memory-fragmentation
TheGameiswar

Yanıtlar:


314

"Büyük" (32 bayt) geniş bir boş hafıza alanına sahip olduğunuzu düşünün:

----------------------------------
|                                |
----------------------------------

Şimdi, bir kısmını tahsis edin (5 tahsis):

----------------------------------
|aaaabbccccccddeeee              |
----------------------------------

Şimdi, ilk dört ayırmayı serbest bırakın, ancak beşinci ayırmayı serbest bırakın:

----------------------------------
|              eeee              |
----------------------------------

Şimdi, 16 bayt ayırmayı deneyin. Hata, neredeyse iki kat fazla ücretsiz olmasına rağmen yapamam.

Sanal belleğe sahip sistemlerde, parçalanma düşündüğünüzden daha az problemdir, çünkü büyük ayırmaların fiziksel adres alanında değil, yalnızca sanal adres alanında bitişik olması gerekir . Örneğimde, sayfa boyutu 2 bayt olan sanal belleğim olsaydı, 16 bayt ayırmamı sorunsuz bir şekilde yapabilirdim. Fiziksel bellek şöyle görünecektir:

----------------------------------
|ffffffffffffffeeeeff            |
----------------------------------

oysa sanal bellek (çok daha büyük olmak) şöyle görünebilir:

------------------------------------------------------...
|              eeeeffffffffffffffff                   
------------------------------------------------------...

Bellek parçalanmasının klasik belirtisi, yeterli boş hafızaya sahip olsanız bile, büyük bir blok ayırmaya çalışmanızdır. Başka bir olası sonuç, işlemin belleği işletim sistemine geri bırakamamasıdır (çünkü işletim sistemi tarafından ayırdığı tüm bloklarda hala kullanılmakta olan bazı nesneler vardır, çünkü bu bloklar artık çoğunlukla kullanılmamaktadır).

Farklı alanlardaki nesneleri boyutlarına ve / veya beklenen ömürlerine göre ayırarak C ++ çalışmasında bellek parçalanmasını önleyen taktikler. Dolayısıyla, daha sonra çok sayıda nesne oluşturacak ve hepsini birlikte yok edecekseniz, bunları bir bellek havuzundan ayırın. Aralarında yaptığınız diğer ayırmalar havuzdan olmayacak, dolayısıyla bellekte aralarında bulunmayacak, dolayısıyla sonuç olarak bellek parçalanmayacak.

Programınız uzun süredir çalışmadığı ve çok fazla tahsis ve serbest bırakmadığı sürece genellikle bu konuda endişelenmenize gerek yoktur. En çok risk altında olduğunuz kısa ömürlü ve uzun ömürlü nesnelerin karışımları olduğunda, ancak o malloczaman bile yardımcı olmak için elinden geleni yapacaktır. Temel olarak, programınızda ayırma hataları oluncaya veya beklenmedik bir şekilde sistemin belleği azalmasına neden olana kadar yoksayın (bunu tercih için testte yakalayın!).

Standart kitaplıklar belleği ayıran herhangi bir şeyden daha kötü değildir ve standart kapsayıcıların hepsinde, Allockesinlikle gerekli olduğunda ayırma stratejilerini ayarlamak için kullanabileceğiniz bir şablon parametresi vardır.


1
Yani her karakter bir bayt mı? Hangi "büyük genişlik" == 32 bayt (tahmin ediyorum - saymadım) yapacak :) Güzel bir örnek, ama son satırdan önce birimleri söz yararlı olacaktır. :)
jalf

1
@jalf: Evet. Birimlerden hiç bahsetmeyecektim, sonunda anladım. Siz yorum yaparken üzerinde çalışıyordu.
Steve Jessop

Bir "cevap" seçmek oldukça zordu - burada birçok harika cevap ve hepsini okumak isteyen herkesi teşvik ediyorum. Yine de, burada tüm önemli noktaları ele aldığınızı düşünüyorum.
AshleysBrain

1
"Standart kütüphaneler bellek ayıran herhangi bir şeyden daha kötü değildir". Bu doğruysa iyi olur, ancak dize ve vektör gibi standart C ++ şablonlarının uygulamaları, yeniden boyutlandırıldıklarında istenmeyen davranışlara sahip olabilir. Örneğin, visual studio'nun eski sürümlerinde std :: string temel olarak realloc 1.5 * current_size (en yakın 8 bayta kadar) ile yeniden boyutlandırılır. Bu nedenle, bir dizeye eklemeye devam ederseniz, yığını, özellikle gömülü sistemlerde çok kolay bir şekilde ortadan kaldırabilirsiniz. En iyi savunma, gizli reallocs'lardan kaçınmak için kullandığınız yer miktarını korumaktır.
locka

1
@ du369: Sanal bellek, fiziksel kadar kötü bir parçaya sahip değil. ffffffffffffffffsanal bellekte bitişik bir ayırmadır, ancak fiziksel bellekte böyle bitişik bir ayırma olamaz. Eşit olarak parçalanmış olduklarına bakmayı tercih ederseniz, ancak sanal alan çok daha büyükse, bunun yerine ona bakmaktan çekinmeyin. Önemli pratik nokta, geniş sanal adres alanlarının kullanılmasının parçalanmayı görmezden gelmek için genellikle yeterli olmasıdır, bu nedenle 16 bayt ayırmamı yapmama izin verdiğinde yardımcı olur.
Steve Jessop

76

Bellek parçalanması nedir?

Bellek parçalanması, belleğinizin çoğunun çok sayıda bitişik olmayan blokta veya parçalara ayrılmasıdır - toplam belleğinizin büyük bir yüzdesini ayrılmamış, ancak çoğu tipik senaryo için kullanılamaz. Bu, bellek yetersiz özel durumları veya ayırma hatalarıyla sonuçlanır (yani malloc null değerini döndürür).

Bunu düşünmenin en kolay yolu , farklı boyutlarda resimler koymak için ihtiyacınız olan büyük bir boş duvara sahip olduğunuzu hayal etmektir . Her resim belirli bir boyut alır ve belli olması için daha küçük parçalara bölemezsiniz. Duvarda boş bir noktaya, resmin boyutuna ihtiyacınız var ya da başka bir yere koyamazsınız. Şimdi, resimleri duvara asmaya başlarsanız ve onları nasıl düzenlediğiniz konusunda dikkatli değilseniz, yakında kısmen resimlerle kaplı bir duvarla karşılaşacaksınız ve boş lekeleriniz olsa bile çoğu yeni fotoğraf sığmayacak çünkü mevcut noktalardan daha büyükler. Hala gerçekten küçük resimler asabilirsiniz, ancak çoğu uygun değildir. Bu yüzden, daha fazlası için yer açmak için zaten duvarda olanları yeniden düzenlemelisiniz (kompakt).

Şimdi, duvarın sizin (yığın) hafızanız olduğunu ve resimlerin nesneler olduğunu hayal edin. Bu hafıza parçalanması ..

Bellek parçalanmasının uygulamam için bir sorun olup olmadığını nasıl anlarım? Ne tür bir programın acı çekmesi muhtemeldir?

Bellek parçalanmasıyla ilgili olabileceğinizin bir belirtisi, özellikle kullanılan belleğin yüzdesi yüksek olduğunda - ancak tüm belleği henüz kullanmıyorsanız - çok fazla ayırma hatası alıyorsanız - teknik olarak bol miktarda alanınız olmalıdır. ayırmaya çalıştığınız nesneler için.

Bellek büyük ölçüde parçalandığında, bellek ayırıcı yeni nesne için uygun bir alan bulmak için daha fazla iş yapmak zorunda olduğundan, bellek ayırmaları daha uzun sürer. Buna karşılık birçok bellek ayırmanız varsa (muhtemelen bellek parçalanmasıyla sonuçlandığınızdan beri yaparsınız), ayırma süresi bile dikkate değer gecikmelere neden olabilir.

Bellek parçalanmasıyla başa çıkmanın yaygın yolları nelerdir?

Bellek ayırmak için iyi bir algoritma kullanın. Çok sayıda küçük nesne için bellek ayırmak yerine, bu küçük nesnelerin bitişik dizisi için belleği önceden ayırın. Bazen bellek ayırırken biraz savurgan olmak performans için yol kat edebilir ve bellek parçalanmasıyla uğraşmak zorunda kalmanıza engel olabilir.


10
+1. Ben sadece "duvardaki resimler" metafor gerçekten, gerçekten iyi, net bir cevap çünkü önerilen cevabımı sildim.
ctacke

Resimlerin değişen boyutlarda olması gerektiğini vurguladıysanız daha çok istiyorum. Aksi takdirde, parçalanma olmaz.
Björn Pollex

1
İlginç bir şekilde, ana bellek veritabanları bu günlerde biraz pratik hale geliyor (gerçekten çok fazla bellek var). Bu bağlamda, HDD'lerde olduğu gibi, RAM'den sürekli satırların okunmasının, verilerin parçalanmış olandan çok daha hızlı olduğunu belirtmek gerekir.
Björn Pollex

1
Duvarlardaki resimlerle güzel görsel benzetme, ancak ana bellek iki boyutlu değil! Yine de, güzel cevap, teşekkürler.
AshleysBrain

24

Bellek parçalanması, disk parçalanmasıyla aynı kavramdır: kullanılan alanlara atıfta bulunur, çünkü kullanımdaki alanlar birbirine yeterince yakın değildir.

Basit bir oyuncak örneği için on bayt belleğiniz olduğunu varsayalım:

 |   |   |   |   |   |   |   |   |   |   |
   0   1   2   3   4   5   6   7   8   9

Şimdi üç üç baytlık blok atayalım: A, B ve C:

 | A | A | A | B | B | B | C | C | C |   |
   0   1   2   3   4   5   6   7   8   9

Şimdi B bloğunu yeniden konumlandırın:

 | A | A | A |   |   |   | C | C | C |   |
   0   1   2   3   4   5   6   7   8   9

Şimdi dört baytlık bir D bloğu tahsis etmeye çalışırsak ne olur? Peki, dört bayt bellekte boş yer var, ancak dört bitişik bayt belleğimiz yok, bu yüzden D'yi ayıramayız! Bu, hafızanın verimsiz kullanımıdır, çünkü D'yi depolayabilmeliydik, ancak yapamadık. C'yi yer açmak için hareket ettiremeyiz, çünkü programımızdaki bazı değişkenler C'yi işaret ediyor ve tüm bu değerleri otomatik olarak bulamıyor ve değiştiremiyoruz.

Bunun bir sorun olduğunu nereden biliyorsun? En büyük işaret, programınızın sanal bellek boyutunun gerçekte kullandığınız bellek miktarından çok daha büyük olmasıdır. Gerçek dünyadaki bir örnekte, on bayttan fazla belleğiniz olur, bu nedenle D sadece bir bayt 9 başlayarak tahsis edilir ve daha sonra üç bayt uzunluğunda veya daha küçük bir şey ayırmazsanız, bayt 3-5 kullanılmaz.

Bu örnekte, 3 bayt boşa harcanacak çok şey değildir, ancak iki baytlık iki ayırmanın örneğin bellekte on megabayt olduğu ve 10 megabayt boyutunda bir blok tahsis etmeniz gereken daha patolojik bir durumu düşünün. + 1 bayt. Yeterli alana sahip olmanın sadece bir baytlık olmasına rağmen, işletim sisteminden bunu yapmak için on megabayttan fazla sanal bellek istemeniz gerekiyor.

Nasıl önlersiniz? En kötü durumlar, sık sık küçük nesneler oluşturduğunuzda ve yok ettiğinizde ortaya çıkma eğilimindedir, çünkü bu, birçok küçük delikle ayrılmış birçok küçük nesne ile "İsviçre peyniri" etkisi oluşturma eğilimindedir ve bu deliklere daha büyük nesneler tahsis etmeyi imkansız hale getirir. Bunu yapacağınızı bildiğinizde, etkili bir strateji, küçük nesneleriniz için büyük bir bellek bloğunu havuz olarak önceden ayırmak ve daha sonra izin vermek yerine bu blok içindeki küçük nesnelerin oluşturulmasını manuel olarak yönetmektir. varsayılan ayırıcı işlemek.

Genel olarak, ne kadar az ayırma yaparsanız, bellek parçalanma olasılığı o kadar az olur. Bununla birlikte, STL bununla oldukça etkili bir şekilde ilgilenir. Geçerli tahsisatının tamamını kullanan bir dizeniz varsa ve bu karaktere bir karakter eklerseniz, geçerli uzunluğuna ve bir tanesine yeniden tahsis edilmez , uzunluğunu iki katına çıkarır . Bu, "sık küçük tahsisat havuzu" stratejisinin bir varyasyonudur. Dize, tekrarlanan küçük yeniden tahsisler yapmadan boyutta tekrarlanan küçük artışlarla etkili bir şekilde başa çıkabilmesi için büyük bir bellek yığınını yakalar. Tüm STL kapları aslında bu tür bir şey yapar, bu nedenle genellikle otomatik olarak yeniden tahsis edilen STL kaplarının neden olduğu parçalanma hakkında çok fazla endişelenmenize gerek yoktur.

Tabii ki STL kapları bellekleri birbirleri arasında biriktirmese de, çok sayıda küçük kap (sık sık yeniden boyutlandırılan birkaç kap yerine) oluşturacaksanız, aynı şekilde parçalanmayı önleme konusunda kendinizi endişelendirmeniz gerekebilir. herhangi bir sık ​​oluşturulan küçük nesneler için, STL veya değil.


14
  • Bellek parçalanması nedir?

Bellek parçalanması, teorik olarak mevcut olmasına rağmen belleğin kullanılamaz hale gelmesi sorunudur. İki tür parçalanma vardır: dahili parçalanma ayrılan ancak kullanılamayan bellektir (örneğin bellek 8 baytlık parçalara tahsis edildiğinde, ancak program sadece 4 bayta ihtiyaç duyduğunda tekrar tekrar tekli açıklamalar yapar). harici parçalanma , boş belleğin birçok küçük parçaya bölünmesi sorunudur, böylece yeterli boş bellek olmasına rağmen büyük ayırma istekleri karşılanamaz.

  • Bellek parçalanmasının uygulamam için bir sorun olup olmadığını nasıl anlarım? Ne tür bir programın acı çekmesi muhtemeldir?

programınız gerçek paylod verilerinin gerektirdiğinden çok daha fazla sistem belleği kullanıyorsa (ve bellek sızıntılarını dışladıysanız) bellek parçalanması bir sorundur.

  • Bellek parçalanmasıyla başa çıkmanın yaygın yolları nelerdir?

İyi bir bellek ayırıcı kullanın. IIRC, "en uygun" stratejiyi kullananlar, biraz yavaşlarsa parçalanmadan kaçınmak konusunda genellikle çok daha üstündürler. Bununla birlikte, herhangi bir tahsis stratejisi için patolojik en kötü vakaların olduğu gösterilmiştir. Neyse ki, çoğu uygulamanın tipik tahsis paternleri, tahsis edicilerin ele alması için nispeten iyi huyludur. Detaylarla ilgileniyorsanız bir sürü kağıt var:

  • Paul R. Wilson, Mark S. Johnstone, Michael Neely ve David Boles. Dinamik Depolama Ayırma: Anket ve Eleştirel İnceleme. 1995 Uluslararası Bellek Yönetimi Çalıştayı, Springer Verlag LNCS, 1995
  • Mark S.Johnstone, Paul R. Wilson. Bellek Parçalama Sorunu: Çözüldü mü? ACM SIG-PLAN Bildirimleri'nde, cilt 34 No. 3, sayfa 26-36, 1999
  • MR Garey, RL Graham ve JD Ullman. Bellek ayırma algoritmalarının en kötü durum analizi. Dördüncü Yıllık ACM Bilgisayar Teorisi Sempozyumu'nda, 1972

9

Güncelleme:
Google TCMalloc: İş Parçacığı Önbelleğe Alma Malloc Uzun süren bir süreçte parçalanma işleminde oldukça iyi
olduğu bulundu .


HP-UX 11.23 / 11.31 ia64'te bellek parçalanmasıyla ilgili sorunları olan bir sunucu uygulaması geliştiriyorum.

Öyle görünüyordu. Bellek ayırma ve ayırma işlemleri yapan ve günlerce süren bir süreç vardı. Ve bellek sızıntısı olmamasına rağmen, işlemin bellek tüketimi artmaya devam etti.

Deneyimlerim hakkında. HP-UX'de HP-UX gdb kullanarak bellek parçalanması bulmak çok kolaydır. Bir kesme noktası ayarlarsınız ve vurduğunuzda bu komutu çalıştırırsınız: info heapişlem için tüm bellek ayırmalarını ve toplam yığın boyutunu görürsünüz. Sonra programa devam et ve bir süre sonra tekrar kırılma noktasına ulaş. Tekrar yapıyorsun info heap. Yığın toplam boyutu daha büyükse, ancak ayrı ayırmaların sayısı ve boyutu aynı ise, bellek ayırma sorunlarınız olabilir. Gerekirse bunu birkaç ön kontrol yapın.

Durumu iyileştirme yolum buydu. HP-UX gdb ile bazı analizler yaptıktan sonra, bellek problemlerinin std::vectorbir veritabanından bazı tür bilgileri saklamak için kullandığımdan kaynaklandığını gördüm . std::vectorverilerin bir blokta tutulmasını gerektirir. Birkaç konteynere sahiptim std::vector. Bu kaplar düzenli olarak yeniden yaratıldı. Sıklıkla veritabanına yeni kayıtların eklendiği ve daha sonra kapların yeniden oluşturulduğu durumlar vardı. Ve yeniden oluşturulan kaplar daha büyük olduğundan, kullanılabilir boş bellek bloklarına sığmadılar ve çalışma zamanı işletim sisteminden yeni bir büyük blok istedi. Sonuç olarak, bellek sızıntısı olmamasına rağmen, işlemin bellek tüketimi arttı. Konteynerleri değiştirdiğimde durumu iyileştirdim. Yerine std::vectorkullanmaya başladımstd::deque veri için bellek ayırmanın farklı bir yolu vardır.

HP-UX'te bellek parçalanmasını önlemenin yollarından birinin Küçük Blok Allocator veya MallocNextGen kullanmak olduğunu biliyorum. RedHat Linux'ta varsayılan ayırıcı, birçok küçük bloğun tahsis edilmesini iyi ele alıyor gibi görünüyor. Windows'da Low-fragmentation Heapçok sayıda küçük tahsis sorunu var ve bu sorunu çözüyor.

Anladığım kadarıyla, STL-ağır bir uygulamada önce problemleri tanımlamanız gerekir. Bellek ayırıcılar (libc'deki gibi) aslında çok küçük ayırma sorununu ele alırlar , bu tipiktir std::string(örneğin sunucu uygulamamda çok sayıda STL dizesi vardır, ancak çalıştığımdan beri info heapherhangi bir soruna neden olmuyorlar). Benim izlenimim, sık sık büyük tahsislerden kaçınmanız gerektiğidir. Ne yazık ki onlardan kaçınamayacağınız ve kodunuzu değiştirmeniz gerekmediği durumlar var. Benim durumumda söylediğim gibi, geçiş yaptığımda durumu iyileştirdim std::deque. Bellek parçanızı belirlerseniz, bunun hakkında daha kesin bir şekilde konuşmak mümkün olabilir.


6

Bellek parçalanma büyük olasılıkla tahsis ve ne zaman meydana etmektir ayırması büyüklü küçüklü birçok nesne. Bellekte aşağıdaki düzeniniz olduğunu varsayalım:

obj1 (10kb) | obj2(20kb) | obj3(5kb) | unused space (100kb)

Şimdi, obj2serbest bırakıldığında, 120kb kullanılmayan belleğiniz var, ancak 120kb'lik tam bir blok ayıramazsınız, çünkü bellek parçalanmıştır.

Bu etkiyi önlemek için yaygın teknikler arasında halka tamponları ve nesne havuzları bulunur . STL bağlamında, benzer yöntemler std::vector::reserve()yardımcı olabilir.



3

Bellek parçalanması nedir?

Uygulamanız dinamik bellek kullandığında, bellek parçalarını ayırır ve serbest bırakır. Başlangıçta, uygulamanızın tüm hafıza alanı bitişik bir boş hafıza bloğudur. Bununla birlikte, farklı büyüklükteki blokları ayırıp serbest bıraktığınızda, bellek parçalanmaya başlar , yani büyük bitişik serbest blok ve birkaç bitişik tahsis edilmiş blok yerine, ayrılmış ve serbest bloklar karıştırılır. Serbest blokların boyutu sınırlı olduğundan, bunları tekrar kullanmak zordur. Örneğin, 1000 bayt boş belleğiniz olabilir, ancak 100 baytlık bir blok için bellek ayıramazsınız, çünkü tüm boş bloklar en fazla 50 bayt uzunluğundadır.

Başka bir kaçınılmaz, ancak daha az sorunlu parçalanma kaynağı, çoğu mimaride bellek adreslerinin 2, 4, 8 vb. Bayt sınırlarıyla hizalanması gerektiğidir (yani adresler 2, 4, 8 vb. Katları olmalıdır). örneğin 3 charalan içeren bir yapıya sahip olsanız bile , her alanın 4 baytlık bir sınıra hizalanması nedeniyle, yapınızın 3 yerine 12 boyutu olabilir.

Bellek parçalanmasının uygulamam için bir sorun olup olmadığını nasıl anlarım? Ne tür bir programın acı çekmesi muhtemeldir?

Açık cevap, bellek yetersiz bir istisna olsun.

Görünüşe göre C ++ uygulamalarında bellek parçalanmasını tespit etmek için iyi bir taşınabilir yol yoktur. Daha fazla ayrıntı için bu cevaba bakınız.

Bellek parçalanmasıyla başa çıkmanın yaygın yolları nelerdir?

İşaretçilerde doğrudan bellek adresleri kullandığınız ve belirli bir bellek adresine kimlerin başvurduğunu denetleyemediğiniz için C ++ 'da zordur. Bu nedenle, ayrılan bellek bloklarını (Java çöp toplayıcısının yaptığı gibi) yeniden düzenlemek bir seçenek değildir.

Özel bir ayırıcı, daha büyük bir bellek yığınındaki küçük nesnelerin tahsisini yöneterek ve bu yığın içindeki boş yuvaları yeniden kullanarak yardımcı olabilir.


3

Bu aptallar için süper basitleştirilmiş bir versiyonudur.

Nesneler bellekte oluşturuldukça, bellekte kullanılan bölümün sonuna eklenirler.

Belleğin kullanılan bölümünün sonunda olmayan bir nesne silinir, yani bu nesne diğer 2 nesne arasındaysa, bir "delik" oluşturur.

Parçalanma denen şey budur.


2

Yığına bir öğe eklemek istediğinizde, bilgisayarın bu öğeye sığacak kadar boşluk araması gerekir. Bu nedenle, bellek havuzunda veya havuzlanmış bir ayırıcıyla yapılmadığında dinamik ayırmalar işleri yavaşlatabilir. Ağır bir STL uygulaması için çoklu iş parçacığı kullanıyorsanız, Hoard ayırıcısı veya TBB Intel sürümü vardır.

Şimdi, bellek parçalandığında iki şey olabilir:

  1. "Büyük" nesneleri yapıştırmak için iyi bir alan bulmak için daha fazla arama yapılması gerekecektir. Yani, güzel bir bitişik bellek yığını bulmak için dağılmış birçok küçük nesne belirli koşullar altında zor olabilir (bunlar aşırıdır.)
  2. Bellek kolay okunabilen bir varlık değildir. İşlemciler, ne kadar tutabilecekleri ve nerede bulundukları ile sınırlıdır. Bunu, ihtiyaç duydukları bir öğe bir yer, ancak geçerli adresler başka bir yer ise sayfaları değiştirerek yaparlar. Sayfaları sürekli olarak değiştirmek zorunda kalırsanız, işlem yavaşlayabilir (yine, bunun performansı etkilediği aşırı senaryolar.) Sanal bellekte bu gönderiye bakın .

1

Farklı boyutlarda bellek blokları istendiğinden bellek parçalanması meydana gelir. 100 baytlık bir tampon düşünün. İki karakter, ardından bir tamsayı istersiniz. Şimdi iki karakteri serbest bırakırsınız, sonra yeni bir tamsayı istersiniz - ancak bu tamsayı iki karakterin alanına sığamaz. Bu bellek yeniden kullanılamaz çünkü yeniden tahsis edilecek kadar büyük bir bitişik blokta değildir. Bunun da ötesinde, karakterleriniz için bir sürü ayırıcı yükü çağırdınız.

Temel olarak, bellek çoğu sistemde yalnızca belirli boyutta bloklar halinde gelir. Bu blokları ayırdığınızda, tüm blok serbest kalana kadar tekrar birleştirilemezler. Bu, aslında bloğun sadece küçük bir kısmı kullanımda olduğunda tüm blokların kullanılmasına yol açabilir.

Yığın parçalanmasını azaltmanın birincil yolu daha büyük, daha az sıklıkta ayırma yapmaktır. Aşırı derecede, nesneleri en azından kendi kodunuz içinde taşıyabilen yönetilen bir yığın kullanabilirsiniz. Bu, problemi tamamen ortadan kaldırır - yine de hafıza perspektifinden. Belli ki hareketli nesneler ve bunun gibi bir bedeli vardır. Gerçekte, gerçekten sık sık yığıntan çok küçük miktarlar tahsis ediyorsanız bir sorun yaşarsınız. Bitişik kapları (vektör, dizi, vb.) Kullanmak ve yığını mümkün olduğunca insanca ayırmak (her zaman performans için iyi bir fikir) onu azaltmanın en iyi yoludur. Bu aynı zamanda önbellek tutarlılığını artırır, bu da uygulamanızın daha hızlı çalışmasını sağlar.

Hatırlamanız gereken şey, 32bit x86 masaüstü sisteminde, 4KB "sayfalara" bölünen 2GB'lık bir belleğinizin olmasıdır (sayfa boyutunun tüm x86 sistemlerinde aynı olduğundan emin olabilirsiniz). Bir sorun yaşamak için omgwtfbbq parçalanmasını çağırmanız gerekecek. Modern yığınlar, uygulamaların büyük çoğunluğu için aşırı derecede büyük olduğundan ve yönetilen yığınlar gibi buna dayanabilecek sistemlerin yaygınlığı nedeniyle parçalanma gerçekten geçmişte kaldı.


0

Ne tür bir programın acı çekmesi muhtemeldir?

Bellek parçalanmasıyla ilgili sorunlara güzel (= dehşet verici) bir örnek , Stardock'un bir bilgisayar oyunu olan "Elemental: War of Magic" in geliştirilmesi ve piyasaya sürülmesiydi .

Oyun 32bit / 2GB Bellek için üretildi ve oyunun bu 2GB Bellek içinde çalışmasını sağlamak için bellek yönetiminde çok fazla optimizasyon yapmak zorunda kaldı. "Optimizasyon" sürekli tahsis ve tahsisatlara yol açtıkça, zamanla yığın bellek parçalanması meydana geldi ve her seferinde oyun çöktü .

YouTube'da bir "savaş hikayesi" röportajı var.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.