原创文章,转载请注明: 转载自庆亮的博客-webgame架构

本文链接地址: mnesia脏读与事物读性能结果

一直知道mnesia的事务比较慢,但慢到什么程度却没有一个数值的概念,今天正好有空测试一下。

上代码:

-module(mnesia_read_test).

-export([start/0, init_data/0, start2/0]).

-record(r_test, {id, name}).

start() ->

        statistics(wall_clock),

    statistics(runtime),

        read(),

        {_, Time1} = statistics(wall_clock),

    {_, Time2} = statistics(runtime),

    io:format("times:~p, wall_clock ~p, runtime:~p", [100000, Time1, Time2]).

 

start2() ->

        statistics(wall_clock),

    statistics(runtime),

        read2(),

        {_, Time1} = statistics(wall_clock),

    {_, Time2} = statistics(runtime),

    io:format("times:~p, wall_clock ~p, runtime:~p", [100000, Time1, Time2]).

 

read() ->

        dirty_read(100000).

dirty_read(0) ->

    ok;

dirty_read(N) ->

    mnesia:dirty_read(r_test, N),

    dirty_read(N-1).

 

read2() ->

        t_read(100000).

 

t_read(0) ->

        ok;

t_read(N) ->

        mnesia:transaction( fun() -> mnesia:read(r_test, N) end),

        t_read(N-1).

 

init_data() ->

    mnesia:stop(),

    mnesia:create_schema([node()]),

    mnesia:start(),

    mnesia:create_table(r_test, [

                               {attributes, record_info(fields, r_test)},

                               {record_name, r_test},

                               {disc_copies, [node()]}

                               ]),

    mnesia:transaction(

        fun() ->

            t_write(10000)

        end

    ).

t_write(0) ->

    ok;

t_write(N) ->

    Name = lists:append(["name_", N]),

    R = #r_test{id=N, name=Name},

    mnesia:write(R),

    t_write(N-1).

 

两种情况都循环读了10W次,连续测试10次,机器配置为:

Intel(R) Xeon(R) CPU           E5420  @ 2.50GHz      2*4核

12G内存

事务读测试结果:

times:100000, wall_clock 4168, runtime:4160ok

times:100000, wall_clock 4296, runtime:4250ok

times:100000, wall_clock 4338, runtime:4290ok

times:100000, wall_clock 4310, runtime:4260ok

times:100000, wall_clock 4330, runtime:4280ok

times:100000, wall_clock 4342, runtime:4270ok

times:100000, wall_clock 4399, runtime:4310ok

times:100000, wall_clock 4366, runtime:4310ok

times:100000, wall_clock 4378, runtime:4310ok

times:100000, wall_clock 4429, runtime:4330ok

一次读的时间大于为44us,这还是在没有分布式的情况下的测试结果,如果是在分布式环境中,由于网络IO和远程加锁,性能会更差。

脏读测试结果:

 

times:100000, wall_clock 128, runtime:130ok

times:100000, wall_clock 126, runtime:120ok

times:100000, wall_clock 124, runtime:120ok

times:100000, wall_clock 126, runtime:120ok

times:100000, wall_clock 127, runtime:130ok

times:100000, wall_clock 125, runtime:130ok

times:100000, wall_clock 125, runtime:120ok

times:100000, wall_clock 127, runtime:120ok

times:100000, wall_clock 128, runtime:130ok

times:100000, wall_clock 127, runtime:130ok

和ets的性能几乎一样,一次读取的消耗大约1.2us,和事务相比快了几十倍。追踪脏读源码到mnesia_lib.erl中:

db_get(TabKey) ->

    db_get(val({Tab, storage_type}), TabKey).

db_get(ram_copies, TabKey) -> ?ets_lookup(TabKey);

db_get(disc_copies, TabKey) -> ?ets_lookup(TabKey);

db_get(disc_only_copies, TabKey) -> dets:lookup(TabKey).

呵呵,果然是ets直接操作。