Containerdateien/Virtuelle Dateisysteme



  • ich nehme mal keinen header, sondern ein indexfile der form

    img/terrein/wiese.png 0 1564
    img/terrein/pflaster.png 1564 100
    script/traktor.loa 1664 345
    

    und

    struct Beschreiber{
       int offset;
       int laenge;
    };
    ...
    //indexfile laden
    map<string,Beschreiber> lagerFiles;
    ifstream in("files.idx");
    string name;
    Beschreiber beschreiber;
    for(;;){
       file>>name;
       file>>beschreiber.offset>>beschreiber.laenge;
       if(in.eof())
          break;
       lagerfiles[name]=beschreiber;
    }
    

    und zum laden

    char* loadFile(string filename){
    Beschreiber& b=lagerFiles[filename);//ja, das ist lecker schnell!
    void* mem=operator new(beschreiber.laenge);
    offenesLagerfile.seek(beschreiber.laenge);
    offenesLagerfile.read(mem,beschreiber.laenge);
    return mem;
    }
    

    oder so. nur prinzipskizze.



  • volkard schrieb:

    ich nehme mal keinen header, sondern ein indexfile der form

    img/terrein/wiese.png 0 1564
    img/terrein/pflaster.png 1564 100
    script/traktor.loa 1664 345
    

    und

    struct Beschreiber{
       int offset;
       int laenge;
    };
    ...
    

    oder so. nur prinzipskizze.

    Ich würde es so machen:

    string
    string
    string
    

    Dann würde ich die strings einlesen und beim einlesen eine Nummer verpassen. Chunks haben den Vorteil das man sie ja überspringen kann weil sie ihre eigene Länge beinhalten. Der Vorteil an der Version ist das man wenn sich der Inhalt der Datei ändert nicht alles Aktualisieren muß, sondern man einfach den string und den Chunk an den richtigen Stellen entfernt oder einfügt, man muß somit nicht bei jeder änderung des Containers für jede Datei die Offsets aktualisieren, weil das programm sich die selbst zusammen sucht.



  • Xebov schrieb:

    Ich würde es so machen:

    auch ok. war ja nur ne skizze, um die verwendung der map zu verdeutlichen.


  • Mod

    Scorcher24 schrieb:

    Warum nicht einfach ein .zip?

    so machen es die meisten spiele. that's the way to go



  • rapso schrieb:

    Scorcher24 schrieb:

    Warum nicht einfach ein .zip?

    so machen es die meisten spiele. that's the way to go

    Was ich jetzt noch gefunden habe und was ich sehr cool finde, ist PhysFS:
    http://icculus.org/pipermail/physfs/2009-March/000697.html
    Das ist ein System zum laden von Resourcen, das jeglichen Zugriff ausserhalb der eigenen Resourcen unterbindet. Wie genau weiss ich noch nicht, aber ich habs mal geladen und werd da ein wenig reinpeeken. Vllt integrier ich das sogar bei mir.. mal schauen.
    Gute Nacht.
    rya.


  • Mod

    volkard schrieb:

    es reicht doch, wenn du aus den dateinamen fortlaufende integers machst und eine lut baust, die diese integers in fileoffsets übersetzt.

    ja, und man kann auch alle variablen einfach durchnummerieren, mit nur einem namen, foo0 bis foo65535 😮

    typischer fall von sachen, die erst kurz vorm brennen gemacht werden sollten.

    ich weiss nicht bei welchen spielen du solche erfahrungen gesammelt hast, aber von allen produkten bei denen ich mitgearbeitet habe kenne ich das man bei jedem nightly-build alle resourcen so zusammengefasst hat.
    gerade so primitive dinge sollten von anfang an implementiert und getestet sein, damit man nicht am ende boese ueberraschungen erlebt. simpelstes beispiel ist gross-kleinschreibung, je nach entwicklungsplattform ist das wichtig, essentiell oder egal. baut man am ende ein archivsystem ein was anders funktioniert (weil man was fertiges nimmt) kann das einiges an zeit dauern bis man es sauber zum laufen bekommt.
    da waere es gut es schon lange getestet zu haben.

    performancetechnisch sollte das wenig ausmachen, ob du ein mapping mit hunderten von views anguckst oder hunderte von filemappings mit je einem view. gerade das nicht-ins-ram-zwingen könnte performance bringen, könnte ich mir vorstellen.

    es bringt gerade beim oeffnen von dateien sehr viel performance, da man normalerweise alles vom OS umgeht was bremsen koennte und es bringt performance beim lesen von langsamen laufwerken, weil z.b. bei zip, die kompression kleinere dateien erlaubt.

    btw. ja ich hab gelesen was du noch geschrieben hast, und das rad was du da neu erfindest ist was .zip macht, nur sagt dein erster beitrag das irgendwie anders.



  • rapso schrieb:

    btw. ja ich hab gelesen was du noch geschrieben hast, und das rad was du da neu erfindest ist was .zip macht, nur sagt dein erster beitrag das irgendwie anders.

    ich will das entzippen vom installer erledigen lassen die daten ausgepackt auf der platte leben lassen. in einem fetten file.

    das laden einer datei will ich im prinzip weg haben. zur verdeutlichung nochmal mit indexfile und datenfile getrennt.

    //indexfile und datafile komplett in den speicher gemapt
    Range<char*,char*> loadFile(u32 fileID){
       Range<u32,u32>* descriptor=theIndexFileContent[fileID];
       return makeRange(theDataFileContent+descriptor.first,theDataFileContent+descriptor.second);
    }
    

    das macht beim file-aufsuchen O(1). und verdient darüberhinaus sogar noch das prädikat 'sauschnell'. die verwaltungskosten sind bei wenigen dutzend takten anzusiedeln. fertig und schluß.
    falls geladen werden muß, muß halt geladen werden. dann kostet es was. weil die platte lahm ist. diese kosten kommen auch auf einen zu, weil das vorher teuer ausgepackte zeug in die auslagerungsdatei ausgelagert werden mußte.
    ich hab halt quasi null verwaltungskosten, während dieses einzel-datei-geanfasse beim anwender laufzeit und programmierer entwicklungszeit kostet und bei beiden nicht gerade wenig.

    abstriche habe ich gemacht, um dem fragesteller den einsteig zu erleichtern.


  • Mod

    ja, sowas 'primitives' hat man frueher gemacht, bei konsolen sogar noch bis zur letzten generation, aber mittlerweile hat sogar ein nintendo ds ein file system. flexibilitaet und qualitaetssicherung (weil man das system immer nutzt) ist wichtiger als O(1). dateien im ram mit O(log n) suchen ist nicht dramatisch, das ist sicher um den faktor 1000schneller also eine festplatte braucht bis der lesekopf den dateianfang erreicht hat.
    und wie gesagt, kompression ist wichtig fuer schnelleren dateitransfer, auch von festplatte macht das noch sinn. natuerlich ist ein memory mapped file auf das ganze archiv einfach und simpel, aber spiele haben mittlerweile locker ein paar GB an arhieven, das bekommt man in 32bit nicht mehr gemappt.

    wegen dir hab ich total den falshback*hehe*



  • naja, der Landwirtschaft-Simulator 2008 braucht 7 sekunden bis das menu kommt, 17 sekunden, bis nach auswahl des spielstandes man was machen kann. danke, rapso!

    natürlich kann ich davon ausgehen, alles auf einmal reinzumappen. 64-bit kommt ja bald. bis dahin kann man sich behelfen zu geringen kosten.
    außerdem verlange ich mitnichten, daß ALLES in dem fetten file ist. und ich gehe davon aus, daß images als *.png im fetten file liegen, also gepackt, da ist das packen des fetten files kontraproduktiv...

    und ja, ich kann den neuesten entwicklungen nicht wirklich folgen. du hast eher das ohr am draht des zeitgeistes. ich bin beim programmieren sowas von 60-er-jahre, das gehört eigentlich auf die müllkippe.



  • Also ich muß sagen wenn ich das von euch so lese dann muß ich irgendwie an 2 alte Mänenr auf der Couch denken 😃

    rapso schrieb:

    es bringt gerade beim oeffnen von dateien sehr viel performance, da man normalerweise alles vom OS umgeht was bremsen koennte und es bringt performance beim lesen von langsamen laufwerken, weil z.b. bei zip, die kompression kleinere dateien erlaubt.

    Darf ich das dann so verstehen das du die dateien im RAM auf Lager liegen lassen würdest? Oder eher das du sie lädst und sie bis die Ladevorgänge abgeschlossen sind im RAM lässt?

    volkard schrieb:

    ich will das entzippen vom installer erledigen lassen die daten ausgepackt auf der platte leben lassen. in einem fetten file.

    das laden einer datei will ich im prinzip weg haben. zur verdeutlichung nochmal mit indexfile und datenfile getrennt.

    Nur das ich das nicht Falsch verstehe du würdest die gesammte Containerdatei so wie sie ist in den RAM schieben und von da aus dann alle Operationen durchführen lassen, statt aus dem Container eizellne Dateien rauszuladen?


  • Mod

    volkard schrieb:

    naja, der Landwirtschaft-Simulator 2008 braucht 7 sekunden bis das menu kommt, 17 sekunden, bis nach auswahl des spielstandes man was machen kann. danke, rapso!

    deine aussage zeigt dass du nicht gelesen hast was ich schrieb.
    1000 dateien in einer map suchen=1ms (also suchen des offsets)
    1000 dateien auf festplatte zugreifen = 17sekunden, dabei sprech ich von einem archiv, _ohne_ OS-overhead.

    wenn jemand also ein problem mit dem menue hat, wird eine O(1) suche des DateiOffsets keinen merklichen vorteil machen. was man machen muss ist eine analyse der dateizugriffe und dann alle dateien als kontinuirlichen stream anlegen. festplatte ist ja nur der 'best case', beim laden von DVD muessen wir mit ca 250ms pro dateizugriff rechnen, bei 100 dateien sind das schon 25s. ich lade eine ganze level von einer UMD (psp) in 5s, andere spiele wie z.b. WWE (siehe link naechster post) laden minutenlang (wobei sie das laden durch mehrere "ladeschirme" unterteilen, weil man sonst nicht durch die TRC pruefung von sony kommt die nur eine begrenzte zeit zum laden erlaubt).

    und ja, ich kann den neuesten entwicklungen nicht wirklich folgen. du hast eher das ohr am draht des zeitgeistes. ich bin beim programmieren sowas von 60-er-jahre, das gehört eigentlich auf die müllkippe.

    zumindestens optimierst du an der falschen stelle, hat sicher nichts mit dem alter zu tun 😉


  • Mod

    Xebov schrieb:

    Also ich muß sagen wenn ich das von euch so lese dann muß ich irgendwie an 2 alte Mänenr auf der Couch denken 😃

    lass deine feuchten fantasieen stecken 😛

    rapso schrieb:

    es bringt gerade beim oeffnen von dateien sehr viel performance, da man normalerweise alles vom OS umgeht was bremsen koennte und es bringt performance beim lesen von langsamen laufwerken, weil z.b. bei zip, die kompression kleinere dateien erlaubt.

    Darf ich das dann so verstehen das du die dateien im RAM auf Lager liegen lassen würdest? Oder eher das du sie lädst und sie bis die Ladevorgänge abgeschlossen sind im RAM lässt?

    die tabelle mit den offsets steht im ram, die dateien auf festplatte, wobei du irgendwann, wenn du performanceprobleme hast, aufzeichnen lassen kannst welche dateien du oeffnest beim starten und diese dann in einem archiv in dieser reihenfolge ablegst, beim laden von der festplatte oder disk kannst du dann z.b. immer 8MB am stueck von deinem virtual-file-system laden lassen und arbeitest drauf bis du eine datei lesen willst die nicht mehr drinnen ist in den 8MB und laedst die naechsten.
    deswegen ist kompression auch einigermassen wichtig, die 8MB koennen gerade bei z.b. DXT texturen ploetzlich wie 32MB wirken (bei zip dateien).

    manche betriebssysteme erlauben dir auch hintergrund-streamen, sodass du waehrend du auf den 8MB arbeitest schon die naechsten 8MB laedst (da du die dateien in der richtigen reihenfolge abgelegt hast, weisst du ja dass die naechsten 8MB die richtigen sind).

    in dem zusammenhang macht es auch sinn, falls man keine speicherprobleme hat, einige dateien doppelt abzulegen, einfach damit das kontinuierliche reinladen funktioniert.

    btw: http://www.youtube.com/watch?v=Lhib8lDknBM



  • Xebov schrieb:

    Nur das ich das nicht Falsch verstehe du würdest die gesammte Containerdatei so wie sie ist in den RAM schieben und von da aus dann alle Operationen durchführen lassen, statt aus dem Container eizellne Dateien rauszuladen?

    nicht wirklich. durchs filemapping http://en.wikipedia.org/wiki/Memory-mapped_file fühlt es sich aber so an, als wäre die komplette datei im ram.


Anmelden zum Antworten