Zum Inhalt springen

Arbeitsspeicher Freigeben


Empfohlene Beiträge

Geschrieben

Hallo.

Gibt es in C# .NET (auch .NET CF) eine andere möglichkeit außer den GarbageCollector um Arbeitsspeicher freizugeben?

Zur zeit sieht mein Code so aus:


        private void btnSave_Click(object sender, EventArgs e)

        {

            DataBase.Unit unit = new Unit();



            ..... Working Code....


            // Ram freigeben


            unit = null

            GC.Collect();


        }

Geschrieben

Außerdem sollte man den Garbage Collector nicht selber aufrufen bzw. erreicht man dazu keinerlei Vorteil.

In manchen Situationen ist es durchaus erforderlich.

Beispielsweise wenn man notgedrungen mit der Speicheradresse eines Objektes arbeiten muss und das jeweilige Objekte dann dafür Pinnen sollte, da ansonsten die Möglichkeit besteht, das der Garbage Collector das Objekt an eine andere Stelle im Speicher verschiebt und somit die Adresse ungültig wird.

Man könnte jetzt sagen. Sowas macht/braucht man im .NET nicht.

Aber die Tatsache das solche Funktionen existieren, legt nahe, dass es dafür sehrwohl einige dafür vorgesehene Situationen gibt.(Zumindest aus Sicht der Entwickler des Frameworks).

lg

Gateway

Geschrieben

Hallo,

man sollte hier GC.Collect() nicht mit einem direkten Befehl an den GC verwechseln. Mit GC.Collect() kann man den GC ausschließlich darum "bitten" es zu tun. Ob er es tut liegt nicht in unserer Hand!

Ausserdem sollte man am Objekt vor einem initialen Aufruf des GC ein .Dispose() am Objekt ausführen um das Objekt zu "zerstören" ein = null entfernt lediglich den Verweis auf das Objekt, welches aber erstmal im Speicher existent bleibt bis der GC entschieden hat ob es vernichtet wird.

So sollte der GC das nicht mehr benötigte Objekt auch direkt aus dem Speicher entsorgen.

Viele Grüße,

Thomas

Geschrieben

Okey dann drück ich mich mal anders aus:

Ich hab diverse Klassen (selbst geschrieben) und diverse normale Variablen (int, string)

Und weil ich auf einem mobilgerät schaff und nur 2 MB freien Arbeitsspeicher hab, möchte ich jede Variable die ich nicht mehr Brauch freigeben.

Das muss doch irgentwie gehen oder?

Geschrieben

Naja gut eine einzelne Variable vom Typ int zu entsorgen finde ich etwas überzogen. Die fressen kaum Speicher.

Wenn Du Deinen Klassen beibringen möchtest sich zerstören zu können (.Dispose()), kannst Du das Interface IDisposable nutzen. Die Methode des Interface implementieren und fertig.

In etwa so:


    public class MyClass[COLOR="Red"] : IDisposable[/COLOR]

    {

        int alter;

        string name;



[COLOR="red"]        #region IDisposable Member


        public void Dispose()

        {

            this.Dispose();

        }


        #endregion[/COLOR]

    }


Geschrieben
Und weil ich auf einem mobilgerät schaff und nur 2 MB freien Arbeitsspeicher hab, möchte ich jede Variable die ich nicht mehr Brauch freigeben.
Freier Speicher ist nutzloser Speicher.

Hast du einen konkreten Problemfall, oder ist das mehr ein "Bauchgefühl"?

Geschrieben
Freier Speicher ist nutzloser Speicher.

Hast du einen konkreten Problemfall, oder ist das mehr ein "Bauchgefühl"?

Leider ein konkretes Problem. Auf meinem Handy läuft TouchFlo, Windows Media Player, etc. Der Media Player startet sich leider jedes mal Neu, wenn ich eine Form öffne.

Desshalb brauch ich jedes kb an RAM.

Geschrieben

Ausserdem sollte man am Objekt vor einem initialen Aufruf des GC ein .Dispose() am Objekt ausführen um das Objekt zu "zerstören" ein = null entfernt lediglich den Verweis auf das Objekt, welches aber erstmal im Speicher existent bleibt bis der GC entschieden hat ob es vernichtet wird.

Nein sollte man nicht. Denn das einzige was du damit bewirkst ist nutzloser Arbeitsaufwand des GCs.

Sobald keine Refrenz mehr auf ein Objekt existiert kann der Speicher potenziell vom GC freigegeben werden und das ist alles was zählt. Wann der GCs das tut entscheidet er selber, spätestens tut er es aber dann wenn der Speicher auch benötigt wird.

Das heißt wenn man solche Sachen macht um Resourcen "freizugeben", verbraucht man in Wirklichkeit bei ca.99% der Fälle unötig Resourcen durch unötige durchläufe des GCs statt etwas positives zu erreichen.

Aus dem selben Grund sind auch so tolle Tools die ungenutzen Arbeitsspeicher "freigeben" total sinnlos weil das Betriebssystem das sowieso macht wenn er benötigt wird.

Geschrieben

.....

