Özel yığın ayırıcılar


9

Çoğu program, işlevsel programlama dillerinin eski nesneleri değiştirmek yerine yeni nesneler ayırmayı tercih ettiği ve çöp toplayıcının bir şeyleri serbest bırakma konusunda endişe duyduğu ölçüde yığın ayırma konusunda oldukça rahat olabilir.

Gömülü programlamada, sessiz sektör, ancak, bellek ve zor gerçek zamanlı kısıtlamalar nedeniyle yığın ayırmayı hiç kullanamayacağınız birçok uygulama vardır; işlenecek her türden nesne sayısı belirtimin bir parçasıdır ve her şey statik olarak ayrılmıştır.

Oyun programlama (en azından donanımı itme konusunda iddialı olan oyunlarla) bazen arasına girer: dinamik ayırmayı kullanabilirsiniz, ancak ayırıcıyı kara kutu olarak kullanamayacağınız yeterli bellek ve yumuşak gerçek zamanlı kısıtlamalar vardır , çöp toplama kullanalım, bu yüzden özel ayırıcılar kullanmalısınız. Bu, C ++ oyun endüstrisinde hala yaygın olarak kullanılmasının nedenlerinden biridir; http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html gibi şeyler yapmanızı sağlar

Aradaki bölgede başka hangi alanlar var? Oyunlar dışında, özel ayırıcılar nerede yoğun olarak kullanılıyor?


1
Bazı işletim sistemleri , nesne önbelleğe alma olanağı sağlayan bir plaka ayırıcı kullanır, ancak bir nesnenin üyelerini modulo 2 ** N dizinli önbellek için farklı kümelerle eşleştirerek işlemci önbelleği çakışma hatalarını azaltmak için de kullanılabilir (her ikisi de bitişik bir bellekte birden çok örneğe sahip olarak ve döşeme içinde değişken dolgu ile). Önbellek davranışı, bazı durumlarda ayırma / serbest hız veya bellek kullanımından daha önemli olabilir.
Paul A. Clayton

Yanıtlar:


4

Performans yoğun bir kritik yolu olan bir uygulamanız olduğunda, hafızayı nasıl ele aldığınızı düşünmelisiniz. Son kullanıcı istemci tarafı uygulamalarının çoğu bu olaya dahil değildir, çünkü bunlar birincil olay güdümlüdür ve çoğu olay kullanıcı ile etkileşimlerden gelir ve bu kadar çok (hiç varsa) performans kısıtlamasına sahip değildir.

Ancak, çok sayıda arka uç yazılım hafızanın nasıl ele alındığına biraz odaklanmalıdır, çünkü bu yazılımın birçoğu daha fazla sayıda istemci, çok sayıda işlem, daha fazla veri kaynağı işlemek için ölçeklenebilir. sınırları zorlayarak, yazılım kullanıcılarınızın nasıl bellek kullanabileceğini analiz etmeye başlayabilir ve akla gelebilecek herhangi bir kullanım durumunu işlemek için yazılmış tamamen genel bir bellek ayırıcısına güvenmek yerine yazılımınıza göre özel tahsis düzenleri yazabilirsiniz.

Size birkaç örnek vermek gerekirse ... ilk şirketimde, bir Historian paketinde, süreç kontrol verilerinin toplanmasından / depolanmasından / arşivlenmesinden sorumlu yazılım üzerinde çalıştım (10 milyonlarca sensörlü bir fabrika, nükleer santral veya petrol rafinerisi düşünün, bu verileri depolarız). Tarihçinin daha fazla veri işlemesini engelleyen herhangi bir performans darboğazını analiz ettiğimizde, çoğu zaman problem hafızanın nasıl işlendiği ile ilgiliydi. Kesinlikle gerekli olmadıkça malloc / free'in çağrılmadığından emin olmak için büyük çaba sarf ettik.

Şu anki işimde gözetim video dijital kaydedici ve analiz paketi üzerinde çalışıyorum. 30 fps'de her kanal, her 33 milisaniyede bir video karesi alır. Sattığımız donanımda 100 kanallı videoyu kolayca kaydedebiliriz. Bu, kritik yolda (ağ çağrısı => yakalama bileşenleri => kayıt cihazı yönetim yazılımı => depolama bileşenleri => disk) herhangi bir dinamik bellek ayırma olmadığından emin olmak için başka bir durumdur. Sabit boyutlu arabellek kovaları içeren ve daha önce ayrılmış arabellekleri yeniden kullanmak için LIFO kullanan özel bir çerçeve ayırıcıya sahibiz. 600Kb depolama alanına ihtiyacınız varsa, boşa harcanan 1024Kb tampon ile sonuçlanabilir, ancak her tahsisin çok kısa ömürlü olduğu yerlerde kullanımımız için özel olarak tasarlandığından, tampon kullanıldığı için çok iyi çalışır,

