Erlang中本地和远程ETS表操作的性能比较

分享实验ErlangETS by 达达 at 2011-02-21

早上在路上想到一个idea,在每台游戏服务器上运行一个数据节点 + 多个游戏逻辑节点,两台服务器只需要在两个数据节点间同步数据,最小化数据同步量。到了公司快速做了一个测试,比较了一下直接ets表插入和通过rpc:call调用的ets表插入的性能,下面是测试代码。

-module(ets_test).
-export([
    local/0,
    remote/0,
    remote_start/0,
    remote_init/0,
    remote_call/1
]).

-define(TIMES, 100000).
-define(TEST_DATA, {<<I:128>>}).
-define(MASTER_NODE, 'master@192.168.1.120').

local()->
    ets:new(test_table, [private, set, named_table]),
    statistics(wall_clock),
    Fun = fun(I) ->
        ets:insert(test_table, ?TEST_DATA)
    end,
    for(?TIMES, Fun),
    {_, Time} = statistics(wall_clock),
    io:format("Time: ~pms~n", [Time]).

remote()->
    net_adm:ping(?MASTER_NODE),
    statistics(wall_clock),
    Fun = fun(I)->
        rpc:call(?MASTER_NODE, ?MODULE, remote_call, [?TEST_DATA])
    end,
    for(?TIMES, Fun),
    {_, Time} = statistics(wall_clock),
    io:format("Time: ~pms~n", [Time]).

remote_start()->
    proc_lib:spawn(?MODULE, remote_init, []),
    ok.

remote_init()->
    register(remote_proc, self()),
    ets:new(test_table, [private, set, named_table]),
    remote_proc().

remote_proc()->
    receive
        {insert, Pid, Data} ->
            ets:insert(test_table, Data),
            Pid ! ok,
            remote_proc()
    end.

remote_call(Data)->
    remote_proc ! {insert, self(), Data},
    receive ok -> ok end.

for(0, _)-> ok;
for(N, Fun)-> Fun(N), for(N - 1, Fun).

执行本地直接插入测试的脚本:

#!/bin/sh
erl -noshell -s ets_test local -s init stop

测试10w数据插入耗时140ms。

执行远程插入测试需要先启动一个master节点,再启动一个slave节点。

master节点的启动脚本:

#!/bin/sh
erl -name master@192.168.1.120 -setcookie the_cookie -s ets_test remote_start

slave节点的测试脚本:

#!/bin/sh
erl -noshell -name slave@192.168.1.120 -setcookie the_cookie -s ets_test remote -s init stop

测试10w数据插入耗时21s。

140ms和21s,两者性能相差巨大。