Bomberman Online and Habraeffect - 450 players on one map. Report and game engine details



    As promised in the topic-announcement of our game , we post the report on the habraeffect and details of the game engine.


    First of all, we want to thank everyone who participates (both in the game and in practical suggestions and ideas) in our testing of the first and current versions of the engine and gameplay. As practice has shown, during the Habra effect, bugs are found and fix much faster :)


    Statistics for 3 weeks


    Players registered: 4,663
    Rounds played: 2,252
    Number of players (including guests): 13,402
    Number of frags: 469,534
    Number of deaths: 545,957
    Number of goals scored: 1,707 ( WTF ?)

    [During Habraffect]
    Players online (maximum): 453
    CPU usage (according to the munin schedule): 168% (16 cores - 1600%)
    Memory usage: 1.65 GB
    Traffic (maximum): outgoing 24 Mbps | incoming 9 Mbps

    (Charts are clickable)
    [Engine] Connections [ 1 ]

    [Engine] Main cycle time [ 2 ]

    [Engine] Bytes per send [ 3 ]

    [Server] CPU usage

    [Server] Memory usage


    TTX


    Hosting: a dedicated server in the data center Vladimir (which was kindly provided by Parking.ru for the time of habitation testing)

    1. Game engine in Java & Jetty
    2. HAProxy - proxying of web sockets
    3. Nginx - statics and proxying to node
    4. Web-based functionality - Node.js (packages: express, mysql, request, nodemailer, validator, moment, forever)
    5. Clientside - GWT broadcast in javascript


    Game engine details


    Further - on behalf of Jedi_Knight (author of the engine).
    The development of gaming applications on canvas is a promising direction in which many development groups are currently moving, for example, the Estonian project mightyfingers.com.

    Some ideas are taken from the article www.html5rocks.com/en/tutorials/canvas/performance

    HTML5 Canvas Typing Basics


    Terminology: tile - one small square, for example 32 × 32; chunk - 8 × 8 tiles.

    Consider the features of the tile engine. Here is the model I came to:

    1) Subpixel rendering for tiles is simply not needed.

    2) Several transparent canvases are used, located on top of each other. If terrain was not modified, there was no scrolling, then you can not redraw it - this gives a small increase in performance (compared to cache optimization).

    3) As in the game model, the entire field is divided into 8 × 8 chunks. Since 64 drawImage calls for 32 × 32 images are much more expensive than one call for 256 × 256, visible chunks are drawn into the cache, which consists of two layers: under the player and above it.

    4) The cache is associative, that is, a pair of canvas'ov is used by several chunks on the map: a chunk with coordinates (X, Y) uses a cache with coordinates (X mod A, Y mod B) where (A, B) are cache sizes. In this case, the cache size must be such that two chunks with a common cache do not appear on the screen at the same time, there will be a race.

    5) In addition to canvas, cache numbers of tiles from the texture that are generated by the logical map are also stored in the cache. By number, you can uniquely draw a tile.

    6) When changing the visible chunk, the corresponding object in the cache is marked as dirty, requiring redrawing. At the same time, neighboring chunks can also be marked as dirty: you never know, suddenly a new shadow falls there, or there you need to draw a cut of a stone.

    7) If you need to redraw a dirty or new chunk, the table is put into the buffer 10 × 10 table - the chunk and the tiles surrounding it. An array of tile numbers is generated from this buffer - it is already 8 × 8. The tile number may also contain information about the shadow falling on this tile. In those places where the tile number has changed from the last time, redrawing occurs.

    8) For tiles it is more convenient to use not drawImage, but createPattern and fillRect. fillRect is also more convenient in that they can draw several identical consecutive tiles, and it will be faster.
    This test reveals the strange effect: that textures 32 × 32 has a significant performance boost to the iPads 2.5 times:
    jsperf.com/canvas-texture-draw-vs-fill
    Memo with the addition of TheShock

    9) And finally, why all this is necessary: ​​when scrolling, instead of drawing a bunch of small 32 × 32 images, drawing from the cache occurs. Calls to drawImage are significantly less, this seriously affects performance.

    Green, yellow, shadows - are drawn on the first layer, each 32 × 32 square can be drawn independently of the others, since the tile number contains information about the substrate, wall and shadow.
    The second layer is drawn in red, it is shifted 8 pixels up.




    Found bugs


    So, during the collective testing, the following problems were discovered:

    1) The tile cache suddenly turned off on a large map of a certain size, which led to wild brakes that only chrome could handle. It was all a matter of the periodic map: the size of the map (W, H) should be divided by the size of the cache (A, B).



    Let W, H = 7 A, B = 3, corner chunks fall on one cache position, and on a periodic map they fall on one screen, which leads to a race. The same situation is observed throughout the “seam” of the card.

    2) Client profiling revealed bottlenecks in code using java collections. In these places, collections are replaced by self-written structures.

    3) Changing the network protocol and switching from utf8 to binary web sockets in those browsers where they are supported (Chrome, Firefox) allowed to reduce the average client traffic to 12 Kbps. A native ArrayBuffer is used, I note that the DataView class is not implemented in Firefox, so we dispense with the usual Uint8Array.


    The graphs at the beginning of the article show:


    [1] Connections - the number of active connections to the server.

    [2] Main cycle time - how much the various stages of the main cycle take. The tick lasts 100ms, preprocess - checking commands from clients, tick - updating the game state, Observers - generating messages for clients. Total - all together, and plus the time it takes for messages to go to the network buffer. It is measured in milliseconds spent within one second, so when Total approaches 1000 - the server is bad, overhead starts to appear.

    [3] Bytes per send - pure traffic sent to clients, without headers of websocket frames, in bytes / sec.


    Gameplay Changes


    Almost all the time it took to accelerate the engine, client and network protocol. Serious work was done on optimization and refactoring, a lot of bugs were fixed.

    But a little was done on the gameplay: it became easier to lock the enemy. But the most important thing is that the ball and the gate have been added! Those who score receive a life shield. Particularly agile collect 3 shields and run like superheroes :)



    New stress habratesting. Goal - 1000 players online on one map


    The first time the server without problems and lags kept 350 players online. Today he is ready for 1000.

    We invite everyone on June 8, 9 and 10, from 17 to 22 to try to reach a new level of players online. Join , call friends / colleagues - we are waiting for you!
    (if someone does not have a domain available, go directly: 141.101.245.117 - not everyone has their dns updated after the move)

    Specially for the habrayuzers, we have prepared a Habramonitor that displays graphs of the current load on the engine and server (with an interval of 5 minutes).

    And may the Force and Fan abide with you.

    Also popular now: