Autor |
Beitrag |
Martin W
Beiträge: 116
|
Verfasst: Mo 25.10.04 17:51
Also ich hab gerade folgendes Problem...
Kurze Erklärung: Ich habe unterschiedliche Ereignisse die zu unterschiedlichen Zeiten aufgerufen werden müssen. Der Sinn der da hinter steckt ist folgender: In einem Spiel kann der User z.B. ein Gebäude bauen. Da das Gebäude Zeit braucht bis es fertig ist, brauche ich einen Timer, der mir sagt "das Gebäude x ist jetzt fertig". Und von solchen Ereignissen die zu einer Zeit x initiert werden und zu einer Zeit x gestartet werden müssen habe ich bis zu 180'000 Stück.
Geplant habe ich das ganze folgendermaßen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| type timer_execute_functions = record ID_der_zu_startenden Funktion: integer; Parameter_a: string; Parameter_b: string; Parameter_c: string; Parameter_d: string; Parameter_e: string; Endtime: integer; end;
var currenttimerpostion: integer = 0; aktionen: array of timer_execute_functions; |
Ein Timer erhöht den Wert currenttimerpostion jede Sekunde um 1.
Anwendungsbeispiel:
Der User klickt auf einen Button, ab jetzt soll ein Gebäude in 500 Sekunden fertig sein. Das Array "aktionen" wird um 1 verlängert, die Werte werden ins Array geschrieben. Der Wert Endtime wird wie folgt berechnet: currenttimerpostion + 500.
Der Timer überprüft nun jede Sekunde nachdem es den Wert currenttimerpostion um 1 erhöht hat ob der Wert currenttimerpostion irgendeinem Wert Endtime entspricht. Wenn ja, wird das dazugehörige Ereigniss ausgeführt.
Allerdings funktioniert das bei 180'000 verschiedenen Records im Array nicht mehr richtig, da der PC es nicht schafft innerhalt einer Sekunde 180'000 Variablen zu überprüfen.
Wie kann ich das ganze optimieren??? Wenn ihr fragen habt, dann postet bitte!!!
|
|
jasocul
Beiträge: 6388
Erhaltene Danke: 146
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mo 25.10.04 18:59
Vielleicht gehtst du den falschen Weg. Wenn du versuchst das ganze mit Threads zu lösen, kannst du im Thread die Variablen setzen.
Ich kann dir aber auch nicht sagen, wie ein Programm auf 180.000 Threads reagiert.
|
|
.Chef
Beiträge: 1112
|
Verfasst: Mo 25.10.04 19:24
jasocul hat folgendes geschrieben: | Ich kann dir aber auch nicht sagen, wie ein Programm auf 180.000 Threads reagiert. |
Ähm ... gar nicht?
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
jasocul
Beiträge: 6388
Erhaltene Danke: 146
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mo 25.10.04 19:54
Hast du es ausprobiert?
|
|
.Chef
Beiträge: 1112
|
Verfasst: Mo 25.10.04 19:57
War ein Gedankenexperiment.
_________________ Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
|
|
jasocul
Beiträge: 6388
Erhaltene Danke: 146
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mo 25.10.04 20:04
War meine Ironie also nicht deutlich genug. Mist.
Nochmal:
Ob nun 180.000 Timer (im Sekundentakt) oder Threads ist mehr oder weniger egal. Es ist in beiden Fällen definitiv zuviel. Du solltest das Konzept deines Programms überdenken.
Ein Freund hat ein Programm geschrieben, dass einige Hundert Threads benutzt. Das ist dann aber auch schon eine heiße Maschine, damit das überhaupt einigermaßen läuft.
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 25.10.04 20:05
Wieso gar nicht??? Ich glaub mal eher, der Thread Manager wird, wenn er nicht grad vorher mit ner Fehlermeldung "Ungenügende Ressourcen" mit 80% Kernel-Zeiten arbeiten Für'n Spiel also genau das Richtige, um Verzögerung zu produzieren. Dann bräuchte er in jedem Thread nur ein Sleep positionieren von einer ms und kriegt gleich seine 500 Sekunden Bauzeit
Naja, würd das eher über einen Hintergrund-Thread machen, der das Array nach Ereignissen absucht und jeweils fällige Objekte an einen Event-Handler übergibt.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
AndyB
Beiträge: 1173
Erhaltene Danke: 14
RAD Studio XE2
|
Verfasst: Mo 25.10.04 20:13
BenBE hat folgendes geschrieben: | Naja, würd das eher über einen Hintergrund-Thread machen, der das Array nach Ereignissen absucht und jeweils fällige Objekte an einen Event-Handler übergibt. |
Das wäre wohl die idealste Lösung.
_________________ Ist Zeit wirklich Geld?
|
|
jasocul
Beiträge: 6388
Erhaltene Danke: 146
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mo 25.10.04 20:27
Der Ansatz ist vermutlich der beste bisher. Aber ob damit auch 180.000 Objekte gut verwaltet werden können?
Schaun wir mal, was Martin dazu meint.
|
|
blackbirdXXX
Beiträge: 1077
Erhaltene Danke: 1
Ubuntu Dapper
|
Verfasst: Mo 25.10.04 21:05
Ähh.
Anderer Weg.
Ein Timer, der auf 2000ms (oder 1000ms) eingestellt ist, und 180.000 Variablen überprüft?
Dürfte etwas besser sein, als 180.000 Timer laufen zu lassen.
_________________ Klein, schwarz und ärgert Techniker? Jumper!
|
|
Martin W
Beiträge: 116
|
Verfasst: Di 26.10.04 14:04
blackbirdXXX hat folgendes geschrieben: | Ähh.
Anderer Weg.
Ein Timer, der auf 2000ms (oder 1000ms) eingestellt ist, und 180.000 Variablen überprüft?
Dürfte etwas besser sein, als 180.000 Timer laufen zu lassen. |
Sehr gut, die Idee hatte ich auch schon Die Überschrift war nur Sinngemäß gemeint!!!
Ein Timer, der auf 2000ms (oder 1000ms) eingestellt ist, und 180.000 Variablen überprüft. Genau so habe ich mir das auch gedacht.
Ich habe im Anfangsthread das ganze genau so versucht zu erklären!!! Die Überschrift war nur Sinngemäß gemeint.
Meine Idee war so:
EINE Variable
Delphi-Quelltext
EIN Record
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| type timer_execute_functions = record ID_der_zu_startenden Funktion: integer; Parameter_a: string; Parameter_b: string; Parameter_c: string; Parameter_d: string; Parameter_e: string; Endtime: integer; end; |
EIN Array
Delphi-Quelltext 1:
| aktionen: array of timer_execute_functions; |
EIN Timer der jede Sekunde folgendes macht
Delphi-Quelltext
EINE Funtion, die sich in einem Thread befindet
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| function checkfunc: boolean; var k: integer; begin for k := 0 to 179999 do begin if aktionen[k].Endtime > i then begin exe_befehl(aktion[k].ID_der_zu_startenden Funktion (..und parameter)); end; end; end; |
Hat jemande einen Bessern Vorschlag???
Gruß
Martin
Ach und danke für alle eure Vorschläge bis jetzt!!!
|
|
NeWsOfTzzz
Beiträge: 233
D4 Prof
|
Verfasst: Di 26.10.04 14:32
Doch einen Vorschlag hätte ich... Du machst ein objekt
type
TTrigger=class
public
count;
start[1..100];
end;
das du sagen wir mal mit 600 erstellst
var
Triggers[1..600]:TTrigger;
oncreate()
for x:=1 to 600
Triggers[x]:=TTrigger.create;
trigger[1] entspricht jetzt was du in der nächsten sekunde machen willst, trigger[600] was du in 10 minuten machen willst.
Jetzt wenn Timer ausgeführt wird:
for x:=1 to Triggers[1].count do
start(Triggers[1].start[x]);
Und wenn jetzt ein start in 500 sekunden erfolgen soll dann:
inc(Triggers[500].count);
triggers[500].start[triggers[500].count]:= ...was auch immer gestartet werden soll..
und dann evtl noch jede Minute das Triggers array um 60 aufrücken lassen..
|
|
Martin W
Beiträge: 116
|
Verfasst: Di 26.10.04 20:33
Geht leider nicht, es kann sein, das um z.B. 16:14:18 Uhr mehrere Befehle gleichzeitig ausgeführt werden müssen...
Gibt es noch Vorschläge zur optimierung des Codes??? Auch ein "ist perfekt so" als Antwort wäre sehr nett...
Gruß
martin
|
|
NeWsOfTzzz
Beiträge: 233
D4 Prof
|
Verfasst: Di 26.10.04 20:49
Dann machst du halt das Trigger Objekt mit 86400 = die Anzahl Sekunden eines Tages.. Dann brauchste auch net mal "aufrücken" weil das dann sowieso den ganzen Tag abdeckt..
Und wenn du das noch für mehrere Tage brauchst dann machste das noch größer und wenn du das für noch mehr brauchst dann speicherst du halt Teile die weit in der Zukunft liegen in einer Text Datei ab
|
|
wulfskin
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Di 26.10.04 20:57
Wie wärs mit einer Liste und einsortieren? Sprich, du ordnest die Liste nach Endzeiten und sortierst neue Elemente entsprechend ihrer Endzeit ein. So weisst du das immer das oberste Item an der Reihe ist und kannst zum Beispiel in einem Thread überprüfen ob es fällig ist oder nicht.
Außerdem kann ich mir kaum vorstellen das 180.000 Elemente gleichzeitig passieren. Was macht den das Spiel alles?
Mfg, Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
delphiDeveloper
Beiträge: 48
|
Verfasst: Di 26.10.04 21:00
Titel: alternative strategie
bau dir sowas wie eine warteschlange auf, jedoch sortierst du neue Elemente sofort
in der richtigen Reihenfolge ein.
On top das Ereignis was als naechstes ausgeführt werden soll.
Dann braucht ein Timer immer nur schauen ob die Zeit für dein Element on top reif ist.
|
|
NeWsOfTzzz
Beiträge: 233
D4 Prof
|
Verfasst: Di 26.10.04 21:05
Ja die Warteschlange hab ich mir auch schon überlegt, aber erstens müsste die Warteschlange 180.000 groß sein und bei jedem Objekt das ausgeführt wird die 179.999 nachfolgenden um einen nach vorne geschoben werden.. ergo dasselbe wie direkt alle 180.000 variablen zu prüfen..
|
|
Martin W
Beiträge: 116
|
Verfasst: Di 26.10.04 21:12
Titel: Re: alternative strategie
NeWsOfTzzz hat mir gerade das vorweggennommen was ich schreiben wollte
Zitat: | Außerdem kann ich mir kaum vorstellen das 180.000 Elemente gleichzeitig passieren. Was macht den das Spiel alles? |
gleichzeitig ist falsch, da sind allerdings auch erst Objekte, die erst innerhalb von z.B. 10 Tagen passieren! Zum anderen - "180'000" wäre die höchstzahl der möglichen Objekte - Normalerweise arbeite ich mit einem sehr kleinen Bruchteil davon - Die Zahl 180'000 zu erreichen ist praktisch nicht möglich!!! Aber bis zu 9000 Elemente die in den Kommenden Tagen ausgeführt werden sollen ist relatistisch. Die Chache auch nur gleichzeitig auf 15'000 zu kommen ist schon sehr gering - aber mir geht es weniger um diese eine Zahl, wichtig ist nur das sie groß ist. Mir geht es darum meine Routine zu optimieren!!!
So, ich hab noch ne Frage... Wieviel Clients könnten an der INDY UDP Komponente connecten so das das Programm noch stabil läuft??? Was sagt ihr aus eigener Erfahrung dazu?
|
|
NeWsOfTzzz
Beiträge: 233
D4 Prof
|
Verfasst: Di 26.10.04 21:16
Soviele wie dein PC schafft? Nur geraten aber..
|
|
Martin W
Beiträge: 116
|
Verfasst: Di 26.10.04 21:23
NeWsOfTzzz hat folgendes geschrieben: | Soviele wie dein PC schafft? Nur geraten aber.. |
3 Ghz Rechenleistung, 2 TB Festplatte, 1 GB RAM, Standleitung der Telekom, Windows XP SP2!
Vorschläge?
|
|