Bellek eşlemeli dosyaların avantajları nelerdir?


90

Bir proje için bellek eşlemeli dosyaları araştırıyorum ve bunları daha önce kullanmış veya kullanmamaya karar vermiş kişilerin düşüncelerini takdir ediyorum ve neden?

Özellikle, önem sırasına göre aşağıdakilerle ilgileniyorum:

  • eşzamanlılık
  • rasgele erişim
  • verim
  • kullanım kolaylığı
  • taşınabilirlik

Yanıtlar:


57

Bence avantaj, geleneksel bir dosya okuma yöntemlerine göre gereken veri kopyalama miktarını azaltmanızdır.

Uygulamanız verileri bellek eşlemeli bir dosyada "yerinde" kullanabiliyorsa, kopyalanmadan içeri girebilir; Bir sistem çağrısı (örneğin Linux'un pread ()) kullanıyorsanız, bu genellikle çekirdeğin verileri kendi tamponlarından kullanıcı alanına kopyalamasını içerir. Bu fazladan kopyalama sadece zaman almakla kalmaz, aynı zamanda verilerin bu ekstra kopyasına erişerek CPU önbelleklerinin etkinliğini azaltır.

Verilerin gerçekten diskten okunması gerekiyorsa (fiziksel G / Ç'de olduğu gibi), işletim sistemi hala bunları okumak zorundadır, bir sayfa hatası muhtemelen bir sistem çağrısından daha iyi bir performans değildir, ancak yapmayın (yani zaten işletim sistemi önbelleğinde), performans teoride çok daha iyi olmalıdır.

Olumsuz tarafı, bellek eşlemeli dosyalar için eşzamansız bir arabirim yoktur - eşlenmemiş bir sayfaya erişmeye çalışırsanız, bir sayfa hatası oluşturur ve ardından iş parçacığı G / Ç'yi bekletir.


Bellek eşlemeli dosyaların bariz dezavantajı, 32 bit işletim sistemindedir - adres alanını kolayca tüketebilirsiniz.


4
En azından Windows'ta, daha büyük bir mmap dosyasının birden çok 32 bit görünümünü eşleyebilirsiniz - bu, normal CRT işlevini kullanarak çok büyük dosyalarla uğraşmaya çalışmaktan daha verimli olabilir
Martin Beckett

@MarkR "Ekstra kopyalaması sadece zaman almakla kalmıyor, aynı zamanda verilerin bu fazladan kopyasına erişerek CPU'nun önbelleklerinin etkinliğini de azaltıyor. " Yazdınız . ( vurgu benim). Çekirdekteki fazladan tampon kopyasının CPU önbelleklerinin etkinliğini nasıl engellediğini açıklayabilir misiniz?
Geek

4
@Geek iki kat fazla belleğe erişiyor = iki kat fazla önbellek boşa harcanıyor (yaklaşık olarak).
user253751

50

Kullanıcı yazarken bir 'otomatik tamamlama' özelliğini uygulamak için bellek eşlemeli bir dosya kullandım. Tek bir dizin dosyasında depolanan 1 milyondan fazla ürün parça numaram var. Dosya bazı tipik başlık bilgilerine sahiptir, ancak dosyanın büyük kısmı, anahtar alanında sıralanan dev bir sabit boyutlu kayıt dizisidir.

Çalışma zamanında dosya bellek eşlenir, C-tipli bir structdiziye dönüştürülür ve kullanıcı türü olarak eşleşen parça numaralarını bulmak için ikili arama yaparız. Dosyanın yalnızca birkaç bellek sayfası aslında diskten okunur - ikili arama sırasında hangi sayfalara ulaşılırsa bakılır.

  • Eşzamanlılık - Bazen aynı işlem alanında dosyayı birden çok kez belleğe eşleyen bir uygulama sorunum vardı. Bu hatırladığım kadarıyla bir sorundu çünkü bazen sistem dosyayı eşlemek için yeterince büyük bir sanal bellek bloğu bulamıyordu. Çözüm, dosyayı yalnızca bir kez eşlemek ve tüm çağrıları ona atmaktı. Geçmişe bakıldığında, tam gelişmiş bir Windows hizmeti kullanmak harika olurdu.
  • Rastgele Erişim - İkili arama kesinlikle rastgele erişim ve yıldırım hızında
  • Performans - Arama son derece hızlıdır. Kullanıcılar bir açılır pencere yazdıkça eşleşen ürün parça numaralarının bir listesi görüntülenirken liste yazmaya devam ettikçe küçülür. Yazarken gözle görülür bir gecikme yok.

1
Sayfalar her denemede okundukça ikili arama yavaş olmaz mı? Veya işletim sistemi bununla verimli bir şekilde başa çıkacak kadar akıllı mı?
jjxtra

1
Sanırım bellek eşlemeli G / Ç kullanmanın ikili arama için bir tür israf olduğunu düşünüyorum, çünkü arama göreceli olarak uzak bellek konumlarında yalnızca birkaç tek tuşa erişecek, ancak işletim sistemi bu tür her istek için 4k sayfa olarak yükleyecektir. Ancak yine de, parçalı dosya fazla değişmez, bu nedenle önbellek bunu örtbas etmeye yardımcı olur. Ama kesinlikle konuşursak, burada geleneksel arama / okumanın daha iyi olacağına inanıyorum. Son olarak, 1 milyon bugünlerde fazla değil. Neden hepsini RAM'de tutmuyorsunuz?
the domuz

5
@ the swine and PsychoDad benim asıl cevabım 2008 yılına aitti ve bu bellek eşlemeli otomatik tamamlama özelliğinin gerçek uygulaması 2004-2005 civarındaydı. Dosyanın tamamını yüklemek için 800-1000 MB fiziksel bellek tüketmek, kullanıcı tabanımız için iyi bir çözüm değildi. Bellek eşlemeli çözüm çok hızlı ve etkiliydi. Tekmeledi ve bunu genç geliştirici günlerimden sevgiyle hatırlıyorum. :)
Brian Ensink

@BrianEnsink: Tamam, bu mantıklı. Her girişin 1kB kadar olmasını beklemiyordum. o zaman elbette sayfalı yaklaşım daha verimli hale gelir. güzel :)
the swine