Das heißt wenn man solche Sachen macht um Resourcen "freizugeben", verbraucht man in Wirklichkeit bei ca.99% der Fälle unötig Resourcen durch unötige durchläufe des GCs statt etwas positives zu erreichen.

.....

Das heisst du findest meine Idee Schwachsinnig den Arbeitsspeicher von mir aus in meinem Programm freizugeben oder wie soll ich das sehen?

Ich hab halt folgendes Problem:

Ich arbeite mit C# .NET 3.5 (Compact Framework, ganz Wichtig) auf einem Gerät mit Gerade mal 51.11 MB RAM (Windows Mobile 6.5).

Wenn Paralell Telefoniert wird, das Bluetooth an ist, der Media Player ebenfalls und andere Applikationen habe ich Gerade mal 2 MB Arbeitsspeicher zu verfügung.

Mein größtes Problem ist: läuft meine Applikation flüssig und es ruft mich jemand an, werden alle Applikationen (von WM selbst) beendet damit das Telefonat entgegen genommen werden kann.

Beispiel: Meine Applikation läuft, Windows Media Player. Es ruft mich jemand an. Ich merk das vorerst garnicht. Zuerst wird Entweder Windows Media Player oder meine Appliaktion beendet. Und ich möchte einfach dass meine Applikation weniger Arbeitsspeicher verbraucht damit sie erst garnicht beendet werden muss.

Es ist nicht nur ein "Bauchgefühl" dass ich den Arbeitsspeicher freigebe, sondern eher ein muss damit die Applikation läuft.

Das muss doch irgentwie gehen dass ich den RAM einer Variable oder einer Instanz einer Klasse freigeben kann ohne alles auf NULL zu setzen und dann den GC aufzurufen.

By the Way: Was genau hat eig die Dispose() Methode auf sich? Im enddefekt (laut MSDN) ruft meine Dispose Methode in meiner Klasse die Dipose() Methoden der Instanzen auf:


    public void Dispose() 

    {

        Dispose(true);


        // Use SupressFinalize in case a subclass

        // of this type implements a finalizer.

        GC.SuppressFinalize(this);      

    }


    protected virtual void Dispose(bool disposing)

    {

        // If you need thread safety, use a lock around these 

        // operations, as well as in your methods that use the resource.

        if (!_disposed)

        {

            if (disposing) {

                if (_resource != null)

                    [B]_resource.Dispose();[/B]

                    Console.WriteLine("Object disposed.");

            }


            // Indicate that the instance has been disposed.

            _resource = null;

            _disposed = true;   

        }

    }


Was genau passiert dann in dieser Instanz? Ich versteh das nicht so ganz. Alle rufen einfach nur Dispose auf und es Passiert nichts? Was mach ich wenn ich ein Int Array mit 1000 werten habe? Da gibt es kein Dispose.

Geschrieben
Und ich möchte einfach dass meine Applikation weniger Arbeitsspeicher verbraucht damit sie erst garnicht beendet werden muss.

Es ist nicht nur ein "Bauchgefühl" dass ich den Arbeitsspeicher freigebe, sondern eher ein muss damit die Applikation läuft.

Deine Vorgehensweise beruht aber auf der Vermutung, dass der GC nicht sowieso schon alles unternimmt, um Speicher zu sparen, bevor der Speicher zu Ende geht.

Das muss doch irgentwie gehen dass ich den RAM einer Variable oder einer Instanz einer Klasse freigeben kann ohne alles auf NULL zu setzen und dann den GC aufzurufen.
Hast du wirklich geprüft, ob dieses GC.Collect überhaupt einen positiven Effekt auf dein Programm hat?

Du solltest vielleicht eher dein Programm so ändern, dass es von vornherein weniger Speicher reserviert.

Alle rufen einfach nur Dispose auf und es Passiert nichts? Was mach ich wenn ich ein Int Array mit 1000 werten habe? Da gibt es kein Dispose.
Dispose ist dann sinnvoll, wenn du unmanaged-Ressourcen verwaltest.
Geschrieben

Hier gibts 2 Artikel die einen guten Überblick geben:

An Overview of the .Net Compact Framework Garbage Collector - Steven Pratschner's .Net CF WebLog - Site Home - MSDN Blogs

Simon Hart: Memory management on Windows Mobile <= 6.1

Mit 2MB Arbeitsspeicher bist du anscheinend sowieso schon an der Grenze wo das System versucht aufzuräumen so das sich zwangsläufig etwas beenden muss.

Geschrieben

Hallo

Ich hatte schon manchmal die Situation, dass ein GC.Collect() mir Vorteile eingebracht hat.

Bei mir wars verbunden mit einem StreamReader und einem StreamWriter. Wollte schnell hintereinander schreiben und lesen und schreiben und........

Ein GC.Collect() alleine hat bei mir aber nicht gereicht.

Es musste noch zusätzlich ein GC.WaitforCollectionFinished() (oder so ähnlich heißt die funktion).

Geschrieben

nur mal so in die Runde geworfen ...

Wie sieht's denn mit der using-Anweisung aus, die nach dem Verlassen des Blocks schnellstmöglich, darin enthaltene Objekte zerstört? Vielleicht kannst Du dadurch schon einiges an Platz sparen:]

