Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Speicherverbrauchs Ideen für C# Applikation
jogibear9988
myCSharp.de - Member



Dabei seit:
Beiträge: 623
Herkunft: Offenau

Themenstarter:

Speicherverbrauchs Ideen für C# Applikation

beantworten | zitieren | melden

Hallo,

wir haben eine Applikation, ein Visualisierungssystem für PLCs.

Aus Performance Gründen halten wir immer alle aktuellen werte als Klasse im Speicher. Dadurch das wir Visualiserungen haben mit mehr als 1,5 Mio Variablen, haben wir einen ganz schönen Speicherverbrauch.
da ja jede Variable durch eine Klasseninstanz repräsentiert wird.

Nun bin ich am überlgen das ganze etwas zu reduzieren, dazu ein paar fragen:

- Was braucht ein leeres Feld vom Type "object" einer Klasse im Speicher? Ich würde im Moment mal auf 8 Byte tippen, oder täusche ich mich da?
- Was braucht ein Bool? Würdet Ihr es als sinnvoll erachten mehrere Bool's in eine Flags enum zu verstecken (nur zur speicheroptimierung?)
cSharp Projekte : https://github.com/jogibear9988
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.757

beantworten | zitieren | melden

Zitat von jogibear9988
- Was braucht ein leeres Feld vom Type "object" einer Klasse im Speicher? Ich würde im Moment mal auf 8 Byte tippen, oder täusche ich mich da?
4 Bytes unter x86 und 8 Bytes unter x64
Zitat von jogibear9988
- Was braucht ein Bool?
1 Byte, aber das Alignment führt zu 4 Bytes unter x86 und 8 Bytes unter x64.
Zitat von jogibear9988
Würdet Ihr es als sinnvoll erachten mehrere Bool's in eine Flags enum zu verstecken (nur zur speicheroptimierung?)
Solange die Korrektheit erfüllt wird, sind solche Dinge okay; Korrektheit darf halt nie leiden.

Für mich hört sich das Vorgehen aber nach einem wilden Rumgestochere an, was die Memory Verbesseerung betrifft.
Ich hab auch schon viele PLC Visualisierungen gesehen (und mit optimiert): immer lag es an der Software Architektur, die halt kacke war und dessen Auswirkungen unnötig Speicher gefressen hat.
Geschweige denn, dass man Basics von .NET Memory Management einfach nicht kannte.
private Nachricht | Beiträge des Benutzers
jogibear9988
myCSharp.de - Member



Dabei seit:
Beiträge: 623
Herkunft: Offenau

Themenstarter:

beantworten | zitieren | melden

Ein "Tag" braucht bei uns ca. 500 Bytes als Leeres Objekt (durch die Verschiedenen Properties die wir im Tag haben (Min/Max Value, Scripte, ...)). Das ist aber noch ohne Strings wie dem Tag Namen und der Adresse. D.h. wenn ich 1.5mio tags habe, welche im speicher sind, dann habe ich alleine dafür knapp 1GB speicher, da ich aber noch strings wie Name, Adresse und Beschreibung habe, komme ich auf ca 1.5GB.

Das ganze funktioniert ja so auch, ich überlege einfach nur was, und ob ich es reduzieren kann oder soll.

Ein Tag hat bei uns z.b. über 30 Properties wo man ihn konfigurieren kann, wie archivierung, meldung erzeugen, usw...
cSharp Projekte : https://github.com/jogibear9988
private Nachricht | Beiträge des Benutzers
jogibear9988
myCSharp.de - Member



Dabei seit:
Beiträge: 623
Herkunft: Offenau

Themenstarter:

beantworten | zitieren | melden

Hab den code genutzt um die leere objekt größe zu ermitteln: https://www.codeproject.com/Articles/1254217/Calculating-Heap-Size-of-Managed-Objects
cSharp Projekte : https://github.com/jogibear9988
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.757

beantworten | zitieren | melden

Korrekt, Basics: im Speicher hält man das, was man zwingend braucht.
Man schiebt auch nicht Dinge in die UI, die mal nicht sehen kann - zB braucht niemand eine UI Liste mit 1.5 Einträgen (als Beispiel).

Zur Größenmessung: beachte, dass Du schnell in Messfehler rutschen kannst.
Die Runtime-Größe muss nicht der Theorie entsprechen.

Beispiel: jeder Referenztyp hat mindestens 12 Bytes, die tatsächlich benötigt werden, auch wenn das Objekt nur mind. 4 Byte hat.
Hinzu kommt nämlich noch die Verwaltung des Objekts; 4 Bytes Object Header und 4 Bytes Table Pointer.
Value Types haben das nicht.

In Visual Studio gibts ein .NET Object Allocation Tracking Tool, das dir die gesamte Größe anzeigt.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.320

beantworten | zitieren | melden

Bei Wertetypen wird direkt der Wert gespeichert, bei Referenztypen wird für die Referenz (intern ein Zeiger) selber Speicher je nach Bittigkeit des Prozesses (also 32 oder 64 bit) benötigt als auch das eigentliche Objekt (+Verwaltungsdaten).
Kannst es selber mal ausprobieren anhand folgenden Codes:


using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public class C
{
}

public struct S
{
}

public class Test
{
	public static void Main()
	{
		Console.WriteLine(Marshal.SizeOf(typeof(IntPtr)));
		Console.WriteLine(Marshal.SizeOf(typeof(bool)));
		Console.WriteLine(Marshal.SizeOf(typeof(C)));
		Console.WriteLine(Marshal.SizeOf(typeof(S)));
		Console.WriteLine();
		Print();
	}
	
	static unsafe void Print()
	{
		Console.WriteLine(sizeof(IntPtr));
		Console.WriteLine(sizeof(bool));
		//Console.WriteLine(sizeof(C));
		Console.WriteLine(sizeof(S));
	}
}
sizeof kann nur die Größe von Wertetypen berechnen (daher Marshal.SizeOf für eine Klasse [mit explizitem StructLayout(LayoutKind.Sequential)-Attribut]).
Es sollte

8
4
1
1

8
1
1
herauskommen (bei 64 bit).
(der Interop-Wert für bool ist 4, aber das liegt an dem WinAPI-Datentyp BOOL, daher ist 1 Byte die .NET-Größe)
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.757

beantworten | zitieren | melden

Zitat von Th69
Bei Wertetypen wird direkt der Wert gespeichert,
.. auch nicht bei allen :-)
Ein struct mit In-Parameter wird zur Referenz.

Sustainable Code - In Param
Erklärung dazu: https://twitter.com/marcgravell/status/1520297502771142657
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.320

beantworten | zitieren | melden

Das bezieht sich aber nicht auf die Datenspeicherung [im Heap] (z.B. als Member in einer Klasse oder in einer List<T> oder Collection<T>), sondern nur für die Übergabe als Methodenparamater (d.h. auf dem Stack).
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 6.814
Herkunft: Waidring

beantworten | zitieren | melden

Hallo jogibear9988,

mach ein Speicherabbild und analysiere das. Dann siehst du genau welcher Objekt am größten ist, etc.
Das geht am einfachsten mit dem dotnet-dump Tool.

Danach kannst du überlegen wie Objekte geteilt werden, etc.
So pauschal ohne den Code zu kennen, kann ich keine konkrete Hilfe geben.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers