Forum: Ders Arası RSS
Bir MmFile örneği
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4641 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Bir MmFile örneği
MmFile, "memory-mapped file" anlamına geliyor. Türkçe'ye "bellekle eşleştirilmiş dosya" diye çevirebiliriz. Ne kadar büyük olursa olsun, bütün dosya sanki bellekte bir adreste oturuyormuş gibi sunuluyor. İşin güzel tarafı, aslında dosyanın yalnızca erişilen bölümleri gerektikçe otomatik olarak okunuyor.

Bu, aslında D'nin değil, işletim sisteminin sanal bellek (virtual memory) olanağından yararlanarak sunduğu bir olanak. Küçük dosyalarda yarardan çok zarar getirebilirmiş çünkü sanal belleğin kullandığı en küçük bellek birimi 4K. O yüzden, örneğin dosya 5K bile olsa toplamda 2 adet 4K kullanılması gerekiyor.

Bu olanak ancak binary dosyalarla kullanılabilir. Örneğin, bir metin dosyasını bu şekilde kullanmak uygun değil. Ek olarak, dosya içeriği olarak sunulan diziye eleman eklemeye kalkışmamak gerek çünkü D bütün içeriği bambaşka bir yere kopyalar ama işletim sisteminin bundan haberi olmaz.

Aşağıdaki program mevcut değilse bir dosya oluşturuyor, içeriğinin bir bölümünü dizi olarak kullanıyor. Güzel olan, dosyayı kendimiz açmıyoruz ve elemanları doğrudan kullanıyoruz. Programın gösterdiği gibi, dosyayı kayıt bile etmiyoruz. Biz belleği gerektiğinde dizi ile oynayarak değiştiriyoruz; asıl dosyanın değiştirilmesi işletim sistemine kalıyor.
 
import std.exception : enforce;
import std.range : iota, array;
import std.algorithm : map;
import std.string : format;
import std.conv : to;
import std.stdio : writefln, File, writeln;
import std.file : exists;
import std.mmfile : MmFile;
 
struct S {
    double d;
    int i;
    short s;
    byte b;
}
 
// Yanlışlıkla fazla büyük dosya üretmemek için yapay bir sınır
enum sınır = 1_000_000; // bayt olarak
 
void main() {
    const dosyaİsmi = "S_nesnelerim";
 
    if (exists(dosyaİsmi)) {
        writefln("%s dosyası mevcut olduğundan tekrar oluşturmuyorum.", dosyaİsmi);
    } else {
        const adet = 10;
        dosyaOluştur(dosyaİsmi, adet);
    }
 
    elemanlarıKullan(dosyaİsmi);
}
 
void dosyaOluştur(string dosyaİsmi, ulong adet) {
    enforce(adet * S.sizeof <= sınır,
            format("Fazla büyük dosya oluşturmak istemiyorum." ~
                   " Gerekiyorsa 'sınır' değişkeninin değerini değiştirin."));
 
    auto dosya = File(dosyaİsmi, "w");
 
    // Kaç adet eleman olduğunu yaz
    dosya.rawWrite([adet]);
 
    // Elemanları üret
    const dizi = adet.iota.map!(i => S(i + 0.5, i.to!int, i.to!short, i.to!byte)).array;
 
    // Dosyaya yaz
    dosya.rawWrite(dizi);
 
    writefln("%s dosyasını oluşturdum:", dosyaİsmi);
    writefln("%(%s\n%)", dizi);
}
 
void elemanlarıKullan(string dosyaİsmi) {
    // mm, dosyanın içeriğine erişim sağlayan bir nesnedir
    // 0: uzunluğunu dosyadan kendin hesapla anlamına geliyor
    // null: dosyayı bellekte istediğin yere yerleştir anlamına geliyor
    auto mm = new MmFile(dosyaİsmi, MmFile.Mode.readWrite, 0, null);
 
    // Bu dosya düzeninde en başta ulong türünde adet bilgisi bulunduğunu
    // biliyoruz.  O yüzden mm'in iki farklı dizi olarak dilimliyoruz:
    const adet = (cast(ulong[])(mm[0..ulong.sizeof]))[0];
    auto dizi = cast(S[])mm[ulong.sizeof..mm.length];
 
    // Elemanlara nasıl erişildiğini göstermiş olmak için ortadaki elemanla
    // oynuyoruz
    dizi[$/2].i *= 2;
 
    writefln("Ortadaki elemanı değiştirdim:");
    writefln("%(%s\n%)", dizi);
}
Ali
Avatar
Salih Dinçer #2
Üye Ock 2012 tarihinden beri · 1926 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yani 1 dosya içinde 10 adet S yapısını mı kopyaladık? Aynı şekilde biz bu bir deste S dizine erişip değiştikçe yaptığımız değişiklikler otomatik güncellenmiş mi olacak?
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4641 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Salih Dinçer:
Yani 1 dosya içinde 10 adet S yapısını mı kopyaladık?

Eve ama hepsini birden yazma işi zaten rawWrite() ile hallediliyor.

Aynı şekilde biz bu bir deste S dizine erişip değiştikçe yaptığımız değişiklikler otomatik güncellenmiş mi olacak?

Evet, kolaylık orada. Dosya sistemi dosyaları diskte ardışık olmayan parçalar halinde tutar. İşletim sisteminin burada yaptığı, bütün dosyayı tek bellek bloğu olarak göstermek ama yalnızca gereken parçalarını biz eriştikçe okumak ve yazmak.

Burada akla gelen bir soru, bellekteki her değişikliğin dosyayı hemen etkileyip etkilememesi. Çünkü eğer her değişiklik dosyaya yazıyorsa gereksiz yavaşlık oluşabilirdi. (Yani, sistemin "caching" davranışını merak ediyoruz.) Şimdi baktım, işletim sistemi sanal bellek için nasıl davranıyorsa MmFile da dolaylı olarak onu kullanıyormuş. Bundan oldukça etkin olduğunu anlamalıyız.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2018-02-20, 01:04:26 (UTC -08:00)