I spent the past few weeks slaving over a new version of OpenPoker and after a few rewrites I can safely say that this is the greatest and most scalable poker server ever!
How scalable? I don't know but you can tell me!
Grab the poker server binaries as well as the data files for the test harness and uncompress them into a directory.
Install Erlang/OTP R12B3 if you haven't already. R12B4 should work as well, although I haven't tested it.
Switch to the directory where you put the binaries and start by running everything on a single Erlang VM like this:
ulimit -n 100000
erl +K true +P 134217727 -sname 1 -s mnesia start -smp disable
It doesn't matter what the VM is named and you don't have to disable SMP at all.
DO increase the number of available file descriptors A LOT! Every bot uses a socket, every player uses another one. Every running game gets an observer which uses another socket!
Type the following at the Erlang prompt
schema:install().
mb:run().
bb:run().
This will set up the database, run the game launcher and the bot runner.
Wave your hands in the air, save a little prayer and type
dmb:test(1000).
This will launch 1000 poker games and start them once all the players have joined their respective games. All of the games will start at the same time!
Your output should look like this
mothership:openpoker_v2 joelr$ /db2/poker
Erlang (BEAM) emulator version 5.6.3 [source] [async-threads:0] [kernel-poll:true]
Eshell V5.6.3 (abort with ^G)
(1@mothership)1> bb:run().
{ok,<0.117.0>}
(1@mothership)2> mb:run().
'1@mothership': game server on port 3001
'1@mothership': port server on 3001...
ok
(1@mothership)3> dmb:test(1000).
gateway:start('1@mothership', 4000, 500000)
Waiting for game servers...
'1@mothership': port server on 4000...
Simulating gameplay with 1000 games...
50 games started, 262 players
...
1000 games started, 5066 players
dmb: 1000 games will be launching simultaneously
dmb: waiting for games to end...
barrier: reached target of 1000
50 games finished
...
1000 games finished
dmb: exited successfully, 207.306785 seconds elapsed
ok
(1@mothership)4>
Ignore the Mnesia is overloaded warnings but make sure there are no player timeouts and all of the games finish successfully. Now you can get to the fun part and see how many games you can run simultaneously without player timeouts!
There are two ways to accomplish this and the simplest one goes like this
dmb:run(500, 5, 5, 5000). % 500 games, 5 game servers, 5 bot launchers
This will likely not work under Windows as it starts a bunch of Erlang slave nodes, 10 to be precise. Of these 5 will be used to launch games and 5 to run bots. You will also see statistics written to the terminal window every 5 seconds or so. 5000ms is the default so you can just drop this argument while keeping the first three.
Slaves use a RAM copy of the database tables and these arguments
common_args() ->
"+K true -smp disable".
If everything goes well, your output should look like this
mothership:openpoker_v2 joelr$ /db2/poker
Erlang (BEAM) emulator version 5.6.3 [source] [async-threads:0] [kernel-poll:true]
Eshell V5.6.3 (abort with ^G)
(1@mothership)1> schema:install().
=INFO REPORT==== 30-Oct-2008::02:26:08 ===
application: mnesia
exited: stopped
type: temporary
ok
(1@mothership)2> dmb:run(500, 5, 5).
game5@mothership: game server on port 3001
game5@mothership: port server on 3001...
...
game1@mothership: game server on port 3005
game1@mothership: port server on 3005...
cluster: [bot5@mothership,bot4@mothership,bot3@mothership,
bot2@mothership,bot1@mothership,game5@mothership,
game4@mothership,game3@mothership,game2@mothership,
game1@mothership]
bot launchers : [<7645.84.0>,<7644.79.0>,<7643.74.0>,<7642.69.0>,
<7641.63.0>]
game launchers : [<7640.548.0>,<7639.614.0>,<7638.536.0>,<7637.417.0>,
<7636.253.0>]
game servers : [<7640.385.0>,<7639.451.0>,<7638.373.0>,<7637.254.0>,
<7636.90.0>]
gateway:start('1@mothership', 4000, 500000)
Waiting for game servers...
'1@mothership': port server on 4000...
Simulating gameplay with 500 games...
50 games started, 262 players
...
500 games started, 2562 players
dmb: 500 games will be launching simultaneously
dmb: waiting for games to end...
=INFO REPORT==== 30-Oct-2008::02:26:54 ===
module: stats
elapsed: 4.999982
{total_bots_connected,0}: 602
{bots_connected,0}: 602
{games_launched,0}: 202
...
{time_to_client,0}: 0.1876190042803583
{time_to_server,0}: 0.4820268169244182
50 games finished
50 games finished
100 games finished
100 games finished
dmb: exited successfully, 71.21448699999999 seconds elapsed
dmb: exited successfully, 71.214702 seconds elapsed
dmb: exited successfully, 71.214737 seconds elapsed
dmb: exited successfully, 71.21477 seconds elapsed
dmb: exited successfully, 71.214803 seconds elapsed
ok
(1@mothership)3>
Perhaps you are feeling lucky today, have a bunch of machines in a closet, or just want to run game servers and bot launchers with SMP enabled. Run as many nodes as you like and type
schema:install().
on your master node, then
mb:run(hostname).
on all the game server nodes and
bb:run().
on your bot runner nodes.
Hostname should be the fully qualified domain name and you should be able to connect to it outside of Erlang.
When you are done, come back to the master node and type
stats:start().
dmb:test(1000). % 1000 games, use 5000+ for maximum effect
Game servers and bot runners join their respective global groups and automatically join the cluster so long as you point them to the master node.
I use this shell script to launch my master node
#!/bin/bash
POKER=~/work/openpoker/
erl +K true +P 134217727 -pa $POKER/server/src -sname 1 -s mnesia start -smp disable $*
and this to launch other nodes (add -sname 2, 3, etc.)
#!/bin/bash
POKER=~/work/openpoker/
erl +K true +P 134217727 -pa $POKER/server/src -mnesia extra_db_nodes "['1@mothership']" -s mnesia start $*
That's it folks! Please let me know how far you go.
Feel free to join the OpenPoker Google group if you want to discuss this further.
Update:
The Erlang Questions thread can be found here. Also, it's R12B3 or R12B4, my bad!
I split the download into two parts. This is now part of the download instructions above. Also added link to the OpenPoker Google group.
You can also follow me on Twitter.
Update II:
Here are the results of testing on a 3Gb Joyent Accelerator running Solaris 5.11.
I'm launching 5000 games with 25000 players on 5 game servers and 5 bot nodes, all running on the same physical machine. I'm hitting the 65000 socket maximum so the way to scale out is by adding more physical servers to the cluster.
A starter gun fires when all the players join their respective tables. All games start at the same time and players act in rapid fire, with no delay between bet request and response. Think of it as a 25000 player tournament, running full-speed!
Poker barely consumes any CPU power so the way to scale with OpenPoker is to run a handful of cheap servers with 1-2Gb of memory.
(1@fhm8e4aa)1> schema:install().
=INFO REPORT==== 30-Oct-2008::20:49:19 ===
application: mnesia
exited: stopped
type: temporary
ok
(1@fhm8e4aa)2> dmb:run(5000, 5, 5, 60000).
game5@fhm8e4aa: game server on port 3001
game5@fhm8e4aa: port server on 3001...
game4@fhm8e4aa: game server on port 3002
game4@fhm8e4aa: port server on 3002...
game3@fhm8e4aa: game server on port 3003
game3@fhm8e4aa: port server on 3003...
game2@fhm8e4aa: game server on port 3004
game2@fhm8e4aa: port server on 3004...
game1@fhm8e4aa: game server on port 3005
game1@fhm8e4aa: port server on 3005...
cluster: [bot5@fhm8e4aa,bot4@fhm8e4aa,bot3@fhm8e4aa,bot2@fhm8e4aa,
bot1@fhm8e4aa,game5@fhm8e4aa,game4@fhm8e4aa,game3@fhm8e4aa,
game2@fhm8e4aa,game1@fhm8e4aa]
bot launchers : [<7615.83.0>,<7614.78.0>,<7613.73.0>,<7612.68.0>,<7611.62.0>]
game launchers : [<8822.485.0>,<8820.498.0>,<7610.582.0>,<7609.416.0>,
<7608.252.0>]
game servers : [<8822.322.0>,<8820.335.0>,<7610.419.0>,<7609.253.0>,
<7608.89.0>]
gateway:start('1@fhm8e4aa', 4000, 500000)
Waiting for game servers...
'1@fhm8e4aa': port server on 4000...
Simulating gameplay with 5000 games...
50 games started, 262 players
...
5000 games started, 25404 players
dmb: 5000 games will be launching simultaneously
dmb: waiting for games to end...
=INFO REPORT==== 30-Oct-2008::20:50:59 ===
module: stats
elapsed: 60.003419
{total_bots_connected,0}: 8904
{bots_connected,0}: 8904
{games_launched,0}: 1820
=INFO REPORT==== 30-Oct-2008::20:51:59 ===
module: stats
elapsed: 59.99997
{total_bots_connected,1}: 17961
{bots_connected,1}: 9057
{games_launched,1}: 1811
=INFO REPORT==== 30-Oct-2008::20:52:59 ===
module: stats
elapsed: 60.000001
{total_bots_connected,2}: 24494
{bots_connected,2}: 6533
{games_launched,2}: 1198
barrier: reached target of 5000
50 games finished
50 games finished
=INFO REPORT==== 30-Oct-2008::20:53:59 ===
module: stats
elapsed: 59.996606
{total_bots_connected,3}: 25404
{total_bots_disconnected,3}: 742
{total_games_ended,3}: 188
{total_games_started,3}: 5000
50 games finished
...
1000 games finished
dmb: exited successfully, 269.970918 seconds elapsed
dmb: exited successfully, 269.971041 seconds elapsed
dmb: exited successfully, 269.97109 seconds elapsed
dmb: exited successfully, 269.971134 seconds elapsed
dmb: exited successfully, 269.971178 seconds elapsed
ok
(1@fhm8e4aa)3>
=INFO REPORT==== 30-Oct-2008::20:54:59 ===
module: stats
elapsed: 60.000917
{total_bots_connected,4}: 25404
{total_bots_disconnected,4}: 30404
{total_games_ended,4}: 5000
{total_games_started,4}: 5000
