2 Stimmen

Gibt es gute Softwareentwicklungs-"Muster" für speicherintensive .net-Programme?

Grundsätzlich arbeite ich an einem Programm, das viele große Video- und Bilddateien verarbeitet, und ich habe mit der Speicherverwaltung zu kämpfen, weil ich mich noch nie mit so etwas beschäftigt habe.

Es speichert zum Beispiel all diese Bilder in einer Datenbank und lädt eine Liste von Videos, zwischen denen man dann umschalten und Bilder aus dem Video ansehen kann. Im Moment werden all diese Bilder die ganze Zeit im Speicher gehalten, was eine Menge Platz verbraucht. Ich weiß, dass ich die Bilder langsam laden kann, aber wenn man einmal hin- und hergeschaltet hat, bleiben sie alle im Speicher hängen.

Ich möchte die Vorteile der WPF-Datenbindungsfunktionalität und MVVM so weit wie möglich nutzen, aber wenn ich eine andere Architektur betrachten muss, werde ich das tun.

Ich bin auf der Suche nach allgemeinen Ratschlägen, Tipps, Links zu Artikeln oder anderen Dingen, die mir helfen könnten.

3voto

Sam Punkte 6047

Eines der Dinge, die Sie betrachten könnten, ist die Datenvirtualisierung, die in WPF standardmäßig nicht zur Verfügung gestellt wird (sie bieten stattdessen UI-Virtualisierung). Datenvirtualisierung kann sagen, "laden und binden die Daten für ein Element / Bereich von Elementen während sichtbar, dann entladen, wenn nicht sichtbar".

Hier ist ein großartiger Artikel, der eine konkrete Implementierung beschreibt, die Sie möglicherweise unverändert verwenden oder anpassen können:

http://www.codeproject.com/KB/WPF/WpfDataVirtualization.aspx

3voto

Robert Rossney Punkte 91100

Es klingt so, als ob das Hauptproblem, das Sie haben, nicht so sehr die Leistungsintensität der Anwendung ist (bei der Dinge wie Puffer mit fester Größe und statische Zuweisung helfen), sondern ihr Gesamtspeicherbedarf. Das lässt sich mit Virtualisierung in den Griff bekommen.

Mit Lazy Loading kommt man auf halbem Weg zum Ziel: Man erstellt das Objekt erst, wenn es benötigt wird. Das ist in Ordnung, aber je länger der Benutzer mit der Anwendung arbeitet und je mehr Objekte er in der Benutzeroberfläche besucht, desto mehr Objekte werden erstellt, und schließlich geht der Anwendung der Speicher aus.

Sie wollen also Objekte wegwerfen, die der Benutzer nicht mehr braucht. Herauszufinden, welche Objekte der Benutzer nicht braucht, kann ein schwieriges Problem sein, aber es kann auch so einfach sein wie die Annahme, dass der Benutzer das Objekt, das er am wenigsten benutzt hat, nicht braucht. Dazu verwenden Sie einen LRU-Cache (Least-Recently-Use-Cache).

Dies ist völlig im Einklang mit dem MVVM-Muster. In Ihrer View-Klasse machen Sie Ihren Property Getter für das Objekt mit diesem Pseudocode:

if object hasn't been loaded
    load object
add object to the LRU cache (whether you loaded it or not)
return object

Der LRU-Cache, den ich geschrieben habe führt eine einfache Warteschlange der darin enthaltenen Objekte. Wenn Sie dem Cache ein Objekt hinzufügen, wird es, wenn es noch nicht in der Warteschlange ist, nach hinten verschoben, und wenn es bereits in der Warteschlange ist, wird es nach hinten verschoben.

Wenn die Warteschlange ihre Kapazität erreicht hat, wenn Sie ein Objekt hinzufügen, wird das Objekt, das sich an der Spitze der Warteschlange befindet (d.h. dasjenige, das zuletzt verwendet wurde), entfernt und die DiscardingOldestItem Veranstaltung.

Dieses Ereignis ist die Chance des Objekts, alles, was einen Verweis auf es hält (d.h. das View-Objekt, von dem es eine Eigenschaft ist), darüber zu informieren, dass es verworfen werden muss (wahrscheinlich durch Auslösen eines eigenen Ereignisses). Der Event-Handler des View-Objekts sollte zuerst das PropertyChanged Ereignis. Wenn die Eigenschaft Getter aufgerufen wird, wenn es dies tut, gibt es eine Bindung irgendwo, die noch auf die Eigenschaft suchen, so dass es noch nicht verworfen werden sollte. (Außerdem wurde das Objekt, da der Getter aufgerufen wurde, gerade an das Ende der Warteschlange verschoben.) Andernfalls kann es weggeworfen werden.

(Beachten Sie, dass dieser kleine Tanz zu einer Endlosschleife wird, wenn mehr Objekte in der Benutzeroberfläche sichtbar sind, als der Cache aufnehmen kann, und Sie einen Stapelüberlauf erhalten).

Bei einem ausgefeilteren Ansatz würde der LRU-Cache damit beginnen, alte Elemente zu verwerfen, wenn der Speicherplatz der Anwendung knapp wird (er verwendet derzeit eine feste Kapazität). Das ist eine einfache Änderung, aber wenn Sie diese Änderung vornehmen, ist das im vorherigen Absatz beschriebene Szenario etwas, über das Sie mehr nachdenken müssen; ein sehr großes Objekt könnte dazu führen, dass die gesamte Benutzeroberfläche zusammenbricht.

1voto

Paul Sasik Punkte 76202

Es scheint, dass man Muster vermeiden sollte, um die reine Leistung zu steigern. Sie haben ihren Nutzen, verstehen Sie mich nicht falsch, aber wenn Sie versuchen, Videos mit der höchstmöglichen Leistung zu erstellen, ist das letzte, was Sie tun sollten, Abstraktionsschichten einzuführen, die dazu gedacht sind, qualitativ hochwertigeren Code zu schreiben und nicht die Anwendungsleistung zu steigern.

1voto

gingerbreadboy Punkte 7138

dieser Artikel auf informIt gibt es viele gute Informationen zu diesem Thema, obwohl es mehr um C und C++ geht.

Statisches Zuweisungsmuster: Weist Speicher im Voraus zu

Sie schlägt vor, Pool-Zuteilungsmuster: Vorabzuweisung von Pools benötigter Objekte

Puffermuster mit fester Größe: Weist Speicher in Blöcken gleicher Größe zu

Smart-Pointer-Muster: Macht Zeiger zuverlässig

Muster der Garbage Collection: Verlorener Speicher wird automatisch zurückgewonnen

Müllverdichter-Muster: Automatisches Defragmentieren und Zurückgewinnen von Speicher

0voto

Jack Ukleja Punkte 12596

"Ich weiß, dass ich die Bilder mit Verzögerung laden kann, aber wenn Sie einmal hin und her gewechselt haben hin und her geschaltet hat, bleiben sie alle im Speicher."

Das stimmt meines Erachtens nicht. Die Bilder können wie alles andere in den Müll wandern, indem alle Verweise entfernt werden. Sind Sie sicher, dass Sie nicht irgendwo einen Verweis auf sie haben? Versuchen Sie einen Speicher-Profiler wie memprofiler o ANTS um zu sehen, was passiert.

Für diejenigen, die diese Frage auf der Suche nach allgemeinen Mustern (nicht WPF) zur Reduzierung des Speichers gefunden haben, ist das berühmte (das ich noch nie verwendet gesehen habe!) Das Fliegengewichtsmuster

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X