Zum Inhalt springen

Speicherleck im .Net?


NancyG

Empfohlene Beiträge

Das ist klar? Du scheinst mir eine Kristallkugel in der Tasche zu haben ;)

Natürlich nicht. Wenn wir aber die Lösung(! ;) ) anschauen, haben wir im Thread mindestens zwei Teile:

- Das Sammeln von irgendwelchen Daten (wie auch immer, das weiß nur der TE)

- Das Speichern von Daten

Ich zumindest würde erst einmal überprüfen, welcher Teil das Thread-Problem verursacht. Wenn es der erstere ist, muss man an dieser Stelle optimieren. Wenn es im letzteren liegt, wäre mein obriger Vorschlag eine Möglichkeit, das Thread-Problem zu beheben.

Meine Kristallkugel sagt mir, dass es immer problematisch ist, zig Verbindungen zu einer DB aufzubauen (dabei könnte man auch eine Instanz einer Verbindung nutzen). Genauso problematisch ist es, eine Textdatei zig mal zu öffnen und zu schreiben, ohne zu wissen, ob noch andere Prozesse die Datei zum Schreiben geöffnet haben. Mit der TCP-Verbindung ist es genauso, was ist, wenn der Ping (warum auch immer) mal höher als 250ms ist... Also laut meiner Kristallkugel ist das gesamte Vorhaben, so wie es jetzt umgesetzt ist, sowieso kritisch einzustufen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich möchte auch was sehen, wenn ich es im VS-Debugger laufen habe.

Sonst soll eben aller 50ms ein Thread erstellt werden.. und im Thread eben aller 100ms i iteriert werden.

Das ist ein Test - um das verhalten nach zuschauen. Hat nichts mit der eigentlichen Anwendung zu tun.

Sorry, wenn das eben nicht so herüber kam.

vG Nancy

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich zumindest würde erst einmal überprüfen, welcher Teil das Thread-Problem verursacht.

Das Erstellen des Threads selbst verursacht das Speicher-Leck.

Meine Kristallkugel sagt mir, dass es immer problematisch ist, zig Verbindungen zu einer DB aufzubauen (dabei könnte man auch eine Instanz einer Verbindung nutzen). Genauso problematisch ist es, eine Textdatei zig mal zu öffnen und zu schreiben, ohne zu wissen, ob noch andere Prozesse die Datei zum Schreiben geöffnet haben. Mit der TCP-Verbindung ist es genauso, was ist, wenn der Ping (warum auch immer) mal höher als 250ms ist... Also laut meiner Kristallkugel ist das gesamte Vorhaben, so wie es jetzt umgesetzt ist, sowieso kritisch einzustufen.

Mutex!

Das Verbindungsobjekt, bzw der Stream ist immer offen und wird nur im Thread beschrieben.

Mutex WaitOne/ReleaseMutex verhindern dass eben 2 Threads gleichzeitig drauf schreiben. Wie ich oben aber schon sagte - das Problem ist nicht die Geschwindigkeit, die Daten wegzuschreiben. Sondern, dass eben jeder neu erstellte Thread Speicher verbraucht und diesen nicht wieder frei gibt.

vG Nancy

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe es mit ThreadPoll versucht - und es bleibt das selbe Phänomen. Es starten x Threads, Handels werden erstellt, Speicher wird alloziert. Nach beenden der Threads bleiben die Handles einfach offen - und damit auch der Speicher belegt.

Was heißt "nach Beenden der Threads"? Der Threadpool beendet seine Threads gar nicht (zumindest nicht alle). Er lässt sie weiterlaufen, damit er für zukünftige Aufgaben keine neuen starten muss. Das ist ja der Trick an der Sache.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Bei 1,8GB RAM hat sich das Programm (ohne DEV-Umgebung) mit der Fehlermeldung "APPCRASH" verabschiedet. Lief bis vorgestern.

Ich werde es nochmal im Debugger laufen lassen.

Das "richtige" Programm, welches Streams und Datenbanken nutzt? Oder das TestProgramm. Was passiert, wenn bei parallel laufen würden?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wieso soll es nicht stimmen.

Ich habe die Aussage an Hand von einer Test-App nachvollzogen.

Du unterstellst hier einfach Sachen - ohne wahrscheinlich selber den Test gemacht zu haben.

Deine Aussage: "Der Speicher wird beim Beenden der App freigegeben", stimmt zwar - aber bringt mir nichts.

Und: Was das Programm sonst noch so macht: Genau das, was es soll!

Ohne die Threads zu erzeugen - wird kein Speicher verbraten. Aller 250ms bekomme ich ein Callback mit den Daten, die ich dann eben nicht verarbeite.

Ja: ich habe auch schon die Threads erstellt, ohne die Daten zu verarbeiten. Selbiges Problem.

Sorry, aber ich habe die Frage ja nicht aus langer Weile gestellt, ob jemanden das Phänomen bekannt ist:

Das durch erstellen von Threads Speicher verloren geht.

vG Nancy

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wieso soll es nicht stimmen.

Ich habe die Aussage an Hand von einer Test-App nachvollzogen.

Du unterstellst hier einfach Sachen - ohne wahrscheinlich selber den Test gemacht zu haben.

Weil das Unsinn ist.


class Program
{
static void Main(string[] args)
{
int i=1;
while (true)
{
Thread t = new Thread(DoSomething);
t.Start();
Thread.Sleep(50);
Console.WriteLine("{0}", i++);
}
}

static void DoSomething()
{
Thread.Sleep(100);
}
}
[/PHP]

Das kannst du den ganzen Tag lang laufen lassen ohne das dir der Speicher voll läuft oder überhaupt der Speicherverbrauch wächst.

Und: Was das Programm sonst noch so macht: Genau das, was es soll!

Ohne die Threads zu erzeugen - wird kein Speicher verbraten. Aller 250ms bekomme ich ein Callback mit den Daten, die ich dann eben nicht verarbeite.

Ja: ich habe auch schon die Threads erstellt, ohne die Daten zu verarbeiten. Selbiges Problem.

Sorry, aber ich habe die Frage ja nicht aus langer Weile gestellt, ob jemanden das Phänomen bekannt ist:

Das durch erstellen von Threads Speicher verloren geht.

Natürlich liegen deine Probleme nicht daran das du irgendwas falsch machst sondern an einem riesen Fehler in .Net der sonst noch nie jemandem aufgefallen ist... :upps

Link zu diesem Kommentar
Auf anderen Seiten teilen

Und auch laufen lassen.

Nein, natürlich nicht! Denn sonst hättest du gesehen, dass dein Speicher von ca. 13000Kb innerhalb von einer Minute auf 18000kb anwächst - siehe Bild. Im Bild ist grün eingekreist die offenen Handles - die eben nicht mehr geschlossen werden.....

Und wenn ich das den ganzen Tag mache - sehe ich sehr wohl, dass der Speicher zur Neige geht.


Sub Main()

    Dim i As UInt32 = 1

    While True

        Dim t As New Threading.Thread(AddressOf doSomething)

        t.Start()

        Threading.Thread.Sleep(50)

        Console.WriteLine("{0}", i)

        i += 1

    End While

End Sub


Private Sub doSomething()

    Threading.Thread.Sleep(100)

End Sub

Und zumindest ist es bei mir so - und wenn du an dem Code nichts falsches siehst - dann bleibt für mich nur die Erkenntnis:

Bei jedem Thread geht Speicher verloren. Wo und wie weiss ich nicht - deswgen farge ich ja hier.

post-83586-14430449638756_thumb.png

Link zu diesem Kommentar
Auf anderen Seiten teilen

Und auch laufen lassen.

Nein, natürlich nicht! Denn sonst hättest du gesehen, dass dein Speicher von ca. 13000Kb innerhalb von einer Minute auf 18000kb anwächst - siehe Bild. Im Bild ist grün eingekreist die offenen Handles - die eben nicht mehr geschlossen werden.....

Da ich mich zu sehr zusammen reißen muss dir vernünftig zu antworten ist das mein letzter Post hier.

Natürlich geht der Speicher erstmal etwas hoch, da der GC wie bereits mehrmals gesagt wurde, nicht sofort hinter dir herräumt weil das viel zu ineffizient wäre.

Deshalb geht der Speicherverbrauch erstmal ein paar kb hoch und es werden ein paar hundert Handels geöffnet bevor man im Taskmanager sehen kann wie alles wieder auf den Ursprungszustand zurück geht, oder manchmal auch nur wieder etwas weiter runter geht und dann bei einem späteren Aufräumvorgang wieder ganz runter.

Wenn das bei dir in nicht alle paar Sekunden sondern vielleicht nur alle paar Minuten passiert dann liegt das evtl. daran das dein System durch was anderes zu sehr ausgelastet ist, oder vielleicht allgemein schwächer ist. Es bleibt aber dabei der der GC das wieder aufräumt, zumindest in diesem einfachen Beispiel.

Wenn etwas wirklich nicht wieder aufgeräumt wird dann liegt das wie auch schon mehrmals gesagt wurde entweder an Designfehlern oder daran das manuell unmanged Resourcen allokiert wurden und nicht wieder freigegeben wurden.

Link zu diesem Kommentar
Auf anderen Seiten teilen


Sub Main()
Dim i As UInt32 = 1
While True
Dim t As New Threading.Thread(AddressOf doSomething)
t.Start()
Threading.Thread.Sleep(50)
Console.WriteLine("{0}", i)
i += 1
End While
End Sub

Private Sub doSomething()
Threading.Thread.Sleep(100)
End Sub
[/code]

Dieses Programm steigt bei mir nicht über 2500 K Speicher und 800 Handles.

Welches Visual Studio benutzt du, welches .NET-Framework?

Link zu diesem Kommentar
Auf anderen Seiten teilen

im wesentlichen ziehst du damit eine isolierte debugging umgebung hoch.

Was bedeutet ist überall drin? implementierst du es ordentlich? Und wird Dispose auch aufgerufen? Rufst du irgendwelchen COM / Win32 Kram auf, der nicht sauber wieder freigegeben wird?

Was macht dein Tool überhaupt?

Im übrigen: was Klotzkopp sagt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hier zwei Möglichkeiten, die funktionieren sollten.


    Sub Main()


        Dim i As UInt32 = 1

        Dim auoResetEvent As AutoResetEvent = New AutoResetEvent(False)


        While (True)


            'Dim task As Task = task.Factory.StartNew(AddressOf DoSomething)

            'task.Wait()


            ' oder


            ThreadPool.QueueUserWorkItem(AddressOf DoSomething, auoResetEvent)

            auoResetEvent.WaitOne()


            Console.WriteLine("Es läuft...{0}", i)


            i += 1


        End While

    End Sub


    ' ThreadPool

    Sub DoSomething(ByVal stateInfo As Object)


        Console.WriteLine(Thread.CurrentThread.ManagedThreadId)


        Thread.Sleep(100)


        CType(stateInfo, AutoResetEvent).Set()


    End Sub


    ' Task

    Sub DoSomething()


        Console.WriteLine(Thread.CurrentThread.ManagedThreadId)


        Thread.Sleep(100)


    End Sub

Link zu diesem Kommentar
Auf anderen Seiten teilen

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...