Tanımladığım uygulama türünde (çok fazla veriyi A'dan B'ye taşımak ve çok sayıda istemci isteğini işlemek) öbeğe ve arkaya gitmek CPU performansı darboğazlarının önemli bir kaynağıdır. Öbek parçalanmasını minimumda tutmak ikincil bir faydadır, ancak çoğu modern işletim sisteminin zaten düşük parçalanma yığınları uyguladığını söyleyebildiğim kadarıyla (en azından Windows'un yaptığını biliyorum ve diğerlerinin de yapmasını umuyorum). Şahsen, bu tür ortamlarda çalışan 12+ yılda, yığınla ilgili CPU kullanım sorunlarını oldukça sık gördüm, bir zamanlar aslında parçalanmış yığından muzdarip bir sistem görmedim.


"Biz kesinlikle gerekli olmadıkça malloc / free çağrılmadığından emin olmak için büyük çaba sarf ettik ..." - Yönlendirici inşa bazı donanım çocuklar biliyorum. Onlar bile uğraşmıyorlar malloc/free. Bir bellek bloğu ayırırlar ve imleç veri yapısı olarak kullanırlar. İşlerinin çoğu indeksleri takip etmeye indirgenmiştir.

4

Video işleme, VFX, işletim sistemleri, vb. Verimli tahsisi sağlamak için veri yapısı ve paylaştırıcının ayrılması gerekmez.

Örneğin, bir ağaçta verimli ağaç düğümü tahsisini, oktree'nin kendisinden uzağa ayırmak ve harici bir ayırıcıya güvenmek için çok fazla karmaşıklık getiriyor. Bu iki kaygıyı birleştirmek ve aynı anda birçok düğümü aynı anda ayırmak için oktree'nin sorumluluğunu yapmak mutlaka SRP'nin ihlali anlamına gelmez, çünkü bunu yapmak için nedenlerin sayısını artırmaz. Pratik olarak, azaltabilir.

Örneğin C ++ 'da, standart kapların harici bir ayırıcıya güvenmesinin geciktirilmiş yan etkilerinden biri , C ++ topluluğu gibi bağlantılı yapıları oluşturmuştur std::mapve std::listC ++ topluluğu tarafından neredeyse yararsız sayılmıştır.std::allocatorbu veri yapıları her seferinde bir düğüm tahsis eder. Tabii ki bağlantılı yapılarınız bu durumda kötü performans gösterecektir, ancak bağlantılı yapılar için düğümlerin verimli bir şekilde tahsisi bir veri yapıcıdan ziyade bir veri yapısının sorumluluğu olarak kabul edilirse işler çok farklı olurdu. Bellek izleme / profil oluşturma gibi başka nedenlerle de özel bir ayırma kullanabilirler, ancak düğümleri birer birer tahsis etmeye çalışırken bağlantılı yapıları verimli hale getirmek için ayırıcıya güvenmek, varsayılan olarak, son derece verimsiz hale getirir, Bu, bağlantılı yapıların artık ücretsiz liste gibi özel bir ayırıcıya ihtiyaç duyması ve makul öneme sahip olması ve önbellek kayıplarını sağa ve sola tetiklemekten kaçınması iyi bir uyarı ile birlikte gelirse iyi olur. Çok daha pratik olarak uygulanabilir bir şey olabilirdistd::list<T, BlockSize, Alloc>, burada BlockSizeücretsiz liste için bir kerede ayrılacak bitişik düğümlerin sayısını gösterir (1 belirtmek std::list, şimdi olduğu gibi etkili bir şekilde yol gösterecektir ).

Ancak, böyle bir uyarı yoktur, bu da bağlantılı listelerin işe yaramaz olduğu gibi bir kült mantranın yankılanmasına neden olan tüm blok başlıkları topluluğuna yol açar;


3

Özel bir ayırıcı isteyebileceğiniz başka bir alan, yığın parçalanmasını önlemektir . Zaman içinde yığınınız yığın boyunca parçalanmış küçük nesneler tahsis edebilir. Programınız yığın belleği bir arada tutamazsa, programınız daha büyük bir nesne ayırmaya gittiğinde, mevcut, parçalanmış yığınınız (çok küçük) arasında boş bir blok bulamadığı için sistemden daha fazla bellek talep etmelidir. nesneler önünüzde). Programınızın toplam bellek kullanımı zamanla artar ve gereksiz yere ek bellek sayfası tüketirsiniz. Bu nedenle, uzun süreler boyunca çalışması beklenen programlar (veritabanlarını, sunucuları vb. Düşünün) oldukça büyük bir konudur.

Oyunlar dışında, özel ayırıcılar nerede yoğun olarak kullanılıyor?

Facebook

Facebook'un yığın performanslarını artırmak ve parçalanmayı azaltmak için kullanmaya başladığını jemalloc'a göz atın .


Sağ. Ancak, kopyalayan bir çöp toplayıcı parçalanma sorununu düzgün bir şekilde çözer, değil mi?
rwallace
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.