| Autor | Beitrag | 
| Martin W 
          Beiträge: 116
 
 
 
 
 | 
Verfasst: Mo 25.10.04 16: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 = recordID_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: 6395
 Erhaltene Danke: 149
 
 Windows 7 + Windows 10
 Sydney Prof + CE
 
 | 
Verfasst: Mo 25.10.04 17: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 18: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: 6395
 Erhaltene Danke: 149
 
 Windows 7 + Windows 10
 Sydney Prof + CE
 
 | 
Verfasst: Mo 25.10.04 18:54 
 
Hast du es ausprobiert?   | 
|  | 
| .Chef 
          Beiträge: 1112
 
 
 
 
 | 
Verfasst: Mo 25.10.04 18: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: 6395
 Erhaltene Danke: 149
 
 Windows 7 + Windows 10
 Sydney Prof + CE
 
 | 
Verfasst: Mo 25.10.04 19: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 19: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 19: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: 6395
 Erhaltene Danke: 149
 
 Windows 7 + Windows 10
 Sydney Prof + CE
 
 | 
Verfasst: Mo 25.10.04 19: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 20: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 13: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 		EIN Record                       Delphi-Quelltext 
 		EIN Array                       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 Timer der jede Sekunde folgendes macht                       Delphi-Quelltext 
 									| 1:
 | aktionen: array of timer_execute_functions;					 |  		EINE Funtion, die sich in einem Thread befindet                       Delphi-Quelltext 
 		                       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 13: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 19: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 19: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 19: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 20: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 20: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 20: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 20:16 
 
Soviele wie dein PC schafft? Nur geraten aber.. | 
|  | 
| Martin W  
          Beiträge: 116
 
 
 
 
 | 
Verfasst: Di 26.10.04 20: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? | 
|  |