Frage

Ich bin eine finanzielle C # Anwendung writting, die Nachrichten aus dem Netzwerk empfangen, übersetzen sie in verschiedene Objekt entsprechend dem Nachrichtentyp und finaly die Anwendung Geschäftslogik auf sie anwenden.

Der Punkt ist, dass, nachdem die Geschäftslogik angewandt wird, ich bin sehr sicher, dass ich nie wieder diese Instanz benötigen. Anstatt für den Garbage Collector zu warten, um sie zu befreien, ich möchte ausdrücklich auf „löschen“ sie.

Gibt es eine bessere Art und Weise so in C # zu tun, soll ich einen Pool von Objekt verwende, immer den gleichen Satz von Instanz wieder zu verwenden oder gibt es eine bessere Strategie.

Das Ziel ist die Garbage Collection zu vermeiden, während ein zeitkritischen Prozesses jede CPU zu verwenden.

War es hilfreich?

Lösung

Löschen Sie sie nicht sofort. Der Aufruf der Garbage Collector für jedes Objekt ist eine schlechte Idee. Normalerweise Sie wirklich will gar nicht mit dem Garbage Collector zu verwirren und sogar zeitkritische Prozesse sind nur Bedingungen Rennen warten, um geschehen, wenn sie so empfindlich sind.

Aber wenn Sie wissen, dass Sie für Ihre Anwendung gegen leichte Lastzeiten beschäftigt haben werden, können Sie eine allgemeinere GC.Collect versuchen (), wenn Sie eine Lichtperiode erreichen Bereinigung vor der nächsten hektische Zeit zu fördern.

Andere Tipps

Schau mal hier: http://msdn.microsoft.com/en-us /library/bb384202.aspx

Sie können den Garbage Collector sagen, dass Sie im Moment kritisch, etwas zu tun sind, und es wird versuchen, nett zu dir zu sein.

Sie treffen in sich selbst - verwenden, um einen Pool von Objekten und diese Objekte wiederverwenden. Die Semantik der Anrufe auf diejenigen Objekt müssten hinter einer Fabrik Fassade versteckt werden. Sie müssen den Pool in einigen vordefinierten Art und Weise wachsen. Vielleicht doppelt so groß wie jedes Mal das Limit trifft - mit einem hohen Wasser Algorithmus oder einen festen Prozentsatz. Ich würde wirklich empfehlen Ihnen dringend, nicht GC.Collect () aufzurufen.

Wenn die Last auf Ihrem Pool niedrig genug bekommt man den Pool schrumpfen könnte, und das wird schließlich eine Garbage Collection auslösen - lassen Sie die CLR Sorge über sie

.

Der Versuch, den Garbage Collector zweites zu erraten ist in der Regel eine sehr schlechte Idee. Unter Windows ist die Garbage Collector einen Generations einer und kann als verlässlich angesehen werden als ziemlich effizient. Es gibt einige Ausnahmen von dieser Regel festgestellt - die häufigste ist das Auftreten eines einmaligen Fall, dass Sie für eine Tatsache wissen, dass viele alte Objekte verursacht haben, zu sterben - einmal Objekte Gen2 gefördert werden (die längste lebte) sie neigen dazu, zu hängen, um.

Im Fall, dass Sie erwähnen, klingen Sie, als ob Sie eine Reihe von kurzlebigen Objekten zu erzeugen - diese in Gen0 Sammlungen führen. Dies geschieht relativ häufig sowieso, und sind die effizientesten. Sie könnten sie vermeiden, indem ein wiederverwendbares Pool von Objekten mit, wenn Sie es vorziehen, aber es ist am besten, mit Sicherheit festzustellen, ob GC ein Leistungsproblem vor der Einnahme eine solche Maßnahme -. Die CLR-Profiler ist das Werkzeug, um dies zu tun

Es ist zu beachten, dass der Garbage Collector auf verschiedenen .NET-Frameworks unterscheidet - auf dem kompakten Rahmen (die auf der Xbox läuft 360 und auf mobilen Plattformen) ist es ein nicht-Generationen-GC ist und als solche müssen Sie viel mehr sein vorsichtig, was Müll Ihr Programm erzeugt.

Erzwingen einer GC.Collect () ist generell eine schlechte Idee, lassen Sie die GC tun, was er am besten kann. Es klingt wie die beste Lösung, die einen Pool von Objekten zu verwenden wäre, die Sie wachsen können, wenn notwendig -. Ich dieses Muster erfolgreich verwendet habe

Auf diese Weise kann nicht nur die Garbage Collection vermeiden, aber die regelmäßige Verrechnungskostenart auch.

Schließlich sind Sie sicher, dass die GC ein Problem verursacht? Sie sollten wahrscheinlich diese messen und beweisen, bevor Sie perf sparende Implementierung von Lösungen - Sie können sich unnötige Arbeit verursachen

"Das Ziel ist, um die Garbage Collection zu vermeiden, während ein zeitkritischen Prozesses jede CPU verwenden"

F: Wenn von zeitkritischen, Sie meinen Sie zu einem gewissen esoterischen Stück Hardware zu hören, und Sie können sich nicht leisten, den Interrupt zu verpassen?

A:. Wenn ja, dann C # nicht die Sprache zu verwenden, mögen Sie Assembler, C oder C ++ für die

F: Wenn von Zeit Kritisch, meinen Sie, während es viele Nachrichten in der Leitung sind, und Sie wollen nicht den Garbage Collector langsam Dinge im Stich lassen?

A: Wenn ja unnötig Sie sind besorgniserregend. Von den Klängen der Dinge, die Ihre Objekte sehr kurzlebig sind, bedeutet dies, die Garbage Collector sie sehr effizient recycelt werden, ohne erkennbare Verzögerung in der Leistung.

Allerdings ist der einzige Weg, um sicher zu wissen ist es zu testen, setzen Sie es über Nacht einen konstanten Strom von Test Verarbeitung von Nachrichten zu laufen, ich betäubt werden, wenn Sie Ihre Performance-Statistiken erkennen können, wenn die GC Kicks (und sogar wenn man es erkennen kann, werde ich noch mehr überrascht, wenn es wirklich wichtig ist).

Holen Sie sich ein gutes Verständnis und das Gefühl auf, wie der Garbage Collector verhält, und Sie werden verstehen, warum das, was Sie denken, hier nicht zu empfehlen. es sei denn, Sie wirklich, wie die CLR Zeit neu anordnen Objekte im Speicher viel .

verbringen

Wie intensiv ist die App? Ich schrieb eine Anwendung, die (16-Bit-Managed DirectX, 44,1 kHz, Stereo), in 8-KB-Blöcken 3 Soundkarten erfaßt und sendet 2 des 3-Streams auf einem anderen Computer über TCP / IP. Die Benutzeroberfläche macht ein Audiopegelmesser und (glatt) Scrolling Titel / Interpreten für jeden der drei Kanäle. Dies läuft auf PCs mit XP, 1,8 GHz, 512 MB, usw. Die App nutzt etwa 5% der CPU.

Ich war frei von GC-Methoden manuell aufrufen. Aber ich habe ein paar Dinge zu stimmen, die verschwenderisch waren. Ich benutzte RedGate Ameise Profiler auf den verschwenderischen Teile zu schärfen. Ein ehrfürchtiges Werkzeug!

Ich wollte einen Pool von im Voraus zugewiesenen Byte-Arrays verwenden, aber die verwaltete DX Assembly ordnet Byte-Puffer intern, kehrt dann, dass in den App. Es stellte sich heraus, dass ich nicht haben.

Wenn es absolut zeitkritisch ist, dann sollten Sie eine deterministische Plattform wie C / C ++ verwenden. Auch Aufruf GC.Collect () wird CPU-Zyklen erzeugen.

Ihre Frage beginnt mit dem Vorschlag ab, die Sie Speicher sparen wollen, aber immer von Objekten zu befreien. Dies ist eine platzkritische Optimierung. Sie müssen entscheiden, was Sie wirklich wollen, weil der GC bei der Optimierung dieser Situation besser ist als ein Mensch.

Aus dem Klang der es, wie es scheint, Sie sprechen über deterministische Finalisierung (Destruktoren in C ++), die in C # nicht existiert. Die nächste Sache, die Sie in C # finden, ist das Einweg-Muster. Grundsätzlich Sie implementieren, um den IDisposable Schnittstelle.

Das Grundmuster ist dies:

public class MyClass: IDisposable
{
    private bool _disposed;

    public void Dispose()
    {
        Dispose( true );
        GC.SuppressFinalize( this );
    }

    protected virtual void Dispose( bool disposing )
    {
        if( _disposed )    
            return;

        if( disposing )
        {
            // Dispose managed resources here
        }

        _disposed = true;
    }
}

Sie konnten eine begrenzte Anzahl von Instanzen jeden Typs in einem Pool, und wiederverwenden, die bereits mit Fällen getan. Die Größe des Pools würde auf der Menge der Nachrichten ab, die Sie verarbeiten werden.

Anstatt eine neue Instanz eines Objekts zu schaffen, jedes Mal wenn Sie eine Nachricht erhalten, warum Sie nicht wieder verwenden Objekte, die bereits verwendet wurden? Auf diese Weise werden Sie nicht gegen den Garbage Collector kämpfen und Ihr Heap-Speicher nicht fragmentiert zu werden. **

Für jeden Nachrichtentyp können Sie einen Pool erstellen, um die Instanzen zu halten, die nicht in Gebrauch sind. Jedes Mal, wenn Sie eine Netzwerk-Nachricht erhalten, schauen Sie auf den Nachrichtentyp, ziehen eine Warte Beispiel aus dem entsprechenden Pool und wenden Sie Ihre Geschäftslogik. Danach setzen Sie diese Instanz des Nachrichtenobjekts zurück in das Pool ist.

Sie werden höchstwahrscheinlich wollen „lazy load“ Ihr Pool mit Instanzen, damit Ihr Code leicht skaliert werden kann. Daher wird Ihre Pool-Klasse ermitteln muß, wenn eine Instanz null gezogen wurde und es zu füllen, bevor es aus reichend. Dann, wenn der aufrufende Code setzt es in dem Pool zurück es ist eine echte Instanz.

** „Objekt-Pooling ist ein Muster zu verwenden, dass Objekte nicht wiederverwendet werden kann als zugewiesen und freigegeben, die Heapfragmentierung sowie teure GC Verdichtungen zu vermeiden hilft.“

http://geekswithblogs.net/robp/archive/2008/08/07/speedy-c-part-2-optimizing-memory-allocations---pooling-and.aspx

In der Theorie sollte die GC nicht ausgeführt, wenn Ihre CPU stark ausgelastet sind oder wenn es wirklich braucht, um. Aber wenn Sie zu haben, können Sie nur wollen, alle Ihre Objekte im Speicher halten, vielleicht eine Singleton-Instanz, und sie nie auf reinigen, wenn Sie bereit sind. Das ist wahrscheinlich der einzige Weg, um sicherzustellen, wenn der GC läuft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top