Wie kann MADV_ZERO implementiert oder emuliert werden?

8

Ich würde gerne in der Lage sein, einen Bereich einer Dateispeicherzuordnung auf null zu setzen, ohne irgendeinen io aufzurufen (um sequentiell riesige Dateien effizient zu überschreiben, ohne dass ein Plattenlesevorgang auftritt).

Doing std::memset(ptr, 0, length) wird dazu führen, dass Seiten von der Festplatte gelesen werden, wenn sie nicht bereits im Speicher sind, selbst wenn die gesamten Seiten überschrieben werden, wodurch die Festplattenleistung komplett verloren geht.

Ich würde gerne etwas wie madvise(ptr, length, MADV_ZERO) machen können, was den Bereich auf Null setzen würde (ähnlich wie bei FALLOC_FL_ZERO_RANGE ), um beim Zugriff auf den angegebenen Bereich anstelle von regulären io-Seitenfehlern Seitenfehler zu verursachen.

Leider MADV_ZERO existiert nicht. Auch wenn das entsprechende Flag FALLOC_FL_ZERO_RANGE in fallocate und kann mit fwrite verwendet werden, um einen ähnlichen Effekt zu erzielen, allerdings ohne sofortige Cross-Process-Kohärenz.

Eine mögliche Alternative wäre, MADV_REMOVE zu verwenden. Dies kann jedoch meines Erachtens eine Dateifragmentierung verursachen und blockiert auch andere Vorgänge während des Abschlusses, was mich hinsichtlich seiner langfristigen Leistungsauswirkungen unsicher macht. Meine Erfahrung mit Windows ist, dass die ähnliche FSCTL_SET_ZERO_DATA kann beim Aufruf erhebliche Leistungsspitzen verursachen.

Meine Frage ist, wie man MADV_ZERO für gemeinsame Zuordnungen implementieren oder emulieren kann, vorzugsweise im Benutzermodus?

1. /dev/zero/

Ich habe gelesen, dass es vorgeschlagen ist, /dev/zero einfach in den ausgewählten Bereich zu lesen Allerdings bin ich mir nicht ganz sicher, was "Lesen in den Bereich" bedeutet und wie man es macht. Ist es wie ein fread von /dev/zero in den Speicherbereich? Nicht sicher, wie dies einen regulären Seitenfehler beim Zugriff vermeiden würde?

  

Lies für Linux einfach /dev/zero in den ausgewählten Bereich. Das   Kernel optimiert diesen Fall bereits für anonyme Mappings.

     

Wenn es sich im Allgemeinen als zu schwierig erweist, es zu implementieren, kann ich es tun   vorschlagen MADV_ZERO sollte diesen Effekt haben: genau wie das Lesen von
  / dev / zero in den Bereich, aber immer effizient.

EDIT: Nach dem Thread ein bisschen weiter stellt sich heraus, dass es tatsächlich geht nicht funktionieren.

  

Es macht keine Tricks, wenn Sie mit einem geteilten Mapping zu tun haben.

2. MADV_REMOVE

Eine Vermutung, es unter Linux zu implementieren (dh nicht in einer Benutzeranwendung, was ich bevorzugen würde), könnte einfach durch Kopieren und Ändern von MADV_REMOVE erfolgen, dh madvise_remove zu verwenden FALLOC_FL_ZERO_RANGE anstelle von FALLOC_FL_PUNCH_HOLE . Allerdings bin ich ein bisschen über den Kopf, wenn ich das errate, vor allem, weil ich nicht ganz verstehe, was der Code um den vfs_allocate macht:

%Vor%     
ronag 31.08.2015, 23:56
quelle

1 Antwort

1

Sie können wahrscheinlich nicht tun, was Sie wollen (im Benutzerbereich, ohne den Kernel zu hacken). Beachten Sie, dass das Schreiben von Nullseiten aufgrund des Seitencache möglicherweise keine physische Datenträger-IO verursacht.

Sie können ein Dateisegment in einer Sparse-Datei , aber einige Dateisysteme (z. B. VFAT) haben keine Löcher oder Sparse-Dateien. Siehe lseek (2) mit SEEK_HOLE , ftruncate(2)

    
Basile Starynkevitch 01.09.2015 08:59
quelle