Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


[web] How do Browser games implement 'tickers'?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
40 replies to this topic

#21 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 08 September 2010 - 01:39 AM

Quote:
Original post by DEbig3
As opposed to a user not logging in for a week, and then having to calculate 10k updates?


I doubt this is a problem. 10k is not very much, that's just about 1 ‰ of the number of rays a very basic realtime ray tracer can trace each second. Of course a web-server is usually not fast, as are most languages when compared to non-beginner C++.

So let's assume a tick is needed once per second:

1 tick/second
= 60 ticks/minute
= 3.600 ticks/hour
= 86.400 ticks/day
= 604.800 ticks/week
= 2.419.200 ticks/(28 days)

Advice A) Benchmark how long it takes for so many ticks. If it is just 10 seconds or less, I'd say we have no problem (in case this technique is applicable)

Advice B) Do you really need 1 tick/second? In case 1 tick/(30 seconds) would be enough, e.g., you would only have 80640 ticks/(28 days). Then go back to A).

(again, this is only in case the technique is applicable and to show actual numbers)

Sponsor:

#22 jolid   Members   -  Reputation: 143

Like
0Likes
Like

Posted 08 September 2010 - 12:52 PM

Quote:
Whether it calls update.php 5 times after 5 minutes of zero activity or once a minute during those 5 minutes, it's the same amount of work done by the server


This is rarely true in practice and completely wrong in theory. An operation 5 times is not equal to 1 operation that comes to the same answer. Example: Do this 5 times: n^2 = nnext, where n is initially 2. Convert the final answer to binary.

Or take 2 in binary (10) and append five 0s (1000000 = 64).

Just something to think about.

PS: Learn to use cron/task scheduler/roll your own if you go that route. Dealing with the extra overhead of triggering it via HTTP (even just the transfer costs!) isn't worth it and can easily become a MAJOR problem. What if your connection goes down? What if the server is disconnected for updates?

#23 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 08 September 2010 - 03:04 PM

Ahh. I'm actually the webserver myself.

For the time being, I've just got an update.php on a META 60 second content refresh.

Later on I'll either use windows scheduler or a curlpp app.

#24 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 08 September 2010 - 03:21 PM

Quote:
Original post by jolid
Quote:
Whether it calls update.php 5 times after 5 minutes of zero activity or once a minute during those 5 minutes, it's the same amount of work done by the server


This is rarely true in practice and completely wrong in theory. An operation 5 times is not equal to 1 operation that comes to the same answer. Example: Do this 5 times: n^2 = nnext, where n is initially 2. Convert the final answer to binary.

Or take 2 in binary (10) and append five 0s (1000000 = 64).

Just something to think about.

PS: Learn to use cron/task scheduler/roll your own if you go that route. Dealing with the extra overhead of triggering it via HTTP (even just the transfer costs!) isn't worth it and can easily become a MAJOR problem. What if your connection goes down? What if the server is disconnected for updates?


This isn't about an operation five times vs. a different operation that comes to the same answer.

This is about calling update.php once per minute for five minutes, vs. calling it 5 times in a row. I don't see a difference here.

Also I think you'd have to append 31 zeros for your example, which is really just showing that squaring numbers that are 1 followed by zeroes is easy in any base. It's not a shortcut.

Switching to a different base doesn't help you at all since you still have to do the work of converting it back to the base you're interested in which is even more work than manually squaring 2, 5 times in decimal.

#25 SimonForsman   Crossbones+   -  Reputation: 6189

Like
0Likes
Like

Posted 08 September 2010 - 03:27 PM

Quote:
Original post by sooner123
Ahh I see.

I don't see a big advantage of having the C++ application make all the updates itself over it calling an update.php. Unless C++ would simply do it far faster than PHP can. But I'd imagine in both cases the bottleneck would be the database.

Well I'll definitely weigh all the suggestions here and figure something out based on the final nature after more design fleshing. I now see that choosing between an "update when user loads a page or does something update-relevant"-solution, a "curlPP-driven C++ app that executes an update.php"-solution, and a "C++ app that updates the gamestate itself"-solution is fairly dependent on the specific nature/popularity of the game.

Ultimately I'll choose something that works without introducing any serious bottlenecks and takes the least work to implement.


Basically the drawbacks of a c++ program running curlpp is:

1) Most free/cheap hosts won't allow it, you'll have to pay for a dedicated server (Same is usually true for windows scheduler and cron) (The windows scheduler also has a lower limit of 5 minutes, atleast on Vista (not sure about server editions)

2) curlpp doesn't run update.php , it generates a HTTP request, sends it to the webserver and has the webserver parse the php script, this is unnecessary overhead.

a c++ app that updates the gamestate directly basically has the same primary drawback as the curlpp solution, it requires a dedicated server, however it has less overhead since it doesn't involve the webserver or the php parser in the update process, If you've allready written your update.php script its probably not worth the effort though.

If you got a dedicated server and know that the database will be the only bottleneck you could just run "php.exe update.php" and have update.php loop and sleep for you, this has less overhead than the curlpp solution (no webserver gets involved) and takes less effort to code (no need for c++ code, just add set_time_limit(0), an infinite loop, a time check(to ensure the correct amount of time has passed before running another update),a short sleep(to avoid eating up all cpu resources while doing nothing) to your update.php script) and a way to terminate the script cleanly (if you need to make updates to the script you don't want to kill it in the middle of an update).

#26 taby   Members   -  Reputation: 336

Like
0Likes
Like

Posted 08 September 2010 - 03:41 PM

Just an FYI: The Windows scheduler's commandline interface is at.exe

(At least it was on WinNT, Win2K...)

#27 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 08 September 2010 - 08:16 PM

Quote:
Original post by SimonForsman
Basically the drawbacks of a c++ program running curlpp is:

1) Most free/cheap hosts won't allow it, you'll have to pay for a dedicated server (Same is usually true for windows scheduler and cron) (The windows scheduler also has a lower limit of 5 minutes, atleast on Vista (not sure about server editions)

2) curlpp doesn't run update.php , it generates a HTTP request, sends it to the webserver and has the webserver parse the php script, this is unnecessary overhead.

a c++ app that updates the gamestate directly basically has the same primary drawback as the curlpp solution, it requires a dedicated server, however it has less overhead since it doesn't involve the webserver or the php parser in the update process, If you've allready written your update.php script its probably not worth the effort though.

If you got a dedicated server and know that the database will be the only bottleneck you could just run "php.exe update.php" and have update.php loop and sleep for you, this has less overhead than the curlpp solution (no webserver gets involved) and takes less effort to code (no need for c++ code, just add set_time_limit(0), an infinite loop, a time check(to ensure the correct amount of time has passed before running another update),a short sleep(to avoid eating up all cpu resources while doing nothing) to your update.php script) and a way to terminate the script cleanly (if you need to make updates to the script you don't want to kill it in the middle of an update).


I am the server. I actually thought php scripts timed out after 30 or 60 seconds or something. Is there a way around that? Or is it different when it's executed on the command line like that?

I really like that solution. It has the cleanliness I was looking for.

#28 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 08 September 2010 - 08:30 PM

Quote:
Original post by sooner123
I am the server.

Huh?

Quote:
I actually thought php scripts timed out after 30 or 60 seconds or something.

This is configurable. In theory, you can make that it never times out. In practice, it might depend on your hoster.

#29 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 09 September 2010 - 02:25 AM

Quote:
Original post by phresnel
Quote:
Original post by sooner123
I am the server.

Huh?

Quote:
I actually thought php scripts timed out after 30 or 60 seconds or something.

This is configurable. In theory, you can make that it never times out. In practice, it might depend on your hoster.


I am running the server.. on my own computer. I said that early on this thread but everyone seems to think I'm accessing a remote host.

If I disable timeouts.. it'll be disabled for anyone else accessing my server too?

I was hoping there was a command line argument to disable the timeout for that one call, but to leave the timeout active since it's an important feature.

#30 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 09 September 2010 - 02:57 AM

Quote:
Original post by sooner123
Quote:
Original post by phresnel
Quote:
Original post by sooner123
I am the server.

Huh?

I am running the server.. on my own computer.

My "Huh?" was targetted at that you are prolly not a server-computer, but a human running a server ;)

Quote:
If I disable timeouts.. it'll be disabled for anyone else accessing my server too?

If you configure it in your php-settings, indeed.

Quote:
I was hoping there was a command line argument to disable the timeout for that one call, but to leave the timeout active since it's an important feature.

According to man php, you can pass the name of a specific php.ini to it. So maybe you can grab your central php.ini, and fork your own custom configuration from it.



#31 SimonForsman   Crossbones+   -  Reputation: 6189

Like
0Likes
Like

Posted 09 September 2010 - 04:29 AM

Quote:
Original post by sooner123
Quote:
Original post by phresnel
Quote:
Original post by sooner123
I am the server.

Huh?

Quote:
I actually thought php scripts timed out after 30 or 60 seconds or something.

This is configurable. In theory, you can make that it never times out. In practice, it might depend on your hoster.


I am running the server.. on my own computer. I said that early on this thread but everyone seems to think I'm accessing a remote host.

If I disable timeouts.. it'll be disabled for anyone else accessing my server too?

I was hoping there was a command line argument to disable the timeout for that one call, but to leave the timeout active since it's an important feature.


you can pass a specific php.ini to the commandline, but...

Since what you really want to do is control the timeout on a per script basis the easiest solution is to call:
set_time_limit(0);
from the php script itself and then only run that php script from the cli.

As for running your own server, its something most of us do while we develop stuff (And i atleast assumed it was only for development purposes in your case aswell), most switch to external hosting services to get better uptime and reliability once the project is ready to be deployed (or as it grows in scale), alot of isps also won't allow you to run commercial services on their connections (Which pretty much removes your ability to generate revenue).

#32 jolid   Members   -  Reputation: 143

Like
0Likes
Like

Posted 09 September 2010 - 01:18 PM

This isn't about an operation five times vs. a different operation that comes to the same answer.

But my point is why not? What can you possibly be doing that can't be rewritten as an algorithm to calculate X number of iterations?

This is about calling update.php once per minute for five minutes, vs. calling it 5 times in a row. I don't see a difference here.

There isn't one, per se, except for the server load. Calculating that calls for a lot more data on estimated stats and execution speeds than I feel like making up for an example.

Also I think you'd have to append 31 zeros for your example, which is really just showing that squaring numbers that are 1 followed by zeroes is easy in any base. It's not a shortcut.

Whoops -- yeah, did the wrong squares. The point is that it IS a shortcut: Shifting bits is a common optimization (Shifting left/right N places is the same as multiplying/dividing by 2^N) that most compilers (C/C++ at least) now do themselves because it's faster than actual multiplication or division. Different bases lend themselves to different mathematical tricks, but as long as computers run in binary those tricks are the fastest.

Switching to a different base doesn't help you at all since you still have to do the work of converting it back to the base you're interested in which is even more work than manually squaring 2, 5 times in decimal

Maybe that's easier for you, but the base conversion was to draw your attention back to the computer. It's running in binary, so what makes sense to you on paper isn't necessarily the same thing that makes sense in a computer. Maybe they don't teach the bit shifting thing anymore? I thought you might recognize the example.

But whatever, just go with what works. You can always optimize later! I'm glad you've gotten it working.

#33 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 09 September 2010 - 02:50 PM

Quote:
Original post by jolid
This isn't about an operation five times vs. a different operation that comes to the same answer.

But my point is why not? What can you possibly be doing that can't be rewritten as an algorithm to calculate X number of iterations?

This is about calling update.php once per minute for five minutes, vs. calling it 5 times in a row. I don't see a difference here.

There isn't one, per se, except for the server load. Calculating that calls for a lot more data on estimated stats and execution speeds than I feel like making up for an example.

Also I think you'd have to append 31 zeros for your example, which is really just showing that squaring numbers that are 1 followed by zeroes is easy in any base. It's not a shortcut.

Whoops -- yeah, did the wrong squares. The point is that it IS a shortcut: Shifting bits is a common optimization (Shifting left/right N places is the same as multiplying/dividing by 2^N) that most compilers (C/C++ at least) now do themselves because it's faster than actual multiplication or division. Different bases lend themselves to different mathematical tricks, but as long as computers run in binary those tricks are the fastest.

Switching to a different base doesn't help you at all since you still have to do the work of converting it back to the base you're interested in which is even more work than manually squaring 2, 5 times in decimal

Maybe that's easier for you, but the base conversion was to draw your attention back to the computer. It's running in binary, so what makes sense to you on paper isn't necessarily the same thing that makes sense in a computer. Maybe they don't teach the bit shifting thing anymore? I thought you might recognize the example.

But whatever, just go with what works. You can always optimize later! I'm glad you've gotten it working.


Yeah I was just nitpicking with specifics. I did get your point and agree entirely and appreciate the advice.

#34 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 09 September 2010 - 09:10 PM

Quote:
Original post by SimonForsman
set_time_limit(0);
from the php script itself and then only run that php script from the cli.


This does not work in safe mode, though. Also, are you sure you can override the php.ini's max-execution-time to a larger time, if set?

#35 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 09 September 2010 - 09:39 PM

I just tested it.

set_time_limit(0); overrode php.ini's time limit.

#36 ToohrVyk   Members   -  Reputation: 1591

Like
1Likes
Like

Posted 09 September 2010 - 11:11 PM

Hey there. Stumbled by, and thought I would show this topic some love.

