Thread-Save Datenverwaltung
-
Gut, hab das geändert aber leider hilft mir das bei der Geschwindigkeitsoptimierung nicht viel weiter.
-
Für bessere Performance benutze Critical Sections, das sind keine Kernel Objekte.
Simon
-
Habe gerade diesen Beitrag hier gefunden: Link
Da wird ja relativ genau auf CS und Interlock (was immer das auch ist) eingegangen.
Die Frage bleibt, ist es effektiver das ganze irgendwie über Events und einem Daten-Verwaltungs-Thread zu machen oder so wie es jetzt ist.
-
Matyr schrieb:
Die Frage bleibt, ist es effektiver das ganze irgendwie über Events und einem Daten-Verwaltungs-Thread zu machen oder so wie es jetzt ist.
Unterschiedliche Anforderungen bringen unterschiedliche Ergebnisse.
Prinzipiell ist dein Ansatz passend.
Wenn du zB in ThreadSaveData nur primitive Typen hältst ist ein InterlockedExchange() wahrscheinlich das schnellste. Das Stichwort hier wäre CAS (compare and set/swap).
Crtitcal Sections sind nicht über mehrere Prozesse Hinweg benutzbar dafür idR einen Tick schneller als Mutexes.
Die Performance spielt aber nur dann eine Rolle wenn du oft für kurze Zeit lockst. Wenn du selten für lange Zeit lockst ist es komplett egal.
Das mit den Events und Verwaltungsthread verstehe ich nicht. Kannst du erklären was da gemeint ist?
Und: Was ist das Anforderungsprofil?
-
Die Anforderungen sind sehr kurze locks in denen meist nur kleine Datenmengen gelesen oder geschrieben werden. In der Regel >=20Byte.
Ganz selten auch mehr,in etwa 1kb.
Gelockt soll wenn es performance technisch geht etwa 20 - 40mal in der Sekunde werden.Das was ich mit Verwaltungsthread meine ist ein SON (service orientatet network oder so) system.
Daher ein Thread auf den man mit events zugreift und der den anderen Threads bescheid gibt das Daten belegt werden. (Wenn ich das richtig verstanden habe)
Dadurch soll eine höhere Geschwindigkeit gewährleistet sein und vor allem viel Dynamischer.
-
Muss man eigentlich bei Lesezugriff ein Mutex bzw. CS überhaupt setzen?
Oder reicht es wenn nur abgefragt wird ob irgendwo Schreibzugriff ist?
-
wenn du nur liest, ist das ok
wenn du allerdings iwo schreibst und gleichzeitig in nem anderen thread liest, kann es sein, dass du müll liest
-
Deswegen wird beim Schreiben der Mutex gesetzt, in der lese Funktion wird einfach nur geprüft ob er gesetzt wurde, wenn ja wartet er, wenn nicht wird einfach gelesen.
Problem ist vielleicht nur das wenn das lesen länger als ein Takt dauert und dann etwas Anfängt zu schreiben...
-
Matyr schrieb:
Deswegen wird beim Schreiben der Mutex gesetzt, in der lese Funktion wird einfach nur geprüft ob er gesetzt wurde, wenn ja wartet er, wenn nicht wird einfach gelesen.
Problem ist vielleicht nur das wenn das lesen länger als ein Takt dauert und dann etwas Anfängt zu schreiben...
richtig - deshalb schrieb ich ja, dass es schief geht, wenn ein thread gerade schreibt und der andere liest... (bzw schief gehen kann - nicht muss)
-
So habe dass nun mit CriticalSection implemiert,
zusätzlich habe ich eine eigene CS programmiert (naja mit Anleitung von CodeProject) die schneller sein soll.Nun ist die Frage wie ich die Geschwindigkeiten der beiden mal messen bzw. vergleichen kann. Die Zeit zu messen wird denke ich zu ungenau. Effektiv ist wahrscheinlich ein vergleich der Rechenschritte,
nur weiß ich leider nicht wie das effektiv geht.Ist clock(); ein vernünftiger Ansatz?
-
Matyr schrieb:
Ist clock(); ein vernünftiger Ansatz?
Nö, dafür eignet sich eher QueryPerformanceCounter() (siehe MSDN).
-
So meine CS ist fertig und durchgemessen.
Zeit normalle CS: 3400
Zeit meine CS: 2000Kann aber wegen Optimierung des Compilers vielleicht falsch sein.
Initialisieren ist etwas langsamer, schätzungweise 5-10% was aber anhand der anderen Ergebnisse verkraftbar ist.Mfg. Matyr
Folgendes Messverfahren:
QueryPerformanceCounter((LARGE_INTEGER*)&count1); for(int i=0;i<30000;i++) { EnterCriticalSection(&cs); LeaveCriticalSection(&cs); } QueryPerformanceCounter((LARGE_INTEGER*)&count2); cout<<"Enter/Leave CS: "<<(count2-count1)<<endl; Sleep(50); QueryPerformanceCounter((LARGE_INTEGER*)&count1); for(int i=0;i<30000;i++) { myCs.Lock(); myCs.Unlock(); } QueryPerformanceCounter((LARGE_INTEGER*)&count2); cout<<"Enter/Leave MyCS: "<<(count2-count1)<<endl;