Laden...

Programm stürzt ab, oder rechnet und rechnet

Erstellt von sane vor einem Jahr Letzter Beitrag vor einem Jahr 887 Views
S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr
Programm stürzt ab, oder rechnet und rechnet

Hallo zsm, ich hab ein großes Problem. Ich hab ein Programm geschrieben, dass mir Performance probleme macht. wie wird in C# damit umgegangen? Mit SQL?

Anbei die Architektur zur Veranschaulichung


class Program
    {
        static void Main(string[] args)
        {
            //die folgende List wird  mit tausenden Eintraegen befuellt
            List<Explain> explains = new List<Explain>();

            //Die folgende Liste wird tausenfach durchlaufen. Solche Listen habe ich bis dato nur 2.
            //Das Programm geht mir beim durchlaufen jetzt schon in die Knie. 
            // ich braeuchte aber noch so einige, aber bevor ich das Performance Prblem nicht geloest hab,
            // find ich macht es keinen Sinn weiter zu arbeiten.
            List<Explain> statusList = explains.Where((status) => status.Status == Status.married).ToList();

            for (int i = statusList.Count - 1; i >= 0; i--)
            {
                if(true)
                {
                    statusList[i].Condition = Condition.luckyGuy;
                }
                else
                    statusList[i].Condition = Condition.whataLuckyBugger;
            }


        }
    }

    class Explain
    {
        public int Number { get; set; }
        public string Firstname { get; set; }
        public Status? Status { get; set; }
        public Condition? Condition { get; set; }
        
        public Explain(int number, string firstname, Status status)
        {
            Number = number;
            Firstname = firstname;
            Status = status;
        }
    }

    enum Status
    {
        married, divorced
    }
    enum Condition
    {
        luckyGuy, whataLuckyBugger
    }

bedanke mich im Voraus für eure Antworten.

C
55 Beiträge seit 2020
vor einem Jahr

Hallo,

Was für eine Exception bekommst du? Stackoverflow, IndexOutOfRange? Bei deinem geposteten Code Schnippsel sollte es so auf dem ersten Blick keine Performance schwierigkeiten geben bzw. ich kann keine erkennen, wenn es nur "paar tausende" Einträge, was ansich schon sehr schwammig formuliert ist, da wäre eine genaue Zahl hilfreicher genauso wie der Fehler und Stacktrace.

Daneben stellt sich für die Frage, hast du es schon mal der Foreach Schleife probiert?

Grüße

T
2.219 Beiträge seit 2008
vor einem Jahr

Der Code an sich gibt eigentlich kein erkennbares Problem wieder.
Auch kann anhand des Snippets kaum ein Performance Problem auftreten.
Das du aber tausendfach durch die Liste läuft richt nach einem falschen Ansatz.

Mir ist auch nicht klar wie ein Performance Problem in deinem C# Code mit SQL gelöst werden sollte.
Ggf. fehlt uns hier Kontext, den du erläutern solltest.

Ansonsten wäre es auch hilreich zu wissen, warum du durch die Listen laufen musst.
Suchst du hier nach Einträgen oder musst du ggf. die Einträge ändern?
Wenn diese z.B. aus einer DB kommen, dann kannst du diese mit einem Update Befehl vermutlich sinnvoller updaten als ales einzuladen durchlaufen und dann zurück zu schreiben.

@ClaraSoft
Da er die Liste rückwärts durchläuft, wäre foreach hier nicht hilfreich.
Generell nimmt sich die for/foreach Schleife nur syntaktisch was.
Unter der Haube machen beide das gleiche.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@ClaraSoft, @T-Virus, bedanke mich für eure Antworten!

Ich bekomme keine Fehlermeldungen, obwohl ich immer wieder Fehler in der Programmierung finde, was halt dann zu einem falschen Ergebnis führt.
Es macht für mich auch keinen Unterschied ob ich die Listen von vorne oder von hinten durchlaufe. Bedanke mich aber, dass ihr darauf eingegangen seit, weil ich mir schon die Frage gestellt hab, was denn nun besser wäre.

Ich hab es mir mal durhgerechnet. Aktuell ist die Liste explains mit ca. 1500 Objekten befüllt und ich durchlaufe sie 4000mal. Das führt dazu, dass die Berechnung zwar etwas dauert, aber man kann damit noch sehr gut arbeiten. Ideal wäre aber, wenn ich die Liste mit 100k Objekten befüllen könnte und diese dann 1mio mal durchlaufen könnt. Das würde aktuell dazu führen, dass entweder der Prozess nicht mehr reagiert, oder ich stunden später die Geduld verlieren würde und den Computer aus dem Fenster werfen würde😊

Ich durchlaufe die Listen überprüfe auf Conditions und verändere dann deren Wert je nach Bedingung.
Meine Gedanken, kann so etwas nicht mit grafischer Programmierung verglichen werden? Ich hab in dem Bereich überhaubt keine Ahnung. Schreibe nur, wie ich es mir vorstelle, dass es funktionieren könnte.
Wird da nicht jedem Pixel einen Wert zugewiesen und bei jeder Veränderung alles neu berechnet? Wie werden die Pixel gespeichert? Wie werden sie durchlaufen? Sie arbeiten doch auch mit Millionen an Werten die in Sekundenbruchteilen neu gerechnet werden?

Seit gnädig mit mir, weil ich hab wirklich keine Ahnung wie so etwas funktioniert.

16.807 Beiträge seit 2008
vor einem Jahr

Aktuell ist die Liste explains mit ca. 1500 Objekten befüllt und ich durchlaufe sie 4000mal.

Nich so doll. Je weniger Listen durchlauft werden müssen, desto besser. Deine Liste ist eine simple Abfrage, die aber in der Form nur auf einem Kern läuft.
Mit Hilfe von TPL kann man diese Where-Abfrage sehr einfach und effizient parallelisieren.

Von Micro-Optimierungen halt ich nun mal Abstand.

Ideal wäre aber, wenn ich die Liste mit 100k Objekten befüllen könnte und diese dann 1mio mal durchlaufen könnt.

Warum müssen 100.000 Items im Speicher gehalten werden? Warum nutzt Du nicht ein geeignetes Query mittel (eben SQL) dazu?
Datenbanken sind für sowas optimiert.

Meine Gedanken, kann so etwas nicht mit grafischer Programmierung verglichen werden?

Nein, eher nicht.

Wird da nicht jedem Pixel einen Wert zugewiesen und bei jeder Veränderung alles neu berechnet? Wie werden die Pixel gespeichert? Wie werden sie durchlaufen? Sie arbeiten doch auch mit Millionen an Werten die in Sekundenbruchteilen neu gerechnet werden?

Ist nun Deine Frage, wie Dein Code besser wird und nicht mehr abstürzt, oder wechseln wir das Thema und es geht eigentlich um Pixel?

T
2.219 Beiträge seit 2008
vor einem Jahr

Ich verstehe immer noch nicht was dein Ziel ist oder sein soll.
Es macht ohne Kontext erstmal keinen Sinn, dass du 4.000 mal durch die Liste laufen musst.
Wenn dann auch noch Berechnungen mit den einzelnen Einträgen dauern können, wirst du um Wartezeiten nicht drum herum kommen.
Man könnte diese zwar noch mit Ansätzen wie Parallel.ForEach auf möglichst alle Kerne verteilen, aber das löst dein Grundproblem nicht.

Alleine mehrfach durch die Listen zu laufen klingt schon nach einem vollig falschen Ansatz.
Im Bestfall macht man es einmal und führt dann alle Operationen in einem Rutsch aus.
Allein dadurch würde man unmengen an unnützen Iterationen und damit Zeit einsparen.
Ebenfalls würde eine Gruppierung der Listen Einträge z.B. mit Dictionary die Suche dann verkürzen.

Aber ohne Kontext kann dir niemand sagen was du hier sinnvoll als Lösung machen kannst.
Bitte liefere Informationen dazu, damit man dies überhaupt mal beurteilen kann wo der Fehler liegt in deinem Konzept liegt.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

danke @Abt, danke @T-Virus für eure Antworten,

@Abt, ich vermute auch, dass das Problem mit einer DatenBank etwas vermindert werden kann. ich hab von SQL halt noch viel weniger Ahnung wie von C#, aber wie mir auffällt kommt man nicht drum herum es zu lernen. das gleiche mit XML.

Nein, ich hab die Pixel nur angesprochen, weil ich dachte, damit vielleicht einen Vergleich herstellen zu können. Bin nicht sehr kreativ 😉

@T-Virus ich hab bewusst nur so ein Schnipsel gesendet, weil es hat ja niemand lust ein größeres Projekt zu durchforsten.

anbei ein etwas größes Schnipsel 😉

Ich speichere in der Liste ein ChartMuster, das ich durchlaufen muss, um zu sehen, ob sie etwas geändert hat. darum so viele durchgänge. ich hätte aber auch keine Ahnung wie ich das sonst lösen könnt, da ja alles in weiter Vergangenheit ist. wenn es unmittelbar wäre, wäre das alles kein Problem.

vielleicht hat ja jemand Lust kurz reinzuschauen. Nur Slowly ist relevant.

T
2.219 Beiträge seit 2008
vor einem Jahr

Und Slowly scheint Update aufzurufen, was nicht in deinem Code enthalten ist.
Auch ist gefühlt 90% des Code generiert und damit für externe Leute wie mich unbrauchbar.

Das ganze geht offensichtlich in die Richtung von Online Trading und Vergleichen von aktuellen Aktien Kursen, da die Namespaces auf NinjaTrader verweisen.
Vermutlich ist dann dein Ansatz mit dem durchlaufen der Liste schon falsch.
Du machst auch je nach Methode ein Where auf deine Listen.
Daduch kommt es unweigerlich bei großen Listen zu langen Suchzeiten.

Vermutlich wäre teilweise ein Ansatz das ganze mit Dictionary zu lösen.
Kannst du dann aber nur für einen Teil verwenden, sobald due mit Werten größer/kleiner suchen musst, funktioniert der Ansatz nicht mehr.

Link:
https://ninjatrader.com/de/

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@T-Virus danke für deine Antwort.
Was meinst du damit? Versteh ich nicht.

Und Slowly scheint Update aufzurufen, was nicht in deinem Code enthalten ist.
Auch ist gefühlt 90% des Code generiert und damit für externe Leute wie mich unbrauchbar.

muss ehrlich gestehen, dass ich mir durch die Where keine Performance einbußen erwartet hätte

Du machst auch je nach Methode ein Where auf deine Listen.
Daduch kommt es unweigerlich bei großen Listen zu langen Suchzeiten.

T
2.219 Beiträge seit 2008
vor einem Jahr

Am ende muss ja durch Where die Liste beim Materialisieren z.B. mit ToList() oder mit First/FirstOrDefault() durchlaufen werden.
Das kostet eben Zeit, hast du aber selbst schon bemerkt.

List<T> ist bei großen Listen als Container zum suchen nicht mehr praktikabel, da er alle Elemente durchlaufen muss.
Je nachdem wie man darauf sucht, muss er bei nicht gefundenen Treffern immer durch die ganze Liste laufen.
Wenn du schnell suchen willst und auch fixe Kriterien wie einen eindeutigen Key hast, dann nimm Dictionary und gruppiere damit deine Einträge.
Z.B. könntest du deine Enums als Keys verwenden und die Werte im Value als List<MyPrice> speichern.
Bei Änderungen musst du dann die Listen entsprechend bearbeiten.

Nachtrag:
Bezogen auf Update.
Die Methode wird in deinen Gettern aufgerufen und dann die Listen, Trends etc. geliefert.
Diese Methode sehe ich im Code aber nicht, weiß ich nicht was diese überhaupt macht.
Ansonsten sehe ich nur eine Stelle wo deine Preis Liste gefllt bzw. ein MyPrice Objekt hinzugefügt wird.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

M
368 Beiträge seit 2006
vor einem Jahr

Zusatz: bei graphischer Programmierung können auch passende Bibliotheken und Möglichkeiten der Grafikkarte (GPU) genutzt werden. Sinn und Zweck der (parallelen) Berechnungen wird der Rechner aber auch nicht kritisieren.

Goalkicker.com // DNC Magazine for .NET Developers // .NET Blogs zum Folgen
Software is like cathedrals: first we build them, then we pray 😉

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@T-Virus, @ M.L , dank euch für eure Antwort,

ich hab nun sehr viele Ratschläge bekommen, vieles zum einlesen.

Ich hab P-Linq schon mal eingebaut gehabt. Die Performance hat sich nicht sonderlich verbessert. Ich hab mir auch die Frage gestellt, ob dadurch auch eine verbesserung entstehen kann, weil ich so gesehen eigentlich nur das gleichzeitig abarbeiten könnte, was auf dem geleichen Preisbereich ist. Werd mal das Dict probieren.

zur Update()

NinjaTrader 8

es ist gut möglich, dass ich diese Methode zuoft aufgeführt hab. Hab mal gelesen, dass sie nur ausgeführt wird,wenn sie benötigt wird. Dann hab ich mir gedacht, rein damit 🙂)

das folgende steht in der Definition
"Forces the OnBarUpdate() method to be called so that indicator values are updated
// to the current bar. If the values are already up to date, the Update() method
// will not be run."

T
2.219 Beiträge seit 2008
vor einem Jahr

Und in der Dou steht auch dick als Note folgende:

Note: This method is only relevant in specific use cases and should only used by advanced programmers

Die Methode manuell aufrufen ist hier vermutlich auch der falsche Weg.
Da du dies in deinen Gettern machst, wird diese auch bei jedem Abrufen der Eigenschaften ausgelöst.
Dadurch tust du dir also keinen Gefallen und verbrennst durch häufige Updates dann zusätzliche Rechenzeit.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@T-Virus ich muss dich um Hilfe bitten.

ich versuche nun irgendwie deinen Ratschlag umzusetzen, hab aber keine Ahnung wie.

Du meintest, dass ich meine enums als Key verwenden sollte. So kam bei mir der Gedanke auf, dass es dann in die Richtung laufen müsste eine Art DatenBank mit Dicts aufzubauen- Dicts in einem Dict, weil ich den Key nur einmal verwenden kann. Aber wie soll ich das umsetzen? in der Beispiel, woher die Daten kommen, ist es kein Problem. ich stell mir da aber die Frage, warum ich die dicts, da in einem Dict speichern soll, wo ich sie ohnehin separat verwalten muss. So hab ich versucht eine eigene Klasse zu schreiben, die wiederverwendet werden könnte, da hab ich aber ganz einfach das problem, wie ich die Dicts in ein Dict bekomme, weil ich muss da ja eine Generische klasse erstellen und das basisDict müsste da ja Statisch sein, aber so kann ich die dicts in das Basisdict speichern. im konstruktor?

mir ist in dem zusammenhang noch ein interessantes Phänomen aufgefallen. ich hab die dics, aktuell in der Klasse beispiel erstellt und befüllt. Die listen sind aber immer noch in verwendung und wenn ich in der liste ein Enum - status verändere, dann wir dieser im dict auch verändert. Warum ist das so? Beispiel folgt!

bedanke mich für deine Hilfe, eure Hilfe!


static void Main(string[] args)
        {
            Person person;
            List<Person> people = new List<Person>();

            Dictionary<int, Person> dict = new Dictionary<int, Person>();

            person = new Person("Stefan", 41, Status.married);
            people.Add(person);
            dict.Add(1, person);

            person = new Person("Sebastina", 46, Status.divorced);
            people.Add(person);
            dict.Add(2, person);

            person = new Person("Lukas", 35, Status.married);
            people.Add(person);
            dict.Add(3, person);


            foreach(var a in people)
                Console.WriteLine("person   " + a.Firstname + "  " + a.Status);

            foreach (var a in dict)
                Console.WriteLine("dict   " + a.Value.Firstname + "  " + a.Value.Status);

            List<Person> statusQuery = people.Where((p) => p.Age > 36).ToList();
            foreach (var a in statusQuery)
            {
                if (a.Firstname == "Stefan")
                {
                    a.Status = Status.divorced;
                    Console.WriteLine("person   " + a.Firstname + "  " + a.Status);
                }
            }

            foreach (var a in dict)
                Console.WriteLine("dict   " + a.Value.Firstname + "  " + a.Value.Status);

            Console.ReadKey();
        }

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

Anbei noch die Klasse Person


class Person
    {
        public string Firstname { get; set; }
        public int Age { get; set; }

        public Status Status { get; set; }

        public Person(string firstname, int age, Status status)
        {
            Firstname = firstname;
            Age = age;
            Status = status;
        }
    }

    enum Status
    {
        divorced, married
    }

16.807 Beiträge seit 2008
vor einem Jahr

Die listen sind aber immer noch in verwendung und wenn ich in der liste ein Enum - status verändere, dann wir dieser im dict auch verändert. Warum ist das so? Beispiel folgt!

Weil Person ein Referenztyp ist.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types
Das is das Grundprinzip jedes Referenz-Objekts und jeder Klasse in C#.

T
2.219 Beiträge seit 2008
vor einem Jahr

Mein Ansatz wäre auch eine eigene Klasse anzulegen, die dann deine Daten intern verwaltet und dir eben für die Abfragen entsprechende Methoden liefert.
Du musst dann schauen ob ein einfaches Dictionary<bla, blub> reicht oder ob du ggf. als Value des Dictionary noch ein weitere Such Struktur benötigst.
Dies hängt aber davon ab wie gut deine Struktur in Schlüssel aufteilbar sind.
Wenn du z.B. wie bei Status nur fixe Werte hast, dann ist der Ansatz hilfreich.

Wenn du aber z.B. Bereiche durchsuchen musst wie Alt > 18, dann hilft der Ansatz nur bedingt.
Hier könnte man tricksen in dem man ein Dictionary mit dem Alter und der Liste der Personen in diesem Alter führt.
Dann müsste man nur die Keys > 18 suchen und kann alle Treffer in einer Liste liefern.

Bei einigen Tausenden bis Millionen Einträgen dürfte dieser Ansatz besser sein als immer wieder die komplette Liste zu durchsuchen.
Vermutlich gibt es aber auch dafür einen besseren Ansatz.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@Apt, @T-Virus danke für eure Antworten!

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

Ma, hab ich jetzt eine Ewigkeit gesucht und wo bin ich fündig geworde. natürlich hier.
anbei der Link falls es jemanden gibt der ebenso das gleiche problem hat.

Listen für Suchen optimieren

ich stelle mir aber nur ein paar Fragen, erstens musste ich, damit ich den den SubKey bekomme die folgende Methode hinzufügen. Bekomm ich da ein Problem, weil ich ja nicht auf das baseDictionary zugreife?


public bool TryGetValue(TPrimaryKey primaryKey, out TSubKey subKey)
		{
			readerWriterLock.EnterReadLock();

			try
			{
				return primaryToSubkeyMapping.TryGetValue(primaryKey, out subKey);
			}
			finally
			{
				readerWriterLock.ExitReadLock();
			}
		}

zudem stell ich mir die Frage, worin mit dem MultiKeydict ein Problem besteht, weil @Abt auf eine OutOfMemoryException hingewiesen hat.

zudem hab ich einen SW Test gemacht. hab die folgenden Dicts mit einer Schleife mit je 1mio einträge gefüllt und je den alle einträge ausgegeben und das Multikey war nur 3k millisekunden schneller. Lohnt es sich in dem Falle überhaubt das Multi zu verwenden?

static Dictionary<int, Person> my = new Dictionary<int, Person>();
static MultiKeyDictionary<int, string, int> my1 = new MultiKeyDictionary<int, string, int>();

bedanke mich für eure Antworten im Voraus

16.807 Beiträge seit 2008
vor einem Jahr

zudem stell ich mir die Frage, worin mit dem MultiKeydict ein Problem besteht, weil @Abt auf eine OutOfMemoryException hingewiesen hat.

Wenn Du den Speicher hier voll haust ist es nur eine Frage der Zeit, bis die Menge eben eine OutOfMemoryException hervorruft.
Steht ja auch im Thread, und hat der Threadsteller auch bestätigt, dass genau das passiert ist (letzter Beitrag).

Lohnt es sich in dem Falle überhaubt das Multi zu verwenden?

Wundert mich nicht, denn Du hast an für sich ja schon einen relativ direkten Zugriff.
Dein Problem ist ja auch offenbar nicht der Zugriff selbst, sondern dass Du immer und immer und immer wieder die Collection durchläufst, also eine andere Art von Compute Belastung.
Schraubst (in meinen Augen) an den völlig falschen Stellschrauben.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

danke @Abt für deine Antwort.

ich stellte die Frage auf deinen Kommentar, weil ich das nicht ganz verstehe. ist es der Arbeitsspeicher der voll ist, oder hat ein dict eine Begrenzung? ist vielleicht aktuell auch noch nicht so schlimm, wenn ich es nicht verstehe und mich zu gegebener Zeit damit näher beschäftige.

darf ich dich um deine Meinung bitten, wie du es aufbaust? Ich arbeite ebenso noch mit SharpDX. mir ist eben in den Sinn gekommen, dass ich versuchen könnte die Berechnung auf Grundlage des Bildschirms machen könnte. Vielleicht würde sich da eine Performance verbesserung ergeben.

danke im Voraus

16.807 Beiträge seit 2008
vor einem Jahr

ist es der Arbeitsspeicher der voll ist, oder hat ein dict eine Begrenzung? ist vielleicht aktuell auch noch nicht so schlimm, wenn ich es nicht verstehe und mich zu gegebener Zeit damit näher beschäftige.

  • Die Architektur (32 vs 64 Bit) hat Limits.
  • Ein Betriebssystem hat Limits.
  • Ein Prozess hat Limits.
  • Ein .NET Objekt hat Limits.
T
2.219 Beiträge seit 2008
vor einem Jahr

@sane
Ich kann dir nicht ganz folgen.
Was genau hat dein Listen/Dictionary jetzt mit SharpDX zu tun?
Wenn dein Code in dem Thread nicht für deine eigentliche Umsetzung gedacht ist, was genau machst/versucht du dann?

Bei dem verlinkten Thema gab es das OutofMemory einfach weil die Datenmenge den RAM sprengt.
Ob das in einem Fall ebenfalls ist, ist uns nicht bekannt.
Wenn du aber endlos Daten produzierst und im RAM speicherst, dann knallt es irgendwann.

Wenn du mit einem Key schon die Einträge finden kannst, dann brauchst du das MultiKeyDictionary nicht.
Ebenfalls ist dieses noch durch die Locks gegen Race Conditions abgehärtet, was einen kleinen Overhead produziert.
Wenn du nicht mehr mehreren Threads/Tasks auf dein Dictionary zu greifst, kannst du mit dem normalen Dictionary arbeiten.
Ansonsten würde ich eher das ConcurrentDictionary von .NET empfehlen.

Auch sehe ich static bei deinen Dictionaries.
Sollte eigentlich nicht nötig sein oder spielst du in der Program Klasse rum?
Im Bestfall liegt dein Code in einer eigenen Klasse die dann über Properties die Dictionaries hält.
Dann brauchst du keine static Instanzen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@Abt, @T-Virus, danke für eure Antworten.

SharpDx ist Teil des Problems, weil es ebenso resourcen verwendet. und ich die Listen/dict ebenso zum Rendern verwende.

Der Code ist eine abgespekte Version davon. Den eigentlichen Code kann ich hier nicht veröffentlichen, weil ich Geheimhaltung des Setups versprochen hab. Der Aufbau ist aber ident.

ich gehe davon aus, dass mein Rechner an seine Grenzen kommt. Weiss nicht, ob ein 3k Euro Rechner vielleicht das Programm schaffen würde. das ganze vielleicht nicht, aber sicherlich einige Tage mehr, nur hab ich nicht die Resourcen mir so ein Teil zu leisten🙂) ich muss mit durchschnittsgeräten um 1k zufrieden sein. Ich kann nur als rückmeldung geben, dass der Rechner rechnet und mir irgendwann, der Geduldsfaden reist und ich den Rechendurchlauf abbreche. macht ja auch keinen Sinn wenn es zu lange dauert, weil damit kann niemand arbeiten.

Der Hund liegt im Key begraben, weil ich keinen individuellen Key habe. bei mir ist ein Level active oder broken und das hunderte male hintereinander. hab da noch eine ganz interessante Variante im It gefunden, bring es aber nicht zustande es mit schleifen zu durchlaufen. Brauch halt noch ein bisschen.
https://softwareengineering.stackexchange.com/questions/319264/dictionary-of-dictionaries-design-in-c

ja, ich stelle sehr viel in einer Konsole nach um zu testen, ob es funktioniert.

bedanke mich, muss mal weg vom Rechner

T
2.219 Beiträge seit 2008
vor einem Jahr

Der Link von StackExchange ist im Kern das gleiche wie dein MultiKeyDictionary, einfach eine Verzweigung von Dictionaries.
Die Frage ist aber immer noch wie du die Daten ermittelst.

Für den Dictionary Ansatz hatte ich dir oben auch schon einen möglichen Ansatz gegeben, der aber nur funktionieren kann, wenn du sagst wie du die Daten ermittelst.
Nur damit kann man dir auch einen sinnvollen Vorschlag geben.

Aktuell machst du Trial and Error in der Hoffnung, dass dabei der richige Ansatz mit kommt.
Aber damit wirst du das Problem nicht lösen können bzw. kann dir dann keiner sagen ob es für deinen Zweck dann die sinnvollste Lösung hast.

Ansonsten ist auch Abts Aussage gültig, dass dein Ansatz vermutlich schon von Grund auf falsch wäre.
Aber auch hier wäre es sinnvoller zu wissen was du machen willst.

Nachtrag:
Ob dein Rechner 1K oder 10K kostet ist Wurst, wenn der Code Schrott ist.
Hier müsstest du einfach nur passend für deinen Fall die Daten optimal ermitteln und verarbeiten.
Dann braucht es auch keinen Mainframe für deinen Code 😉

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@T-Virus, danke für deine Antwort.

ich verstehe nicht ganz was du meinst in Bezug auf, dass ich euch sagen müsse, wie ich die Daten ermittle, weil schematisch ist es ident zu dem Beispiel, das ich geteilt habe. Wie ich es im Detail mache, kann ich nicht mitteilen. Wobei ich bemerken kann, dass es eh alles das gleiche ist. Dow-Theorie!

ich bin halt leider nicht besser. ich gebe mein Bestes jeden Tag etwas Neues dazu zu lernen, aber da hast du recht, es ist ein Kampf. leider hab ich das Programmieren in der Schule nicht gelernt. ich muss mir das Wissen aus Büchern, Videos, Google und Foren zusammensuchen. in der Schule könnt man vielleicht mal den Lehrer fragen. Das folgende Beispiel zeigt sehr gut, dass ich mache, ohne zu verstehen. Bin per zufall drauf gekommen, dass es funktioniert, aber kapier nicht, warum ich eine Liste in ein Property stecken sollte. Aber ist das das, was du mit dem oberen Beispiel gemeint hast?


class Person
    {
        public string Firstname { get; set; }
        public int Age { get; set; }

       public Person(string firstname, int age)
        {
            Firstname = firstname;
            Age = age;
        }
    }

    class DatenVerwalten
    {
        List<Person> listPerson = new List<Person>();

        public List<Person> ListPerson
        {
            get { return listPerson; }
            set { listPerson = value; }
        }
    }

Bedanke mich für die Antwort im Voraus!

T
2.219 Beiträge seit 2008
vor einem Jahr

Dein Code zeigt nur deine Klassen aber nicht wie du z.B. aus deiner Personen Liste die Daten suchst egal ob über Linq (Where) oder FindAll.
Die Stellen sind entscheidend um überhaupt zu wissen wie du für deine Dictionaries deine Keys bauen müsstest.

Damit kann man dann auch schauen wie man sich z.B. eine eigene Klasse anlegt, die dann die Daten z.B. jeweils in eigene Dictionaries speichert und dir für jede mögliche Abfrage eine eigene Suchmethode liefert.

Wenn du die Daten (Personen) z.B. über einen eindeutigen Key noch identifiziern kannst, wäre dies auch schon ein guter Anfang.
Damit könnte man schon einmal die Daten selbst über den Key indizieren also über ein Dictionary<Key, Person> die Liste aufteilen.
Damit wäre es schon möglich den Grundstein für die Datenverwaltung zu legen.

Für weitere Attribute kannst du dann ggf. die Liste in weitere Suchmuster aufteilen wie ganz oben den Status.
Dann nimmst du z.B. ein Dictionary<Status, List<Person>> in dem pro Status alle Personen mit dem Status abgelegt werden.
Damit kannst du dann die Liste auf einer Dimension aufteilen, wenn diese Suchen benötigt werden.

Beim Alter hatte ich dir schon weiter oben den Tipp gegeben mit einem Dictionary<int, List<Person>> und der Ermittlung über die Keys.
Daduch dürftest du schon mit einer Klasse als Container unmengen an Iterationen durch deine Suche über die Liste komplett eliminieren oder auf ein absolutes Minimum beschränken.
Noch weiter optimieren ginge dann nur wenn du immer einen eindeutigen Key pro Person bauen und suchen könntest, aber dies scheint nicht der Fall zu sein.

Anbei kannst du für deine Liste auch eine Auto Property verwenden, die du auch direkt initalisieren kannst.

Hier mal ein Beispiel, wie ich es umsetzen würde.
Ob es aber zu deinen Anforderungen passt, müsstest du prüfen und ggf. anpassen.


// Personen um Key für eindeutige Identifizierung erweitert
public class Person
{
	public int Key { get; set; }

	public string Firstname { get; set; }

	public int Age { get; set; }

	public Status Status { get; set; }
}

public enum Status
{
	Divoreced = 0,

	Married = 1
}


// Register Klasse zur Verwaltung der Personen
public class PersonRegister
{
	public PersonRegister(List<Person> persons)
	{
		Build(persons);
	}

	/// <summary>
	/// Hauptregister mit allen Personen
	/// </summary>
	public Dictionary<int, Person> MainPersons { get; } = new Dictionary<int, Person>();

	/// <summary>
	/// Register für alle Personen nach Alter gruppiert
	/// </summary>
	public Dictionary<int, List<Person>> AgePersons { get; } = new Dictionary<int, List<Person>>();

	/// <summary>
	/// Register für alle Personen nach Status gruppiert
	/// </summary>
	public Dictionary<Status, List<Person>> StatusPersons { get; } = new Dictionary<Status, List<Person>>();

	private void Build(List<Person> persons)
	{
		foreach (Person person in persons)
			AddOrUpdate(person);
	}

	/// <summary>
	/// Fügt die Person hinzu oder updatet die Daten für die Person
	/// </summary>
	/// <param name="person"></param>
	public void AddOrUpdate(Person person)
	{
		// Falls es die Person schon gibt, dann müssen wir diese vorher entfernen!
		Remove(person.Key);

		this.MainPersons.Add(person.Key, person);

		if (!this.AgePersons.TryGetValue(person.Age, out List<Person> agePersons))
		{
			agePersons = new List<Person>();
			this.AgePersons.Add(person.Age, agePersons);
		}

		agePersons.Add(person);

		if (!this.StatusPersons.TryGetValue(person.Status, out List<Person> statusPersons))
		{
			statusPersons = new List<Person>();
			this.StatusPersons.Add(person.Status, statusPersons);
		}

		statusPersons.Add(person);
	}

	/// <summary>
	/// Entfernt die Daten für die Person
	/// </summary>
	/// <param name="key"></param>
	public void Remove(int key)
	{
		// Keine Person vorhanden, dann direkt raus!
		if (!this.MainPersons.TryGetValue(key, out Person person))
			return;

		this.AgePersons[person.Age].Remove(person);
		this.StatusPersons[person.Status].Remove(person);
	}
	
	/// <summary>
	/// Sucht die Person über den Key
	/// </summary>
	/// <param name="key"></param>
	/// <returns></returns>
	public Person Find(int key)
	{
		if (this.MainPersons.TryGetValue(key, out Person person))
			return person;

		return null;
	}

	/// <summary>
	/// Sucht alle Personen ab dem Alter
	/// </summary>
	/// <param name="age"></param>
	/// <returns></returns>
	public List<Person> FindByAge(int age)
	{
		List<Person> result = new List<Person>();
		List<int> keys = this.AgePersons.Keys
			.Where(k => k >= age)
			.ToList();

		foreach(int key in keys)
			result.AddRange(this.AgePersons[key]);

		return result;
	}

	public List<Person> FindByStatus(Status status)
	{
		if (this.StatusPersons.TryGetValue(status, out List<Person> persons))
			return persons;

		return new List<Person>();
	}
}


public static void Main(string[] args)
{
	const int MaxPersons = 1_000_000;
	Random random = new Random((int)DateTime.Now.Ticks);
	List<Person> persons = new List<Person>(MaxPersons);

	for (int i = 1; i <= MaxPersons; i++)
	{
		Person person = new Person()
		{
			Key = i,
			Firstname = $"Vorname {i}",
			Age = random.Next(0, 101),
			Status = (Status)random.Next(0, 2)
		};

		persons.Add(person);
	}

	// Register erstellen und mit den Personen befüllen lassen
	PersonRegister register = new PersonRegister(persons);

	// Suche über Key
	Person firstperson = register.Find(1);

	// Suche über Alter
	List<Person> agedPersons = register.FindByAge(67);

	// Suche nach Status
	List<Person> marriedPersons = register.FindByStatus(Status.Married);
}

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

S
sane Themenstarter:in
40 Beiträge seit 2022
vor einem Jahr

@T-Virus, wow, danke recht herzlich für deine Unterstützung.

ich glaube auf Grundlage des Beispiels kann ich was bauen.

ps. ich war der ansicht, dass du dir die zip angesehen hast. muss mir überlegen welchen schlüssel ich verwende, aus dem Grund hätte mir die Multikey gut gepasst, weil ich den primaryKey mit Datetime(einzigartig) angegeben hätte, den subkey(Enum).

Wünsche einen feinen Tag!

T
2.219 Beiträge seit 2008
vor einem Jahr

Die Zip hatte ich mir angeschaut, hat aber halt auch mit deinem Beispiel mit deiner Person Klasse insgesamt 0 zu tun.
Wenn du eher mit deinen Preisen arbeitest, dann sind deine bisherigen Beispiele komplett unbrauchbar und gehen in die falsche Richtung.

Dann solltest du die nötigen Klassen auch direkt zeigen und uns auch mitteilen, wie du diese verarbeitest bzw. wie du aus den Listen die Daten suchst.
Sonst helfen wir dir nicht mit dem eigentlichen Problem sondern arbeiten an dem völlig falschen Stellen auch wenn das Listen/Dictionary Problem gleich bleibt.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.