Wie schreibt man effizient eine große Folge von NULL Bytes in eine Datei?

8

Ich habe einen Dateideskriptor fd , einen Offset und eine Länge, und ich muss länge NULL bytes von offset schreiben die Datei, die von fd beschrieben wird (Anmerkung: sie tritt nie am Ende der Datei auf).

Gibt es einen effizienten Weg dies zu tun, abgesehen davon, einen Puffer zu benutzen, der mit NULL s gefüllt ist und ihn wiederholt in eine Schleife schreibt? Die Reihenfolge von NULL s kann bis zu 16Mo gehen und ich verwende derzeit einen Puffer der Größe 512 (= ~ 30k Aufrufe an write(2) ).

    
bfontaine 07.11.2013, 15:35
quelle

5 Antworten

4

Sie könnten mmap in der Datei mit dem gewünschten Offset und Mapping in genau der erforderlichen Größe versuchen und dann einfach memset aufrufen.

EDIT: Basierend auf dem Code von @jthill, hier ist ein einfaches Beispiel, das zeigt, wie man einen Vergleich durchführt.

%Vor%

ANMERKUNGEN: mmap mag es nicht, wenn der angegebene Offset nicht ausgerichtet ist (normalerweise auf einer Seitengrenze), also ist es möglicherweise schöner, wenn Sie die Länge + Offset zuordnen und einfach vom Offset (oder alternativ, wenn Sie einen schön ausgerichteten Offset garantieren können, wird dies auch funktionieren ..)

Wie Sie sehen können, sind die Unterschiede zwischen den beiden Operationen lseek ( map + seek ) und dann write ( memset ). Ich denke, das ist ein fairer Vergleich (wenn jemand etwas reparieren will, fühlen Sie sich frei.)

Ich benutze auch MAP_SHARED und nicht MAP_PRIVATE , es gibt einen signifikanten Unterschied zwischen den beiden, letzteres ist Copy-on-Write, was viel langsamer sein kann!

Auf meinem nicht so mächtigen System bekomme ich:

%Vor%

Ich denke, dass mmap + memset schneller ist?

    
Nim 07.11.2013, 15:38
quelle
2

Wenn Sie Linux ausführen und das Dateisystem Sparse-Dateien unterstützt, könnten Sie versuchen, ein Loch in Ihre Datei zu schlagen, indem Sie fallocate(2) mit dem FALLOC_FL_PUNCH_HOLE -Flag verwenden. Ich würde erwarten, dass das schnell ist, obwohl ich es nicht getestet habe.

    
user2719058 07.11.2013 16:32
quelle
1

Unter Linux können Sie splice(2) verwenden, um Daten von /dev/zero zu kopieren.

Das ist ziemlich effizient, da die meiste Arbeit innerhalb des Kernels erledigt wird.

Andere Betriebssysteme bieten möglicherweise eine ähnliche Möglichkeit (d. h. sendfile ).

update !

Ich habe fallocate(2) vergessen, das Löcher in der Mitte einer Datei ausstanzen kann.

    
salva 07.11.2013 16:02
quelle
1

Von unten, 16M von I / O, die schlecht einmal gemacht werden, ist & gt; 20ms. Das grenzt an sich selbst an.

Mitnehmen:

  • I / O verdient Aufmerksamkeit, weil
  • eine Menge davon zu tun macht schlecht bedauerliche Verzögerungen.
  • 512-Byte-Schreibvorgänge tun weh, viel.
  • 4096-Byte-Schreibvorgänge nicht.

Offsets entweder im Speicher oder auf der Platte sind nicht so wichtig, calloc 'ing was auch immer gut tun sollte (Sie könnten es versuchen).

%Vor% %Vor% %Vor%     
jthill 07.11.2013 19:41
quelle
0

lseek() an die Position und write() ein großer Puffer einmal (oder ein kleinerer Puffer mehrmals).

    
mah 07.11.2013 15:38
quelle

Tags und Links