mmofacts.com

Ressi Erhöhung, die zweite

gepostet vor 19 Jahre von Klaus
Wie in einem anderen Thread besprochen, gibt es ja zwei Möglichkeiten eine automatische Erhöhung zu erreichen. Bei mir ist das leider etwas komplizierter und deswegen muss ich auf Cronjobs zurückgreifen. Die einzige Möglichkeit die mir da einfällt ist eine Schleife in der alle Rohstoffproduzierenden Gebäude abgearbeitet werden. Dadruch fallen leider unendlich viele Queries ein.
Irgendwo hab ich gelesen das es möglich ist das durch einen einzigen Query zu lösen. Kann mir jemand davon mehr erzählen?
gepostet vor 19 Jahre von Fornax
Update rohstoffe, gebaeude SET rohstoffe.eisen= rohstoffe.eisen+(gebaeude.eisenmine*1,2)


Ich glaub, so war's
gepostet vor 19 Jahre von dan kirpan
mit dieser möglichkeit hat man aber das problem, dass die Ressi produktion nur Linear erhöht werden kann.

Noch ein anderer Nachteil des CronJob:
Wenn der Server Down ist, geht auch der CronJob nicht mehr, sprich die Ressis laufen nicht weiter.

Mit der Time-Stamp variante, laufen die auch die Ressis weiter...

Nur so ne anmerkung...
gepostet vor 19 Jahre von Klaus
Das funzt soweit schon ganz gut, nur (mal an deinem Beispiel betrachtet) was ist wenn ich jetzt 2 Eisenminen habe?

Update rohstoffe, gebaeude SET rohstoffe.eisen= rohstoffe.eisen+(gebaeude.eisenmine*1,2)

Mit diesem Query wird nur die Produktion einer Mine hinzugefügt, andere werden ignoriert. Ich hab mir schon überlegt SUM(gebaeude.eisenmine) zu benutzen, aber das ist nur in SELECTs zulässig. Jemand eine Idee?



Mit der Time-Stamp variante, laufen die auch die Ressis weiter...


Bei mir müssen die Ressis auch weiterlaufen, wenn der User offline ist. Demnach sehe ich keine bessere Lösung.
gepostet vor 19 Jahre von Kampfhoernchen
Update rohstoffe, gebaeude, insel_hat_gebaeude SET rohstoffe.eisen= rohstoffe.eisen+(gebaeude.eisenmine*1,2* insel_hat_gebaeude.stufe);

Ohne garantie ob das mit dem dem Kreuzprodukt richtig funzt, aber in Updates kann man meines wissens nach nicht joinen.
gepostet vor 19 Jahre von Klaus
Stufen gibt es ja nicht, denn jede Mine produziert einen individuellen Betrag ("gebaeude.eisenmine"). Deswegen müsste man die Beträge irgendwie zusammenzählen oder für jede Mine das Eisen erhöhen.


Edit: überraschend musste ich feststellen, dass alle Joins in UPDATEs möglich sind. Ich hab es mit LEFT JOIN sogar geschafft, dass für jede Mine einmal geupdated wird, allerdings wird dann doch nur um die Produktion der letzten Mine erhöht. Komisch, komisch....
gepostet vor 19 Jahre von Drezil
Original von Klaus
Das funzt soweit schon ganz gut, nur (mal an deinem Beispiel betrachtet) was ist wenn ich jetzt 2 Eisenminen habe?

Update rohstoffe, gebaeude SET rohstoffe.eisen= rohstoffe.eisen+(gebaeude.eisenmine*1,2)

Mit diesem Query wird nur die Produktion einer Mine hinzugefügt, andere werden ignoriert. Ich hab mir schon überlegt SUM(gebaeude.eisenmine) zu benutzen, aber das ist nur in SELECTs zulässig. Jemand eine Idee?

Seit Mysql 4.0 (oder 4.1?) gibt es sog. Sub-Selects:
Update rohstoffe, gebaeude SET rohstoffe.eisen= rohstoffe.eisen+(select sum(gebaeude.eisenmine) from bla where bli=blup)

wäre meine idee dazu ... allerdings darf in diesem fall nur geau 1 Zelle zurückgegeben werden. =)
gepostet vor 19 Jahre von Klaus
hey das geht! Dauert zwar etwas länger, aber es macht was es soll. =)

thx, Klaus
gepostet vor 19 Jahre von KoMtuR
Ich frag mich warum ihr immer die rohstoffproduktion mit den ganzen gebäuden berechnen wollt? sagen wir ihr nehmt in die rohstofftabelle noch ne spalte für jede ressource und speichert darin die produktion an diesem rohstoff pro Stunde/minute/sekunde/etc.. Wenn ihr eine eisenmine baut erhöht den wert einfach um die produzierende Zahl Rohstoffe, die dieses Gebäude macht. Somit brauchste nur eine kurze updatezeit, weil nicht irgendwelche subqueries oder vielleicht noch joins nötig sind
gepostet vor 19 Jahre von knalli
Warum linear? Mysql hat einige mathematische Funktionen im Huckepack, bei sinnvollem Einsatz durchaus eine Möglichkeit.
gepostet vor 19 Jahre von Klaus
Original von KoMtuR
Ich frag mich warum ihr immer die rohstoffproduktion mit den ganzen gebäuden berechnen wollt? sagen wir ihr nehmt in die rohstofftabelle noch ne spalte für jede ressource und speichert darin die produktion an diesem rohstoff pro Stunde/minute/sekunde/etc.. Wenn ihr eine eisenmine baut erhöht den wert einfach um die produzierende Zahl Rohstoffe, die dieses Gebäude macht. Somit brauchste nur eine kurze updatezeit, weil nicht irgendwelche subqueries oder vielleicht noch joins nötig sind



Nicht bei mir. Vorher wird noch überprüft ob das Lager voll ist und ob die Mine überhaupt produzieren kann. Wenn nicht müsste der Wert ja geändert werden. Im Endeffekt fällt so noch mehr Arbeit (jedenfalls bei mir).
gepostet vor 19 Jahre von KoMtuR
Warum fällt damit mehr arbeit an? nehmen wir mal an der user aktualisiert. Du liest ja bei jedem reload eine routine auf, die deine daten aus der db liest. somit auch das lager und die rohstoffe, die dieser spieler hat und pro stunde verdient. nun werden die Rohstoffe einfach im script weiterbehandelt.

Man brauch ja nicht aktualisieren, weil ja eh nichts gemacht wurde. Man hat den alten Timestamp und die alten Ressourcen - am Anfang. Nun berechnet man halt mittels PHP die Ressourcen und gibt die dem User aus. Also natürlich schon mit der Grenze zum Lager. Es wird zwar was produziert, aber im Endeffekt das Überproduzierte wieder subtrahiert. Das Spiel mit dem alten Timestamp kannste ja dann solange weiter treiben, solange nicht ressourcentechnisches geändert wird, wie zb. Lagerausbau oder Rohstoffgebäude-Ausbau. Somit hast du sogar noch weniger Aktualisierungen, da User meist zum klickwütigen Monster mutieren, wenn das Spiel im Echtzeit vorgaukelt
gepostet vor 19 Jahre von schokofreak
Du kannst diese Berechnung statt in PHP auch gleich in JS machen; und schon hast du den effekt dass er ohne Klick zukucken kann, wie sich das ganze erhöht.

Sobald eine "Buchung" kommt gehst du dann kurz überprüfen wie viel eigentlich tatsächlich im Lager ist / Aktualisierst dieses.
Da 9 von 10 Operationen jedoch nur kucken und nicht kaufen sind; hast 9 von 10 DB Updates eingesparrt. Zusätzlich einige Cheat- Quellen.

Gruss
gepostet vor 19 Jahre von KoMtuR
Naja ich mach das ja schon mit JS aber trotzdem kann man dem User nicht trauen. Sicherlich wirste noch alles 10mal prüfen müssen, aber ich habs auch versucht so weit wie es geht mit javascript umzusetzen. klar könnten nun wieder einige sagen, dass man ohne JS besser dran wäre, aber man merkt schon stark, dass viele Spiele Qualität gewinnen, durch Javascript siehe AJAX
gepostet vor 19 Jahre von Kallisti
Original von Klaus
Das ist ja einfacher als erwartet! Danke, mich hat dieser Post ziemlich verweirrt: http://www.galaxy-news.de/forum/viewtopic.php?p=7373#7373


Das Query tut ja auch "etwas" mehr. :-)

sprintf(temp, "UPDATE user SET metall=LEAST(MID(gebaeude,19,2)*4000,MID(gebaeude,21,2)*%i+metall), sauerstoff=LEAST(MID(gebaeude,19,2)*4000,MID(gebaeude,23,2)*%i+sauerstoff), rohoel=LEAST(MID(gebaeude,19,2)*4000,MID(gebaeude,25,2)*%i+rohoel), silizium=LEAST(MID(gebaeude,19,2)*4000,MID(gebaeude,27,2)*%i+silizium), element122=LEAST(MID(gebaeude,19,2)*4000,element122), credits=LEAST(MID(gebaeude,19,2)*4000,credits+%li)", get_long_from_options("metall_pro_level"), get_long_from_options("sauerstoff_pro_level"), get_long_from_options("rohoel_pro_level"), get_long_from_options("silizium_pro_level"), get_long_from_options("add_credits"))

Es updated also 6 verschiedene Ressourcen, rundet gleichzeitig ab auf das Maximum der Speichereinheit (deren level 2 Stellen in einer Zeichenkette aus Integers darstellt, mit dem MID ausgelesen) und aktualisiert dann die Ressourcen entsprechend dem jeweiligen Minenlevel (wieder 2 Stellen in derselben Zeichenkette). get_long_from_options liefert einfach die Einstellungswerte zurueck die bestimmen wie viel pro level erhoeht wird. - Das ist natuerlich linear, aber mysql kennt, wie erwaehnt, ja auch einige mathematische Funktionen, womit alles problemlos moeglich ist.

Der Vorteil an unserer Variante ist einfach dass die Gebaeude und die Ressourcen in derselben Tabelle stehen und die Gebaeude dabei nur eine kleine Integerzeichenkette einnehmen.

Dafuer ist es ein wenig aufwendiger daraus die Informationen zu extrahieren.

Ich hab diesen Code mit dem Spiel uebernommen und mich daher noch nicht nach der performance erkundigt, weil es zu aufwendig waere dieses Konzept nun komplett zu aendern. Keine Ahnung wie fix "MID" ist, verglichen mit dem Aufwand einer extra Tabelle fuer die Gebaeude.
gepostet vor 18 Jahre, 12 Monate von Freshman
ich denke auch, dass es nicht Sinnvoll ist, die Grundlage der Ressourcenberechnugn in einer anderen Tabelle zu Speichern als die Ressourcen selbst.

Wenn die Ressourcenproduktion an die Gebäude gekoppelt ist ( in 95% der Fälle ist es ja so ) dann sollte man halt eine Variable innerhalb der Ressourcen für jede Produktion einführen. Hört sich zwar erstmal dumm an, warum man eine Spalte pro Ress mehr hat also ein Feld pro Ress pro User mehr hat, aber es ist für die Datenbank eindeutig besser zu handeln.

mfg

Freshman
gepostet vor 18 Jahre, 12 Monate von Thomblin
hm,

warum wollt ihr unbedingt alles in einem query machen? Finde das wird bei komplexen Systemem ungemein kompliziert. Gut ich arbeite nicht mit cronjobs, daher muss ich die vergangene Zeit seit dem letzten Update mit einbeziehen. Ich habe es nie getestet, aber geht ein riesen query der alles berechnet so viel schneller, als zwei drei kleine queries deren ergebnis dann per php verwaltet wird? ICh kontne bisher keine Performance Probleme feststellen
gepostet vor 18 Jahre, 12 Monate von Kallisti
Bei uns laeuft ein Daemon im Hintergrund. Das obige Query wird nie komplizierter werden und wird alle 15 min einmal ausgefuehrt. :-)
gepostet vor 18 Jahre, 12 Monate von Klaus
Ich üerlege mir auch eine Art Daemon zu machen, selbst wenn es nur in php ist. Leider hängt bei mir zuvieles von Echtzeit Faktoren ab, warum dann nicht gleich in echt berechnen?
Und wenn der Daemon dann zu Serverlastig wird, kann man den doch auf einen anderen Server laden und der connected dann zum DB-Server.
gepostet vor 18 Jahre, 12 Monate von BLUESCREEN
Original von Thomblin
Ich habe es nie getestet, aber geht ein riesen query der alles berechnet so viel schneller, als zwei drei kleine queries deren ergebnis dann per php verwaltet wird?

Im Normalfall ist ein großer Query immer schneller als zwei kleine, die die selbe Arbeit verrichten. Wenn du allerdings einen Teil der Berechnungen in PHP durchführst, die sonst in den großen Query müssten, dann kann man das nicht mehr so einfach vergleichen, aber ich vermute, dass auch dann noch der eine Query besser ist (muss man im Einzelfall testen, was schneller ist).
gepostet vor 18 Jahre, 12 Monate von Freshman
das schneller oder langsamer ist nicht festgelegt.

Klar ist, dass die meisten Spiele in php geschrieben sind, und in php ist jede Rechenoperation langsamer als eine in mysql, da diese in c++ geschrieben ist, und wohl auch bis auf letzte optimiert ist.

wenn wir aber von c oder c++ daemons sprechen, so kann man auch gefahrlos mehrere abfragen verwenden, da sich dies erst auf die geschwindigkeit auswirkt, wenn man schon lange einen weiteren Server haben sollte.
gepostet vor 18 Jahre, 12 Monate von BLUESCREEN
@Freshman: Dein Post stimmt vorne und hinten nicht...
gepostet vor 18 Jahre, 12 Monate von Duke_
Original von BLUESCREEN
@Freshman: Dein Post stimmt vorne und hinten nicht...


Und was ist mit dem Mittelteil...
gepostet vor 18 Jahre, 11 Monate von Freshman
@ Bluescreen:

Da bin ich ja mal auf die erklärung gespannt, was daran nicht stimmt.

Etwa der Teil, dass berechnungen in php langsamer sind als in der mysql aber dafür c++ genau so schnell ist?

Da bin ich ja mal echt gespannt, wie du mir das zeigen willst.

i1 = 1;
i2 = 2;

y = i1 + i2;

mov eax,dword ptr [ebp-4]
add eax,dword ptr [ebp-8]
mov dword ptr [ebp-10h],eax

y = 1 + 2;
mov dword ptr [ebp-0Ch],3


Lieber Bluescreen, ich habe dir hier einfach mal eine Addition im Assembler aufgeschrieben, dass ist der Maschinencode, du weißt?

hier sehen wir, dass eine Addition 3 assemblerschritte hat, also 3 clocks
( in mysql sieht das genau so aus , es sei denn sie muss erst einen string in einen Wert umwandeln, dann sind es 2 mehr plus den call auf s.B. atoi)


Da du der gute Programmierer von uns bist, zeige bitte mal auf, wie sich eine Addition in php verhält, und warum diese evt. so schnell sein soll wie c++ ( also mysql )

Bitte vergiss aber nicht die Interpretierungsschritte, da diese einen wesentlichen Teil der Zeit einnehmen.


Original von BLUESCREEN


Wenn du allerdings einen Teil der Berechnungen in PHP durchführst, die sonst in den großen Query müssten, dann kann man das nicht mehr so einfach vergleichen, aber ich vermute, dass auch dann noch der eine Query besser ist (muss man im Einzelfall testen, was schneller ist


Du vermutest?

Gut, dann bin ich gespannt, wie schnell php nun wirklich ist, wenn du es mal nachgewiesen hast in clocks.
gepostet vor 18 Jahre, 11 Monate von Chojin
Ich kann mit einem PHP precomiler nochmal den bis zu 10 fachen speed aus eine php script rausholen. Das problem bei PHP liegt einfach darin, das der auszuführende code zur laufzeit immer wieder neu erzeugt wird.

Ich bin mal so frei und poste hier ein paar adressen:
- Zend Optimizer (FREE)
- Zend Platform™ 2 (~$995 1 CPU/yr)
- Turck MMCache (FREE - open source)
- PHP Accelerator (FREE)
- Alternative PHP Cache (FREE)
- afterBURNER*Cache (FREE - open source)

Es wäre schön wenn mal jemand von unseren leuten hier einen representativen Test machen könnte :roll:

Kleiner Tip von mir: Am besten einfach alle Tools auf einmal installieren, das ergibt (rein rechnerisch) einen 300fachen geschwindigkeitsvorteil


reg4rds
chojin
gepostet vor 18 Jahre, 11 Monate von Kallisti
Wenn ich mich recht erinnere wird mmcache nicht weiterentwickelt und heisst nun Eaccelerator. Siehe http://www.eaccelerator.net/HomeUk - den verwende ich auch und bin zufrieden.
gepostet vor 18 Jahre, 11 Monate von Tweety
Im Normalfall ist ein großer Query immer schneller als zwei kleine

Ich denke, das war u. A. auch darauf bezogen, dass man pro Query auch immer den Overhead hat, der durch das Senden der Abfrage und das Zurückschicken der Ergebnisse entsteht - hier ist natürlich eine Abfrage rein von diesem Overhead her gesehen schneller als zwei oder mehrere. Kommt dann natürlich auch drauf an, wie stark die Datenbank durch ne komplexe Abfrage zum Aggregieren und Rechnen gezwungen wird, im Vergleich zu mehreren einfachen Abfragen.
gepostet vor 18 Jahre, 11 Monate von Kallisti
Original von Tweety
Im Normalfall ist ein großer Query immer schneller als zwei kleine

Ich denke, das war u. A. auch darauf bezogen, dass man pro Query auch immer den Overhead hat, der durch das Senden der Abfrage und das Zurückschicken der Ergebnisse entsteht - hier ist natürlich eine Abfrage rein von diesem Overhead her gesehen schneller als zwei oder mehrere. Kommt dann natürlich auch drauf an, wie stark die Datenbank durch ne komplexe Abfrage zum Aggregieren und Rechnen gezwungen wird, im Vergleich zu mehreren einfachen Abfragen.


Falsch zitieren kann ganz ganz boese enden.. sollte man sich nie angewohenen. Nicht Saetze aus dem Zusammenhang reissen oder teile verschlucken, Auslassungen immer mit [...] kenntlich machen.

Dann waere dir naemlich
[...], die die selbe Arbeit verrichten
aufgefallen, was dein Posting daher ueberfluessig macht.
gepostet vor 18 Jahre, 11 Monate von Kampfhoernchen
Ich denke mal, dass du eine große Query auf jeden Fall Rechenzeit gespart wird.

Auch in C++. Einfach weil die Rückgabe der Daten vom DB-Server auf den Client (egal ob C++, Java, PHP oder auch Excel) Zeit braucht, da sie zumindest internen TCP-Traffic produziert.
Die einzelnen TCP-Packete müssen vom DB-Server erstmal aufbereitet werden, und der Client muss diese wieder auseinandernehmen. Da ist es eben ein Unterschied, ob mehr als 1000 Datensätze einzeln abgeholt werden oder gar nichts abgeholt wird und MySQL nur ein "Query wurde ausgeführt" zurückliefert.

Auch C++ bereitet die einzelnen Datensätze als Array auf. MySQL handelt seine Daten da erheblich effizienter (darauf ist es ja getrimmt).
gepostet vor 18 Jahre, 11 Monate von BLUESCREEN
Also doch noch ein Kommentar, da er es nicht einsehen will...

Original von Freshman

Klar ist, dass die meisten Spiele in php geschrieben sind, und in php ist jede Rechenoperation langsamer als eine in mysql, da diese in c++ geschrieben ist, und wohl auch bis auf letzte optimiert ist.
Die Sprache, in der etwas geschrieben ist, scheint dir ja sehr wichtig zu sein.
Wenn man danach geht dürfte es keinen spürbaren Unterschied geben, da PHP in C geschrieben ist.

Aber darauf kommt es nicht an. Sowohl die PHP-Scripts als auch die SQL-Queries werden zur Laufzeit von PHP bzw. MySQL interpretiert und was das schon an Zeit kostet übersteigt kleinere Unterschiede.

Was wirklich den Unterschied macht ist, dass die SQL-Queries erstmal an den Server übertragen werden müssen, dass für jeden Query eine neue Interpretierung gemacht werden muss und dass das Ergebnis wieder zurückgeschickt werden muss.
Bei einem großen Query muss MySQL nur einen Query interpretieren und kann dann den ganzen Kram intern abarbeiten ohne groß Daten hin und herzuschicken, die dann auch noch vom PHP-Script wieder aufgearbeitet werden müssen.

Abgesehen davon wird das PHP-Script so oder so interpretiert werden müssen und da machen ein paar Zeilen mehr nicht den großen Unterschied. Im Gegensatz dazu ist für jeden SQL-Query eine getrennte Bearbeitung nötig und wenn man auf einige von denen verzichten kann, dann sollte man das tun.

Original von Freshman

wenn wir aber von c oder c++ daemons sprechen, so kann man auch gefahrlos mehrere abfragen verwenden, da sich dies erst auf die geschwindigkeit auswirkt, wenn man schon lange einen weiteren Server haben sollte.
Hier hast du komplett an der Frage vorbeigeredet... Es ging darum, was schneller ist und nicht darum, ob eine der Möglichkeiten den Server zu Boden bringt.
Abgesehen davon hebst du schon wieder die Sprache unnötig hervor und schreibst auch nicht von welchem Programm du überhaupt redest.
gepostet vor 18 Jahre, 11 Monate von Kampfhoernchen
Genau das meinte ich mit dem TCP-Traffic. MySQL lauscht an Port 1521 (wenn ich mich net täusche), und nachdem, was in ner Zeitschrift (Ich glaub es war "Der Entwickler") gelesen hab, is der Linux-TCP-Stack recht langsam, was viele kleine Packete angeht, die man hier wohl hat (1 Packet pro Datensatz).

PS. die ganze Diskussion mal etwas sachlicher führen. Danke
gepostet vor 18 Jahre, 11 Monate von Tweety
Dann waere dir naemlich
[...], die die selbe Arbeit verrichten

aufgefallen, was dein Posting daher ueberfluessig macht.

Erstmal vorweg, ich denke mal, Du brauchst mir nicht zu sagen, wie man richtig zitiert - Geklammerte Auslassungspunkte brauchst du beim korrekten Zitieren z. B. nur in der Mitte eines Zitats und nicht so wie oben direkt am Anfang - denn jeder Interessierte wird den entsprechenden Text eh ansehen oder vorher schon gelesen haben.

Meine Antwort war auch und gerade darauf bezogen, dass die verschiedenen Queries dieselbe Arbeit verrichten und nicht zwei vollkommen verschiedene Dinge. Mir ging es eben um die erwähnte Tatsache der unterschiedlichen Last: viele Queries vs eine.

Was genau hier auch noch mal erwähnt wurde, wenngleich auch ausführlicher:
Was wirklich den Unterschied macht ist, dass die SQL-Queries erstmal an den Server übertragen werden müssen, dass für jeden Query eine neue Interpretierung gemacht werden muss und dass das Ergebnis wieder zurückgeschickt werden muss.

Bei einem großen Query muss MySQL nur einen Query interpretieren und kann dann den ganzen Kram intern abarbeiten ohne groß Daten hin und herzuschicken, die dann auch noch vom PHP-Script wieder aufgearbeitet werden müssen.
Das wollte ich nur mal klarstellen. Danke.

Auf diese Diskussion antworten