refactor(erlang): simplify benchmark output to ms/QPS and add CPU clock info
This commit is contained in:
parent
d189535bb8
commit
a1667d1182
|
|
@ -154,55 +154,31 @@ $ make bench-v6
|
||||||
#### IPv4 benchmark example
|
#### IPv4 benchmark example
|
||||||
|
|
||||||
```
|
```
|
||||||
CPU info:
|
System:
|
||||||
model name : Apple M4
|
CPU : Apple M4
|
||||||
cores/threads : 10/10
|
Cores : 10 cores / 10 threads
|
||||||
|
Erlang : Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
||||||
|
Loaded : 487169 IPs in 1.574 s
|
||||||
|
|
||||||
Erlang info:
|
Benchmarks:
|
||||||
system_version:Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
file total= 9.460s count= 487169 qps= 51500.40 avg= 0.019417 ms/op (19.417 us/op)
|
||||||
load test data use 1.34496s
|
cache total= 0.150s count= 487169 qps= 3245240.41 avg= 0.000308 ms/op ( 0.308 us/op)
|
||||||
|
|
||||||
start run benchmark tests
|
Done.
|
||||||
|
|
||||||
search from file:
|
|
||||||
ip count:487169,
|
|
||||||
total time: 11.564375s,
|
|
||||||
search 42126.70377776577 times per second,
|
|
||||||
use 23.737912305585947 micro second per search
|
|
||||||
|
|
||||||
search from cache:
|
|
||||||
ip count:487169,
|
|
||||||
total time: 0.213552s,
|
|
||||||
search 2281266.389450813 times per second,
|
|
||||||
use 0.43835301507279817 micro second per search
|
|
||||||
|
|
||||||
benchmark test finish
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### IPv6 benchmark example
|
#### IPv6 benchmark example
|
||||||
|
|
||||||
```
|
```
|
||||||
CPU info:
|
System:
|
||||||
model name : Apple M4
|
CPU : Apple M4
|
||||||
cores/threads : 10/10
|
Cores : 10 cores / 10 threads
|
||||||
|
Erlang : Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
||||||
|
Loaded : 638953 IPs in 2.724 s
|
||||||
|
|
||||||
Erlang info:
|
Benchmarks:
|
||||||
system_version:Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
file total= 16.326s count= 638953 qps= 39137.65 avg= 0.025551 ms/op (25.551 us/op)
|
||||||
load test data use 2.472659s
|
cache total= 0.469s count= 638953 qps= 1361972.38 avg= 0.000734 ms/op ( 0.734 us/op)
|
||||||
|
|
||||||
start run benchmark tests
|
Done.
|
||||||
|
|
||||||
search from file:
|
|
||||||
ip count:638953,
|
|
||||||
total time: 18.463896s,
|
|
||||||
search 34605.535039842085 times per second,
|
|
||||||
use 28.897111368128797 micro second per search
|
|
||||||
|
|
||||||
search from cache:
|
|
||||||
ip count:638953,
|
|
||||||
total time: 0.541899s,
|
|
||||||
search 1179099.7953493178 times per second,
|
|
||||||
use 0.8481046336741513 micro second per search
|
|
||||||
|
|
||||||
benchmark test finish
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -131,55 +131,31 @@ $ make bench-v6
|
||||||
#### IPv4 基准测试示例
|
#### IPv4 基准测试示例
|
||||||
|
|
||||||
```
|
```
|
||||||
CPU info:
|
System:
|
||||||
model name : Apple M4
|
CPU : Apple M4
|
||||||
cores/threads : 10/10
|
Cores : 10 cores / 10 threads
|
||||||
|
Erlang : Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
||||||
|
Loaded : 487169 IPs in 1.574 s
|
||||||
|
|
||||||
Erlang info:
|
Benchmarks:
|
||||||
system_version:Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
file total= 9.460s count= 487169 qps= 51500.40 avg= 0.019417 ms/op (19.417 us/op)
|
||||||
load test data use 1.34496s
|
cache total= 0.150s count= 487169 qps= 3245240.41 avg= 0.000308 ms/op ( 0.308 us/op)
|
||||||
|
|
||||||
start run benchmark tests
|
Done.
|
||||||
|
|
||||||
search from file:
|
|
||||||
ip count:487169,
|
|
||||||
total time: 11.564375s,
|
|
||||||
search 42126.70377776577 times per second,
|
|
||||||
use 23.737912305585947 micro second per search
|
|
||||||
|
|
||||||
search from cache:
|
|
||||||
ip count:487169,
|
|
||||||
total time: 0.213552s,
|
|
||||||
search 2281266.389450813 times per second,
|
|
||||||
use 0.43835301507279817 micro second per search
|
|
||||||
|
|
||||||
benchmark test finish
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### IPv6 基准测试示例
|
#### IPv6 基准测试示例
|
||||||
|
|
||||||
```
|
```
|
||||||
CPU info:
|
System:
|
||||||
model name : Apple M4
|
CPU : Apple M4
|
||||||
cores/threads : 10/10
|
Cores : 10 cores / 10 threads
|
||||||
|
Erlang : Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
||||||
|
Loaded : 638953 IPs in 2.724 s
|
||||||
|
|
||||||
Erlang info:
|
Benchmarks:
|
||||||
system_version:Erlang/OTP 29 [erts-17.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
|
file total= 16.326s count= 638953 qps= 39137.65 avg= 0.025551 ms/op (25.551 us/op)
|
||||||
load test data use 2.472659s
|
cache total= 0.469s count= 638953 qps= 1361972.38 avg= 0.000734 ms/op ( 0.734 us/op)
|
||||||
|
|
||||||
start run benchmark tests
|
Done.
|
||||||
|
|
||||||
search from file:
|
|
||||||
ip count:638953,
|
|
||||||
total time: 18.463896s,
|
|
||||||
search 34605.535039842085 times per second,
|
|
||||||
use 28.897111368128797 micro second per search
|
|
||||||
|
|
||||||
search from cache:
|
|
||||||
ip count:638953,
|
|
||||||
total time: 0.541899s,
|
|
||||||
search 1179099.7953493178 times per second,
|
|
||||||
use 0.8481046336741513 micro second per search
|
|
||||||
|
|
||||||
benchmark test finish
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,6 @@ init:stop()."
|
||||||
# shellcheck disable=SC2090
|
# shellcheck disable=SC2090
|
||||||
erl -pa _build/default/lib/poolboy/ebin \
|
erl -pa _build/default/lib/poolboy/ebin \
|
||||||
-pa _build/default/lib/ip2region/ebin \
|
-pa _build/default/lib/ip2region/ebin \
|
||||||
|
-kernel logger_level error \
|
||||||
-noshell \
|
-noshell \
|
||||||
-eval "${EVAL}"
|
-eval "${EVAL}"
|
||||||
|
|
|
||||||
|
|
@ -11,30 +11,76 @@
|
||||||
-export([main/1]).
|
-export([main/1]).
|
||||||
|
|
||||||
main(DataFile) ->
|
main(DataFile) ->
|
||||||
|
%% Keep benchmark output clean while still surfacing real errors.
|
||||||
|
_ = logger:set_handler_config(default, level, error),
|
||||||
|
_ = logger:set_primary_config(level, error),
|
||||||
application:ensure_started(ip2region),
|
application:ensure_started(ip2region),
|
||||||
show_hw_sw_info(),
|
show_hw_sw_info(),
|
||||||
IpList = load_test_data(DataFile),
|
IpList = load_test_data(DataFile),
|
||||||
run(IpList).
|
run(IpList).
|
||||||
|
|
||||||
show_hw_sw_info() ->
|
show_hw_sw_info() ->
|
||||||
io:format("CPU info:~n", []),
|
{Model, Clock, Cores, Threads} = cpu_info(),
|
||||||
|
io:format("~nSystem:~n", []),
|
||||||
|
io:format(" CPU : ~s", [Model]),
|
||||||
|
case Clock of
|
||||||
|
"" -> io:format("~n", []);
|
||||||
|
_ -> io:format(" @ ~s~n", [Clock])
|
||||||
|
end,
|
||||||
|
io:format(" Cores : ~s cores / ~s threads~n", [Cores, Threads]),
|
||||||
|
io:format(" Erlang : ~s~n", [string:trim(erlang:system_info(system_version))]),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
cpu_info() ->
|
||||||
case os:type() of
|
case os:type() of
|
||||||
{unix, darwin} ->
|
{unix, darwin} ->
|
||||||
io:format("model name : ~s~n", [string:trim(os:cmd("sysctl -n machdep.cpu.brand_string 2>/dev/null"))]),
|
Model = sysctl("machdep.cpu.brand_string"),
|
||||||
io:format("cores/threads : ~s/~s~n", [string:trim(os:cmd("sysctl -n hw.physicalcpu 2>/dev/null")),
|
Clock = first_non_empty([
|
||||||
string:trim(os:cmd("sysctl -n hw.logicalcpu 2>/dev/null"))]);
|
format_clock(sysctl("hw.cpufrequency")),
|
||||||
|
format_clock(sysctl("hw.perflevel0.frequency")),
|
||||||
|
format_clock(sysctl("hw.perflevel1.frequency"))
|
||||||
|
]),
|
||||||
|
Cores = sysctl("hw.physicalcpu"),
|
||||||
|
Threads = sysctl("hw.logicalcpu"),
|
||||||
|
{Model, Clock, Cores, Threads};
|
||||||
{unix, linux} ->
|
{unix, linux} ->
|
||||||
io:format("~s", [os:cmd("egrep '^model name' /proc/cpuinfo | head -1")]),
|
Model = linux_cpu_field("model name"),
|
||||||
io:format("~s", [os:cmd("egrep '^cache' /proc/cpuinfo | head -1")]),
|
Clock = format_clock_mhz(linux_cpu_field("cpu MHz")),
|
||||||
io:format("~s", [os:cmd("egrep '^cpu MHz' /proc/cpuinfo | head -1")]),
|
Cores = trim(os:cmd("grep -c '^processor' /proc/cpuinfo 2>/dev/null")),
|
||||||
io:format("~s", [os:cmd("egrep '^bogomips' /proc/cpuinfo | head -1")]),
|
Threads = Cores,
|
||||||
io:format("cores/threads : ~s~n", [os:cmd("egrep -c '^processor' /proc/cpuinfo")]);
|
{Model, Clock, Cores, Threads};
|
||||||
_ ->
|
_ ->
|
||||||
io:format("unsupported os~n", [])
|
{"unknown", "", "?", "?"}
|
||||||
end,
|
end.
|
||||||
io:format("Erlang info:~n", []),
|
|
||||||
io:format("system_version:~s", [erlang:system_info(system_version)]),
|
sysctl(Key) ->
|
||||||
ok.
|
trim(os:cmd("sysctl -n " ++ Key ++ " 2>/dev/null")).
|
||||||
|
|
||||||
|
linux_cpu_field(Key) ->
|
||||||
|
Cmd = "grep -m1 '^" ++ Key ++ "' /proc/cpuinfo 2>/dev/null | cut -d: -f2- | sed 's/^ *//'",
|
||||||
|
trim(os:cmd(Cmd)).
|
||||||
|
|
||||||
|
first_non_empty(["" | Rest]) -> first_non_empty(Rest);
|
||||||
|
first_non_empty([Val | _]) -> Val;
|
||||||
|
first_non_empty([]) -> "".
|
||||||
|
|
||||||
|
format_clock(HzStr) ->
|
||||||
|
case string:to_integer(trim(HzStr)) of
|
||||||
|
{ok, Hz, _} when Hz > 1000000000 ->
|
||||||
|
lists:flatten(io_lib:format("~.2f GHz", [Hz / 1000000000]));
|
||||||
|
{ok, Hz, _} when Hz > 1000000 ->
|
||||||
|
lists:flatten(io_lib:format("~.2f GHz", [Hz / 1000000000]));
|
||||||
|
_ ->
|
||||||
|
""
|
||||||
|
end.
|
||||||
|
|
||||||
|
format_clock_mhz(MhzStr) ->
|
||||||
|
case string:to_float(trim(MhzStr)) of
|
||||||
|
{ok, Mhz, _} ->
|
||||||
|
lists:flatten(io_lib:format("~.3f GHz", [Mhz / 1000]));
|
||||||
|
_ ->
|
||||||
|
""
|
||||||
|
end.
|
||||||
|
|
||||||
load_test_data(DataFile) ->
|
load_test_data(DataFile) ->
|
||||||
{ok, Fd} = file:open(DataFile, [read]),
|
{ok, Fd} = file:open(DataFile, [read]),
|
||||||
|
|
@ -42,7 +88,7 @@ load_test_data(DataFile) ->
|
||||||
IpList = load_test_data(Fd, []),
|
IpList = load_test_data(Fd, []),
|
||||||
T1 = os:timestamp(),
|
T1 = os:timestamp(),
|
||||||
Sec = timer:now_diff(T1, T0) / 1000000,
|
Sec = timer:now_diff(T1, T0) / 1000000,
|
||||||
io:format("load test data use ~ps~n", [Sec]),
|
io:format(" Loaded : ~p IPs in ~.3f s~n", [length(IpList), Sec]),
|
||||||
IpList.
|
IpList.
|
||||||
|
|
||||||
load_test_data(Fd, IpList) ->
|
load_test_data(Fd, IpList) ->
|
||||||
|
|
@ -61,24 +107,26 @@ load_test_data(Fd, IpList) ->
|
||||||
|
|
||||||
run(IpList) ->
|
run(IpList) ->
|
||||||
garbage_collect(),
|
garbage_collect(),
|
||||||
io:format("~nstart run benchmark tests~n", []),
|
io:format("~nBenchmarks:~n", []),
|
||||||
io:format("~nsearch from file:~n", []),
|
run_test("file", IpList),
|
||||||
run_test(IpList),
|
run_test("cache", IpList),
|
||||||
io:format("~nsearch from cache:~n", []),
|
io:format("~nDone.~n", []).
|
||||||
run_test(IpList),
|
|
||||||
io:format("~nbenchmark test finish~n", []).
|
|
||||||
|
|
||||||
run_test(IpList) ->
|
run_test(Label, IpList) ->
|
||||||
T0 = os:timestamp(),
|
T0 = os:timestamp(),
|
||||||
run_test_aux(IpList),
|
run_test_aux(IpList),
|
||||||
T1 = os:timestamp(),
|
T1 = os:timestamp(),
|
||||||
Sec = timer:now_diff(T1, T0) / 1000000,
|
Sec = timer:now_diff(T1, T0) / 1000000,
|
||||||
IpCount = length(IpList),
|
Count = length(IpList),
|
||||||
io:format("ip count:~p,~ntotal time: ~ps,~nsearch ~p times per second,~nuse ~p micro second per search~n",
|
Qps = Count / Sec,
|
||||||
[IpCount, Sec, IpCount / Sec, Sec * 1000000/IpCount]).
|
MsOp = Sec * 1000 / Count,
|
||||||
|
UsOp = Sec * 1000000 / Count,
|
||||||
|
io:format(" ~-8s total=~7.3fs count=~7w qps=~12.2f avg=~9.6f ms/op (~6.3f us/op)~n",
|
||||||
|
[Label, Sec, Count, Qps, MsOp, UsOp]).
|
||||||
|
|
||||||
run_test_aux([]) -> ok;
|
run_test_aux([]) -> ok;
|
||||||
run_test_aux([Ip | Tail]) ->
|
run_test_aux([Ip | Tail]) ->
|
||||||
xdb:search(Ip),
|
xdb:search(Ip),
|
||||||
run_test_aux(Tail).
|
run_test_aux(Tail).
|
||||||
|
|
||||||
|
trim(Str) -> string:trim(Str).
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue