Wie viel freies RAM hab ich verfügbar?!?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Wie kann ich ermitteln, wie viel Speicher ich in meinem Python Programm nutzten kann, ohne das das System anfängt zu swappen?!?

Die Information könnte ich in PyHardLinkBackup verwenden, um eine zu sichernde Datei komplett in den Arbeitsspeicher zu laden, wenn sie reinpassen würde...

Aber die Info: "Wie viel RAM ohne swap" brauche ich auch noch Plattform-unabhängig...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Das lässt sich unmöglich vorhersagen, dafür sind moderne Betriebssysteme viel zu komplex. Selbst wenn du die Information hättest lässt sich nicht sagen wieviel ein Python Objekt an Speicher verbraucht, da sich dies zwischen unterschiedlichen Interpretern und Interpreterversionen unterscheidet.
BlackJack

Ich denke die Frage, beziehungsweise die eigentliche Frage lässt sich nicht so leicht beantworten denn selbst wenn diese Frage beantwortbar ist/wäre, möchte man sicher nicht das RAM „bis kurz vor swap“ belegen, denn das Betriebssystem verwendet das ja auch anderweitig um die Leistung zu erhöhen, für Puffer und Caches die dann keinen Platz mehr hätten. Und Dein Programm wird ja auch nicht das einzige sein welches läuft. Wenn es Dir darum geht das Du die Datei erst lesen willst um den Hashwert zu berechnen und dann nochmal um sie zu kopieren falls sie beim Ziel noch nicht existiert und man deshalb keinen Hardlink erstellen kann, dann würde ich `mmap` vorschlagen. Dann überlässt Du dem Betriebssystem die Entscheidung wann wie viel von der Datei tatsächlich im RAM liegt. Das Betriebssystem hat in der Regel den besseren Überblick über alle Prozesse und deren Ressourcen als der Entwickler *einer* Anwendung die mit den anderen zusammen laufen muss.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

BlackJack hat geschrieben:Wenn es Dir darum geht das Du die Datei erst lesen willst um den Hashwert zu berechnen und dann nochmal um sie zu kopieren falls sie beim Ziel noch nicht existiert und man deshalb keinen Hardlink erstellen kann, dann würde ich `mmap` vorschlagen. Dann überlässt Du dem Betriebssystem die Entscheidung wann wie viel von der Datei tatsächlich im RAM liegt.
Das hast du vollkommen richtig erfasst!

https://docs.python.org/3/library/mmap.html sieht nach dem richtigen aus. Danke!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hm... Weiß nicht ob das wirklich weiter hilft...

Denn unter Windows kann ich nicht ein mmap Aufmachen, was größer als der Hauptspeicher ist. Dann kommt:
OSError: [WinError 8] Für diesen Befehl ist nicht genügend Speicher verfügbar
Also müßte ich auch hier wissen, wie viel Speicher ist denn nutzten könnte...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hat noch jemand eine Idee?!?

Also nochmal zu den Vorgaben:

1. Ich möchte/muß den Hash-Wert von jeder Datei bestimmen (Egal ob sie doppelt ist oder nicht)
2. Ich muß mit Dateien rechnen, die nicht ins RAM passen
3. Wenn eine Datei doppelt ist, muß ich sie nicht neu auf Platte schreiben
4. Wenn sie nicht doppelt ist, dann muß sie auf Platte geschrieben werden
5. Beim Lesen/Schreiben soll ein Statusbalken aktualisiert werden

Aktuell ist es so implementiert:

1. Datei Blockweise lesen (Um Statusbalken zu aktualisieren)
2. Hash füttern (Pseudo code: sha.update(chunk) )
3. Block schreiben
4. Wenn alle Blöcke gelesen sind, kann ich ermitteln ob die Datei doppelt oder nicht ist:
4.1. Datei ist doppelt: geschriebene Datei löschen
4.2. os.link() nutzten

Also bei doppelten Dateien wird eigentlich Sinnlos auf Platte geschrieben. Zumindest dann, wenn die Datei eigentlich komplett ins RAM passen würde...

Ich sehe da nur eine Möglichkeit, wie man es besser machen kann:

1. Ich brauche die Angabe, wie viel MB ich im RAM belegen darf.
2. Datei Blockweise lesen
3. Hash füttern
4. Ich lese soviele Blöcke wie ins RAM passen
5. Passen nicht alle Blöcke ins RAM schreibe ich die ersten auf Platte
6. Sind alle Blöcke gelesen -> Hash liegt vor: Kann ich unterscheiden ob:
A. Datei ist doppelt:
A.1. Wenn schon auf Platte geschrieben: Geschriebene Datei löschen
A.2. os.link() nutzten
B. Datei ist nicht doppelt:
B.1. Alle (restlichen) Blöcke schreiben

Aber: Ich weiß ja nicht wie viel RAM zur verfügung steht, wie viel frei ist und wie viel ich nutzten sollte...

Gut, ich könnte einfach den Benutzer eine Größenangabe vornehmen... Als Standard könnte man ja 512MB nehmen oder so... Denn vermutlich sind eh 90% aller Dateien relativ klein...

Aber viel viel RAM soll ich als Vorgabe nehmen?!? Könnte es ja so versuchen:

Code: Alles auswählen

import mmap

START_LENGT = 1 * 1024 * 1024

def get_max_length(length):
    try:
        with mmap.mmap(-1, length=length) as mm:
            pass
    except OSError:
        return length/2
    return get_max_length(length*2)

length = get_max_length(START_LENGT)
print("*** %i MB" % (length/1024/1024))
Liefert unter Windows und Linux 512MB

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Ich würde da einfach erst einmal gar nichts spezielles machen sondern den simplen Weg nehmen. Nur dann kannst Du überhaupt messen ob Dein eigenes Voodoo überhaupt besser ist als das Betriebssystem. Denn letztendlich versuchst Du hier ja Cache-Mechanismen zu basteln die es im Betriebssystem bereits gibt. Wenn ich eine 100 MiB-Datei zweimal direkt nacheinander lese, dann sorgt das Betriebssystem bereits dafür das die nur einmal tatsächlich von der Festplatte kommt und das zweite mal aus dem RAM. Vorausgesetzt das genug Arbeitsspeicher für das Cachen zur Verfügung stand. Falls nicht bekommst man das selbst aber wohl kaum besser hin. Falls Du denkst das Du das doch kannst, solltest Du das messen und nicht nur vermuten und viel Zeit in Optimierungen und mehr Komplexität Deines Programms stecken ohne zu wissen ob und was das an Plus am Ende bringt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, das mache ich ja aktuell. Also den einfachsten Weg.

Quasi sowas (Zusammen gekürzter Pseudocode):

Code: Alles auswählen

with open(src_filepath, "rb") as in_file:
    with open(dst_hash_filepath, "w") as hash_file:
        with open(dst_filepath, "wb") as out_file:
            hash = hashlib.new(phlb_config.hash_name)
            while True:
                data = in_file.read(phlb_config.chunk_size)
                if not data:
                    break

                out_file.write(data)
                hash.update(data)
                process_bar.update(len(data))
            
        hash_file.write(hash.hexdigest())

if hast exist:
    os.remove(dst_filepath)
    os.link(old_backup_path, dst_filepath)
Aber wird hier nicht beim verlassen der with-Statements das ganze auf Platte geschrieben?!?
Zumindest wird dem OS das gesagt, oder?

Spätestens beim zuletzt gelesenen Daten, weiß ich ob ich die neue Datei out_file schreiben muß oder noch. Ob ich was tun kann, solange sie noch offen ist?!?
Sowas wie:

Code: Alles auswählen

out_file.seek(0)
out_file.truncate()

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Okay, vielleicht doch nicht *den* einfachsten Weg. Der einfachste Weg wäre IMHO die Datei zu lesen/hashen und danach zu entscheiden ob sie kopiert werden muss und das dann eben zu tun oder zu lassen.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

