%%% -------------------------------------------------------
|
|
%%% @author huangyongxing@yeah.net
|
|
%%% @doc
|
|
%%% 简单的性能测试工具,匿名函数的影响有限,
|
|
%%% 但是方便不修改工具直接外部添加测试用例进行对比使用,
|
|
%%% 所以忽略匿名函数对测试结果的影响,做基本的性能判断
|
|
%%%
|
|
%%% 对比测试方式:
|
|
%%% ptester:run(Times, [
|
|
%%% {Fun1Label, Fun1/1},
|
|
%%% {Fun2Label, Fun2/1},
|
|
%%% ...
|
|
%%% ]).
|
|
%%% 单个函数测试:
|
|
%%% ptester:timer(FunLabel, Fun/1, Times).
|
|
%%% @end
|
|
%%% -------------------------------------------------------
|
|
-module(ptester).
|
|
-compile(export_all).
|
|
|
|
%% 运行一个测试集
|
|
run(N, List) ->
|
|
[[L, T1, T2] = H | T] = [timer(Label, F, N) || {Label, F} <- List],
|
|
io:format("========================================================================~n"),
|
|
io:format("~20s = ~9.2fms [~8.2f%] ~9.2fms [~8.2f%]~n", [L, T1 + 0.0, 100.0, T2 + 0.0, 100.0]),
|
|
compare(T, H),
|
|
io:format("========================================================================~n").
|
|
|
|
%% 运行单项测试并计时
|
|
timer(Label, F, N) ->
|
|
% WordSize = erlang:system_info(wordsize),
|
|
% 分配较大的初始空间,减少gc对测试结果的影响,以期获得更准确的结果
|
|
% MinHeapSize = 20 * 1024 * 1024,
|
|
% MinBinVHeapSize = MinHeapSize,
|
|
% erlang:process_flag(min_heap_size, MinHeapSize),
|
|
% erlang:process_flag(min_bin_vheap_size, MinBinVHeapSize),
|
|
% 先进行gc一次,避免多个函数测试时,上一次的测试对进程gc的相关影响
|
|
erlang:garbage_collect(self()),
|
|
statistics(runtime),
|
|
statistics(wall_clock),
|
|
for(1, N, F),
|
|
{_, Time1} = statistics(runtime),
|
|
{_, Time2} = statistics(wall_clock),
|
|
U1 = Time1 * 1000 / N,
|
|
U2 = Time2 * 1000 / N,
|
|
io:format("~p [total: ~p(~p)ms avg: ~.3f(~.3f)us]~n", [Label, Time1, Time2, U1, U2]),
|
|
[Label, Time1, Time2].
|
|
|
|
%% 比较结果
|
|
compare([], _) ->
|
|
ok;
|
|
compare([[L, T1, T2] | T], [_, TB1, TB2] = TB) ->
|
|
io:format(
|
|
"~20s = ~9.2fms [~8.2f%] ~9.2fms [~8.2f%]~n",
|
|
[L, T1 + 0.0, T1 / (TB1 + 0.00000001) * 100, T2 + 0.0, T2 / (TB2 + 0.00000001) * 100]
|
|
),
|
|
compare(T, TB).
|
|
|
|
%% for循环
|
|
for(Max, Max, F) -> F(Max);
|
|
for(I, Max, F) -> F(I), for(I + 1, Max, F).
|
|
|
|
%% 产生随机数
|
|
rand(Same, Same) -> Same;
|
|
rand(Min, Max) when Max < Min ->
|
|
rand(Max, Min);
|
|
rand(Min, Max) ->
|
|
case get("rand_seed") of
|
|
undefined ->
|
|
RandSeed = os:timestamp(),
|
|
rand:seed(RandSeed),
|
|
put("rand_seed", RandSeed);
|
|
_ ->
|
|
skip
|
|
end,
|
|
M = Min - 1,
|
|
rand:uniform(Max - M) + M.
|
|
|