Erlang单服游戏开发记录4
为了验证高并发下gen_server的处理性能,写了一个测试程序,如下:
1 -module(testserver).
2
3 -behaviour(gen_server).
4 -export([start_link/0]).
5
6
7 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
8
9 -record(state, {users}).
10 -record(user,{id,pid}).
11
12 start_link() ->
13 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
14
15
16 init([]) ->
17 process_flag(trap_exit, true),
18 {ok, #state{users=[]}}.
19
20 handle_call(Request, From, State) ->
21 do_call(Request, From, State).
22
23
24 do_call({join}, From, #state{users = Users} = State) ->
25 User = #user{pid=element(1,From)},
26 NewUsers = [User|Users],
27 erlang:statistics(runtime),
28 erlang:statistics(wall_clock),
29 broadcast({join_hall,{"abcd","abcd","abcd","abcd","abcd","abcd"}},Users),
30 {_, T1} = erlang:statistics(runtime),
31 {_, T2} = erlang:statistics(wall_clock),
32 io:format("Run Time:~p Clock:~p~n",[T1,T2]),
33 {reply, ok, State#state{users=NewUsers}}.
34
35
36 handle_cast(_Msg, State) ->
37 {noreply, State}.
38
39
40 handle_info(_Info, State) ->
41 {noreply, State}.
42
43
44 terminate(_Reason, _State) ->
45 ok.
46
47
48 code_change(_OldVsn, State, _Extra) ->
49 {ok, State}.
50
51
52
53 broadcast(Msg,Users) ->
54 % 通知大厅内其他用户
55 lists:foreach(
56 fun(User) ->
57 Pid = User#user.pid,
58 Pid ! Msg
59 end, Users).
2
3 -behaviour(gen_server).
4 -export([start_link/0]).
5
6
7 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
8
9 -record(state, {users}).
10 -record(user,{id,pid}).
11
12 start_link() ->
13 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
14
15
16 init([]) ->
17 process_flag(trap_exit, true),
18 {ok, #state{users=[]}}.
19
20 handle_call(Request, From, State) ->
21 do_call(Request, From, State).
22
23
24 do_call({join}, From, #state{users = Users} = State) ->
25 User = #user{pid=element(1,From)},
26 NewUsers = [User|Users],
27 erlang:statistics(runtime),
28 erlang:statistics(wall_clock),
29 broadcast({join_hall,{"abcd","abcd","abcd","abcd","abcd","abcd"}},Users),
30 {_, T1} = erlang:statistics(runtime),
31 {_, T2} = erlang:statistics(wall_clock),
32 io:format("Run Time:~p Clock:~p~n",[T1,T2]),
33 {reply, ok, State#state{users=NewUsers}}.
34
35
36 handle_cast(_Msg, State) ->
37 {noreply, State}.
38
39
40 handle_info(_Info, State) ->
41 {noreply, State}.
42
43
44 terminate(_Reason, _State) ->
45 ok.
46
47
48 code_change(_OldVsn, State, _Extra) ->
49 {ok, State}.
50
51
52
53 broadcast(Msg,Users) ->
54 % 通知大厅内其他用户
55 lists:foreach(
56 fun(User) ->
57 Pid = User#user.pid,
58 Pid ! Msg
59 end, Users).
测试代码如下:
-module(test).
-export([test/1,join/0]).
test(0) ->
finish;
test(A) ->
proc_lib:spawn(?MODULE, join, []),
test(A-1).
join() ->
gen_server:call({testserver,'server@127.0.0.1'}, {join}).
-export([test/1,join/0]).
test(0) ->
finish;
test(A) ->
proc_lib:spawn(?MODULE, join, []),
test(A-1).
join() ->
gen_server:call({testserver,'server@127.0.0.1'}, {join}).
测试结果:
Run Time:47 Clock:483
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:15
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:78 Clock:484
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:15
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:78 Clock:484
把服务和测试程序放在一个节点内,测试结果:
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:16
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:16
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:16
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:0
Run Time:0 Clock:16
由此得出,跨节点通信是造成高并发性能瓶颈的真正原因, 节点通信是通过epmd进行的,而这么多消息通过节点,其耗时也是巨大的。