From a performance standpoint, in your typical PHP+MySQL web application, updating the game state on demand is an extremely bad idea, on par with holding a metal pole in a thunderstorm or bathing in shark-infested waters with a bathing suit made of fresh seal meat. You can try it, and you can make it work (if your server is hideously over-powered for the number of users you have), but it has severe scaling issues.

The first problem with on-demand updates has already been mentioned: it might take a while between sessions. The next user to come online has to suffer a huge performance hit to let the game server catch up with the current state. Not because the language is slow or because it's doing a+=1 five times instead of a+=5 once (all of this can be optimized, although not necessarily for free) but because a massively concurrent web application needs to save the data back to the database, and writing data to MySQL is insanely expensive. If your application has to perform even one indexed INSERT per interaction, then a single user catching up on all the interactions for an hour of idle time will have one hell of a wait time. And without one INSERT per interaction, good luck implementing the «here's what happened while you were away» feature on your game.

But that's not the worst issue (you can kind-of-solve-it by making sure someone requests an update every X seconds, just like the Original Poster is trying to solve it here).

The second problem with on-demand updates is stampeding (or serialization, depending on how you look at it). Stampeding basically happens like this:
  • User A connects to the server, notices that some updates should be done, and starts performing them transactionally.

  • User B connects to the server. Since User A is acting transactionally, User B sees the same needs-to-be-updated game state and starts updating it transactionally. This doubles the performance load of the update.

  • More users connect. Since the performance load increased, the updates take longer, so there's a higher probability of starting an upload that is already being processed. The server load increases until it basically gives up and takes its own life in frustration (yes, MySQL does that).


Depending on what your updates look like and how your transaction isolation level is configured, you might experience serialization instead: User A connects and does an update. User B connects and reads the "Todo" table(s) but is locked out because User A is working on it, so User B idles until User A is done. The lock on the "Todo" table(s) means your server can now only serve one user at a time. This is a major performance problem if you intend to serve more than a handful of simultaneous users, because locking problems can not be solved by adding more hardware.

The ideal architecture for a web game is to have a single update "thread" (might be a cron job or a script running without a time limit) that polls the database for things to be done and does them, and any number of threads to serve the HTTP requests from the players by reading data from the database and using lock-free, possibly delayed, cluster-indexed INSERTs to tell the update thread what to do. If you have the money, replicate the main database on another server and have all the players read from the slave to lighten the load and read locks on the master (if the server holding the update thread is powerful enough, you can scale your game to infinity). If you don't have that kind of money, and you see the update thread getting locked out too often, you might want to set lower a thread isolation level (READ COMMITTED) to reduce that (at the cost of sometimes displaying some inconsistent data on the user's screens).

In practice, it also helps if the game is designed so that most updates cost nothing. This can be done with two techniques:

  • Do not compute or store anything the game logic does not need. If you don't need it to run the game logic, then you can compute it on demand when (and if) the user asks to see it and discard it afterward. For instance, if your units gain ranks based on the number of enemies they kill, then you do need to compute and store the number of kills, but you don't have to find out the name of the current rank until the user needs to see it.

  • Use "do not open until" timestamps. Instead of the user inserting a "Build Space Station" order in an order table, they should instead insert a "Space Station" building in the building table with a timestamp of NOW() + buildtime. This means the act of successfully building the space station does not involve any computation (at the cost of an additional timestamp test when reading from the building table, but that can be easily indexed).


These will decrease the load on your server.

By the way, the default time limit for a PHP script running in CLI is infinite (and defaults to 30 seconds for CGI and Apache mod_php), so you don't have to configure anything.


#37 sooner123   Members   -  Reputation: 241

Like
0Likes
Like

Posted 10 September 2010 - 12:21 PM

Is there a way I could get my never-ending update.php to output some results to the page.. as it ticks away?

As far as I know, there is no html digest until the PHP script is finished.

Do I need to make an ajax page for myself to continually spit out status updates of the never-ending update.php?

As in: update.php loops forever, updating every X minutes or so.
Meanwhile, real_time_status.html uses ajax to query the server and see when the last successful update was, every second and paste it on the page javascript style?

#38 hojo118   Members   -  Reputation: 100

Like
0Likes
Like

Posted 16 February 2011 - 04:23 PM

I found this thread to be pretty helpful as I come up with a way to implement "ticks" in my browser game.

However I am not clear on something.