Geschrieben

Es ist durchaus manchmal vorteilhaft den GC manuell anzustoßen. Auch wenn viele der Meinung zu sein scheinen, dass der Mechanismus des GC "gottgegeben genial" ist.

Er arbeitet zugegebener Weise recht gut. Sind Ressourcen allerdings sehr knapp kann es sehr wohl einen Vorteil bieten den GC per Hand zu bemühen.

Der GC ist ein Dienst mit sehr niedriger Priorität, was bedeutet dass dieser natürlich nur dann seinen Dienst aufnimmt wenn genügend CPU-Zeit zur Verfügung steht oder die Ressourcen sehr kritisch werden.

Der GC speichert Informationen zu allen referenzlosen Objekten der 0´ten (nullten) Generation. Ohne ein explizites .Dispose() (und .SuppressFinalize...) am Objekt wird der GC dieses Object an den Finalizer übergeben. Dieser wird wiederum in einem nächsten Zyklus (also schon 2) die Finalize-Methode aufrufen.

Wenn jetzt z.B. die CPU-Zeit wieder knapp werden sollte wird der GC seine Arbeit wieder einstellen und keine weiteren Generationen von Objekten mehr bearbeiten und sie werden im Speicher weiterleben.

Im übrigen nutzen wir das "ALLE" jeden Tag in unserem Code!

using (SqlCommand cmd = new SqlCommand(...))

{

   // Code...

}

Um einen "using"-Block nutzen zu können muss das dort instanzierte Objekt IDisposable implementieren!

Bei der schließenden Klammer wird dann intern explizit die Methode ... .Dispose() aufgerufen.

Man sollte das manuelle anstoßen des GC nur gezielt einsetzen, das ist korrekt. Wenn eine manuelle Optimierung der Speicherressourcen aber nötig ist kann man dies auch guten Gewissens tun.

Kleiner Ausschnitt aus dem MSDN:

Eine Dispose-Methode sollte die SuppressFinalize-Methode für das Objekt aufrufen, das es freigibt.Wenn sich das Objekt gegenwärtig in der Finalisierungswarteschlange befindet, verhindert SuppressFinalize, dass dessen Finalize-Methode aufgerufen wird.Beachten Sie, dass das Ausführen einer Finalize-Methode hohen Leistungsaufwand erfordert.Wenn Sie das Objekt bereits mit der Dispose-Methode bereinigt haben, muss die Finalize-Methode des Objekts nicht mehr vom Garbage Collector aufgerufen werden.

Gruß,

Thomas

Geschrieben

Der GC ist ein Dienst mit sehr niedriger Priorität, was bedeutet dass dieser natürlich nur dann seinen Dienst aufnimmt wenn genügend CPU-Zeit zur Verfügung steht oder die Ressourcen sehr kritisch werden.

Und was davon ist jetzt wie ein Argument dafür den selber nochmal anzustoßen? :confused:

System ist in der Lage den Dienst laufen zu lassen -> er läuft

System ist nicht in der Lage ihn laufen zu lassen -> er läuft nicht

System hat zu wenig Resourcen -> er läuft

System hat genügend Resourcen -> er läuft nicht

Was willst du da in deinem Programm besser entscheiden?

Geschrieben

Zum Beispiel um mehr Arbeitsspeicher für Anwendungen frei zu geben.

Wie auch der SQL Server nutzen manche Anwendungen so viel Arbeitsspeicher wie zur Verfügung steht, geben diesen aber sofort frei wenn andere Anwendungen ihn benötigen.

Beispiel SQl Server...

Es ist genügend RAM für alle Anwendungen frei, was heißt der GC läuft nur los wenn er es gerade für richtig hält und genügend CPU-Zeit verfügbar ist. Der Speicher den ich nun mit meinen Objekten belege, die eigentlich entsorgt werden könnten, bleibt belegt und der SQL Server kann ihn nichts nutzen, was dazu führt, dass er nicht so viele Daten in den Speicher laden kann wie er gerne würde und immer wieder auf die Platte zugreifen muss um Abfragen bedienen zu können. Das hat zur Folge das der SQL Server "langsamer" wird obwohl eigentlich mehr Speicher (den ich mit meinen entsorgbaren Objekten belege) zur Verfügung stehen könnte.

Der GC wird keine Speicherknappheit erkennen, da der SQL Server nicht mehr Speicher anfordert und eben nur den nutzt der auch zur Verfügung steht.

Habe ich nun eine Anwendung geschrieben die auch noch hohe CPU-Zeit erfordert, was den GC-Durchlauf zeitlich erstmal weiter nach hinten schiebt, wird der SQL Server immer mehr Speicher frei geben um Platz für meinen Objekte-Friedhof zu machen. Irgendwann wird der GC dann greifen, aber bis dahin geht die Performance vom SQL Server oder einer anderen Anwendung erstmal runter.

Das ist denke ich ein guter Grund den GC durchaus mal von Hand zu bemühen.

Natürlich, wie gesagt immer gezielt.

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...