Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am investigating Google App Engine for use in a browser based MMO. The player will make a server request when ever they build, buy or do any other action that the server needs to process. Therefore I am estimating a server request no faster than once per 10 seconds.

I want to store all my player data in one data structure (entity), because I have heard this is the most efficient way -- if not please correct me. So I figure that when a player causes a server request, I need to load/access the player's state data, carry out the action the player wanted to do and then store the result.

However, from an efficiency point-of-view, what is the best way to access the player data? I thought about using the datastore and maybe memcaching the result in memory for fast lookup. But don't I still need to write the data back out to the data store if it's cached? Should I write it out every time data changes? I looked at write behind caching but this seems to eat through your task queue quota.

Any ideas on the best approach? Best being defined as the most efficient method using the Google App Engine.

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

When a player is in the updating state (assuming this isn't a heavy-heavy write game like FPS or RTS), you need to either batch, or heartbeat (every 10 seconds or 100 updates) your updates. I ran into this problem with a Facebook isometric casual game. The basic idea is that a player needed to decorate their store/farm/whatever. If you try writing each time to the Player entity you'll run into huge problems. Also, it's not really a good idea to write only to cache ... it's not consistent and you could have cache evictions that make your players really mad that they just lost 5 hours worth of work.

For my game, I was thinking about using an eventually consistent, write behind cache, but it really is overkill.

My architecture looks something like this:

class MapTile(db.Model):
        """ Map tiles are very efficient way of storing what's on a tile, I just access  it by a key name like userid-x-y

            e.x MapTile(on='10001.180,20002.90')
        """
        on = db.StringListProperty() # a comma separated list of item ids on that tile and the rotation


class Item(db.Expando):
    """properties of a particular item, like a chair or a crop"""

Then when a new update comes along it will either be a sell,put away, purchase, or rotation. So I encode updates like {a:ROTATE,x:1,y:1,r:NW} and {a:PURCHASE,x:1,y:2,id:10001}

And batch them all up into a mapUpdates = [] queue that gets flushed whenever the length is 10 or the heartbeat comes around, whichever is first. This way your client is never waiting around, trying to save dozens to hundreds of entities. You can also have some sort of "...loading" indicator that tells them you're saving.

When the updates get to the server just write,blow cache,write cache. Simple as that.

share|improve this answer
    
Thanks cellis. This sounds fairly similar to the problem I am trying to solve. My updates may be a little slower simply because I have an build time for every item. Are your batches stored on the client until a trigger to send, or are you batching on the server before writing to data store? –  mmopy Apr 24 '11 at 6:59
    
Definitely stored on the client model. As I said, trusting memcache to be consistent with your writes is a very bad thing, even for a game. –  cellis Apr 24 '11 at 13:19
add comment

The most efficient way to organize the data depends on the kinds of operations you are performing on the data, and how often each of those operations will occur.

It sounds like you are making an MMO where players don't interact with each other, and where there's very little interaction with the game server (once every 10 seconds), so storing the player data in one data structure will probably work as long as it's not too large.

The way to find out is to try it. Start with the plain datastore. Measure it with a simulated load test. Find out if it's too slow. My guess is that if it's really once every 10 seconds there's no need for memcache or task queues or write behind caching or anything complicated like that. Once you test the performance, if you find it's too slow, then you'll be able to come here and point to the kinds of operations that are too slow, and we'll be able to help you with specific performance issues.

share|improve this answer
    
Thanks AmitP. Sounds like some sage wisdom there. You are right that the level of interaction is low (social friends, alliances and attacking with units that can take hours to arrive) –  mmopy Apr 24 '11 at 6:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.