Example: Players gain resources at a rate of x/hour and a player's global high score is calculated from total resources. If the player begins construction of a building that increases that rate by 1/hour, and is told that it will take 12 hours for the building to complete and start conferring the new production rate, what happens when that player goes on a business trip and doesn't come back for a couple of days (48 hours)? Other players will be able to look at the "top player scores", but if there is no update being run (since the player is away on business), there will be more than 24 hours where the player is ranked much lower because there was nobody to cause an update to his building and the last couple days' of resource production. How is this resolved in a "Just in time" updating system. It seems to me that a cron job or background updater running at intervals is required to keep everyone in sync and make sure that scores are correct.

Example: Players have "assistant" NPC characters that have a lifespan. If the NPC "dies" while the player is not logged in, how is that resolved in a "Just in time" update system? The same goes for births. If two "married" NPCs have offspring while player is away, something has to generate a new character during the player's absence. The only way i can imagine this working is with a cron job, otherwise these characters simply do not exist until the player logs in again. It could even be possible that a character will be born and die before the player logs in again, so the player would need to be notified when they log in again of both the person's birth and death. However, with the just in time method of updates, NPCs could only be "born" when a player runs and update, since logging in and hence running the update script causes a rash of births and deaths.

Example: A player wants an email notification when a particular resource threshold or event occurs while they are away. If updates to the players' game only happen when they are logged in and causing updates, they will never get an email, or they will simply get all the emails at once the next time they log in. This seems to require a cron job and I do not know how it is resolved with just in time updating.

Those are some examples that I could think of off the top of my head. I really am having a lot of trouble finding resources about how these many browser game companies are handling their backend infrastructure and updates. It seems to be either a closely guarded secret or something that nobody has been able to figure out how to do outside the confines of internal development studios.

If any of you know any resources I could look at to help me wrap my head around this problem of "persistent" browser games, ticks, updates, etc. I would be extremely grateful.

#39 Anntor   Members   -  Reputation: 254

Like
0Likes
Like

Posted 17 February 2011 - 04:34 AM

...Example: A player wants an email notification when a particular resource threshold or event occurs...This seems to require a cron job and I do not know how it is resolved with just in time updating....


You answered your own question.

The magic word here is: "GAME DESIGN".

Start designing your browser based game AROUND these problems! Do not want to cramp your ideas into a framework, which isn't supposed to support such requirements.

If you want player ranks updated in realtime, than you don't want a browser based game with ticks per hour.
If you want email notification on events, than you don't want a browser based game with updates per user request.
If you just need updates per user request, than you don't need cron jobs.
etc.......

The "big" companies don't have magic solutions to these kind of requirements, they just use the right tool for the right job. And they know, what they have at disposal, so they can design their games accordingly.

#40 Dino   Members   -  Reputation: 172

Like
0Likes
Like

Posted 07 April 2011 - 11:22 AM

[Note: I'm not a PHP guy, so my response may not be applicable]
I think people trying to develop persistent games in ASP/PHP.ASP.net often miss the mark because they do not separate game logic from presentation logic. These 'languages' are scripting languages used to generate dynamic HTML. Sure you can use them to also do simple work, but in a moderately complex persistent game, you need to have a dedicated persistent engine running outside the confines of these languages.

Sure you can do simple persistent games (like those Facebook type games or Conquer-Club where events are very timed or user initiated), however in persistent games where there are self-sustaining/controlled NPCs and game triggered events that require no user interaction, ASP/PHP/ASP.net is a poor choice. I don't know about PHP, but ASP.net has support for multi-threading, but even that is a poor way of implementing a persistent engine.

You need to approach game development like you would approach any other application development. In proper application development, you should separate your business logic (or in this case, game logic) from the presentation. With that approach in mind, any ASP/PHP/ASP.NET developer should see PHP has the means of presenting the state of the game to the user, not the game itself. You should develop the game using a different technology that can run continuously in its own process space.

The trick comes in when you want your presentation layer to communicate with your logic layer. This can be done through a few different means:
- Game engine saves the game state to a persistent medium (i.e. a Database) for read-only retrieval from the presentation layer. Actions are sent to the engine through a channel such as a queue table that the game engine pings for actions to perform.
- Any presentation layer communicates with the game logic through the use of a custom protocol over a TCP socket. The HTTP request comes in, it opens a connection to the engine server, sends the action to the server, the server sends some sort of response, the presentation layer takes that response and presents it back to the user.

Both of these implementations, in my opinion, are better than trying to hack PHP/ASP/ASP.net into doing something that it was never designed to do. You'll drive yourself crazy trying to implement something as simple as an Update/Heartbeat event when it can be done easily and quickly using another approach.
Dino M. Gambone
Good judgment is gained through experience. Experience, however, is gained through bad judgment.

Visit http://ajaxmud.net for information about developing web-based games




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS