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?
/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.
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:
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 SEEK_HOLE
, ftruncate(2)
Tags und Links c linux shared-memory mmap fallocate