consuming physical memory to load the entire file was not a good solution. Neden fiziksel bellekle ilgilendiğinizden emin değilim (bir dosyanın byteBuffer'a yüklenmesi daha fazla fiziksel bellek gerektirir mi? Bu bir işletim sistemi detayıdır). mmap, sanal bellekteki tüm bu alanı kaplar ve bir dosyayı ihtiyacınız olan belirli baytlara göre okumak gerekmez. the swinebahsedilen But strictly speaking, i believe that traditional seeking/reading would be better in here.. Bu ilginç bir düşünce, çünkü o zaman tam anlamıyla ihtiyacınız olan baytları ihtiyaç duyduğunuzda okuyabilirsiniz.
Ben Butterworth

22

Bellek eşlemeli dosyalar, okuma / yazma erişimini değiştirmek veya eşzamanlı paylaşımı desteklemek için kullanılabilir. Bunları bir mekanizma için kullandığınızda, diğerini de elde edersiniz.

Bir dosyada aramak, yazmak ve okumak yerine, onu belleğe eşlersiniz ve sadece olmasını beklediğiniz bitlere erişirsiniz.

Bu çok kullanışlı olabilir ve sanal bellek arayüzüne bağlı olarak performansı artırabilir. Performans artışı, işletim sisteminin artık diğer tüm programlı bellek erişiminizle birlikte bu eski "dosya G / Ç'sini" yönetmesi ve (teoride) disk belleği algoritmalarından yararlanabilmesi ve bunun için zaten kullandığı programınızın geri kalanı için sanal bellek . Bununla birlikte, temeldeki sanal bellek sisteminizin kalitesine bağlıdır. Anekdotlar, Solaris ve * BSD sanal bellek sistemlerinin, Linux'un VM sisteminden daha iyi performans iyileştirmeleri gösterebileceğini söyledi - ancak bunu yedekleyecek deneysel veriye sahip değilim. YMMV.

Eşzamanlılık, eşlenmiş bellek aracılığıyla aynı "dosyayı" kullanan birden çok işlemin olasılığını düşündüğünüzde ortaya çıkıyor. Okuma / yazma modelinde, iki işlem dosyanın aynı alanına yazarsa, işlem verilerinden birinin diğer işlemin verilerinin üzerine yazarak dosyaya ulaşacağından hemen hemen emin olabilirsiniz. Birini ya da diğerini alırsınız - ama tuhaf bir karışım olmaz. İtiraf etmeliyim ki, bunun herhangi bir standart tarafından zorunlu kılınan bir davranış olup olmadığından emin değilim, ama bu hemen hemen güvenebileceğiniz bir şey. (Aslında iyi bir takip sorusu!)

Haritalanan dünyada, bunun tersine, iki süreci de "yazarken" hayal edin. Bunu "bellek depoları" yaparak yaparlar, bu da verilerin en sonunda diske O / S sayfalanmasına neden olur. Ancak bu arada, çakışan yazıların olması beklenebilir.

İşte bir örnek. Diyelim ki her ikisi de 1024 ofsette 8 bayt yazan iki işlemim var. İşlem 1 '11111111' yazıyor ve işlem 2 '22222222' yazıyor. Dosya G / Ç kullanıyorlarsa, O / S'nin derinliklerinde, 1'lerle dolu bir tampon ve her ikisi de diskte aynı yere giden 2'lerle dolu bir tampon olduğunu hayal edebilirsiniz. Biri oraya önce, diğeri saniye sonra gidecek. Bu durumda ikincisi kazanır. Bununla birlikte , bellek eşlemeli dosya yaklaşımını kullanıyorsam, işlem 1 4 baytlık bir bellek deposuna, ardından 4 baytlık başka bir bellek deposuna gidecek (bunun maksimum bellek depolama boyutu olmadığını varsayalım). İşlem 2 aynı şeyi yapacak. İşlemlerin ne zaman çalıştığına bağlı olarak, aşağıdakilerden herhangi birini görmeyi bekleyebilirsiniz:

11111111
22222222
11112222
22221111

Bunun çözümü, her halükarda muhtemelen iyi bir fikir olan açık karşılıklı dışlamayı kullanmaktır. Her halükarda, okuma / yazma dosyası G / Ç durumunda "doğru şeyi" yapması için O / S'ye güveniyordunuz.

Sınıflandırma karşılıklı dışlama ilkeli mutekstir. Bellek eşlemeli dosyalar için, (örneğin) pthread_mutex_init () kullanılarak kullanılabilen bellek eşlemeli bir mutekse bakmanızı öneririm.

Tek bir aldatmaca ile düzenleme: Eşlenen dosyaları kullanırken, dosyadaki verilere işaretçileri dosyanın kendisinde gömmek için bir cazibe vardır (eşlenen dosyada depolanan bağlantılı listeyi düşünün). Dosya, farklı zamanlarda veya farklı işlemlerde farklı mutlak adreslerde eşlenebileceğinden, bunu yapmak istemezsiniz. Bunun yerine, eşlenen dosya içinde ofsetleri kullanın.


1

Eşzamanlılık bir sorun olabilir. Rastgele erişim daha kolaydır Performans, iyi ile harika arasıdır. Kullanım kolaylığı. O kadar iyi değil. Taşınabilirlik - çok sıcak değil.

Onları uzun zaman önce bir Güneş sisteminde kullandım ve bunlar benim düşüncelerim.

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.