BlackJack hat geschrieben:@jens: Okay, vielleicht doch nicht *den* einfachsten Weg. Der einfachste Weg wäre IMHO die Datei zu lesen/hashen und danach zu entscheiden ob sie kopiert werden muss und das dann eben zu tun oder zu lassen.
Ja, aber das wäre ja auch doof... Denn dann würde ich im schlechtesten Fall zweimal lesen müssen... OK, vielleicht ist sie im cache. Aber vielleicht auch nicht.

Für mich wird die Quelle meist ein Netzlaufwerk sein.

Letztlich kommt es wohl darauf an, was das OS mehr in den Cache packt: Von einer Datei lesen oder schreiben...

Aber naja... Ich könnte ja einfach mal die beiden Varianten so implementieren, das man sie wahlweise nutzten kann. Dann könnte ich das mal prüfen wann und wo das eine oder das andere schneller ist.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@jens:
Eine andere Möglichkeit wäre, die Dateien in garaniert verarbeitbare Junks zu teilen und hierüber zu hashen und zu kopieren. Einen Junk kannst Du dann einfach solange im RAM halten wie nötig.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das mache ich ja jetzt schon...

Allerdings sollte ein Block nur so groß sein, das ich auf max. 1Sek. Verarbeitungszeit komme, damit es Status Updates gibt.

Dann sind wie aber auch wieder bei der Eingangsfrage: Wie viel RAM Steck im System?!?

Gut von 515MB den ich belegen darf, könnte man ja schon ausgehen...

und auch Praktisch gesehen: Wie groß sind im Schnitt die zu sichernden Dateien?
DSLR-Bilder sind ja übersichtlich... Wenn man allerdings selbst Videos aufnimmt, dann kann das schnell immer so um ein paar GBytes gehen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Ich denke damit war eher gemeint das die so klein gewählt sind das sie garantiert ins RAM passen und nicht das sie so gross gewählt sind das sie gerade noch so rein passen. Weil man da eben sehr schlecht abschätzen kann wie gross das sein sollte ohne das man es am Ende langsamer macht weil das System keinen Spielraum mehr hat effizient zu arbeiten.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das hab ich ja auch schon. Aktuell sind es 1MB die als Block verarbeitet werden... Die überlegung dabei: 1MB/s sollte man wohl vorraussetzten können, oder?

Kann man auch ändern, über eine eigene .ini Datei:
https://github.com/jedie/PyHardLinkBackup#configuration

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: am effizientesten ist es immer noch, mmap zu verwenden, und zwar mit so großen Views, wie das System halt unterstützt. Ob es besser ist, lieber 2 mal zu lesen oder einmal zu viel zu schreiben, kommt darauf an, was wahrscheinlicher ist. Helfen könnten Block-Hashes, so dass schon früher entschieden werden kann, dass die Dateien nicht identisch sind.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@jens:
Ich würde die Junks eher klein halten, vllt. bei 10MB bei heutigen Systemausstattungen. Ein Backuptask versteh ich als Hintergrunddienst, welcher das System nicht sonderlich in Mitleidenschaft ziehen sollte. Wenn das System hierfür beim Prozesskontextwechsel jedensmal Speicherseiten auslagern muss, nur weil die Junks zu groß gewählt sind, hast Du verloren.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@jens:
Eine Sache noch zu Deinen Backupambitionen (offtopic) - ich finde die Snapshotfunktion von LVMs sehr brauchbar fürs Backup, damit erhält man *einen* definierten Backupzeitpunkt (NTFS kann das auch als sog. Schattenkopien). Ohne Snapshots hast Du bei aktiven Partitionen mit Schreibaktionen den Zeitpunkt nur für eine Datei fixiert.
BlackJack

@jerch: Im Grunde ja nicht einmal nur für eine Datei wenn die während des Sicherns verändert wird.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Jupp, was die Gefahr von kaputten Daten im Sinne von inkonsistenten Dateizuständen im Backup erhöht.
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@jens
Biete doch eine Option an, mit der man die Chunksize selbst bestimmen kann. Standardwert auf 8.192KB (8 MB) oder sowas.

Oder alternativ die Pagesize des Systems abfragen und die Chunkgröße mit einem Vielfachen davon definieren.
Antworten