Current section

Files

Jump to
erlcass benchmarks load_test.erl
Raw

benchmarks/load_test.erl

-module(load_test).
-include("erlcass.hrl").
-export([
profile/2,
profile/3,
prepare_load_test_table/0
]).
-define(KEYSPACE, <<"load_test_erlcass">>).
-define(QUERY, {<<"SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14 FROM test_table WHERE col1 =?">>, ?CASS_CONSISTENCY_ONE}).
-define(QUERY_ARGS, [<<"hello">>]).
-define(CLUSTER_NAME, <<"dc-beta">>).
start() ->
case application:ensure_all_started(erlcass) of
{ok, [_|_]} ->
ok;
UnexpectedError ->
UnexpectedError
end.
prepare_load_test_table() ->
start(),
erlcass:query(<<"DROP KEYSPACE ", (?KEYSPACE)/binary>>),
ok = erlcass:query(<<"CREATE KEYSPACE ", (?KEYSPACE)/binary, " WITH replication = {'class': 'NetworkTopologyStrategy', '", (?CLUSTER_NAME)/binary, "': 3 }">>),
Cols = datatypes_columns([ascii, bigint, blob, boolean, decimal, double, float, int, timestamp, uuid, varchar, varint, timeuuid, inet]),
Sql = <<"CREATE TABLE ", (?KEYSPACE)/binary, ".test_table(", Cols/binary, " PRIMARY KEY(col1));">>,
io:format(<<"exec: ~p ~n">>,[Sql]),
ok = erlcass:query(Sql),
InsertQuery = <<"INSERT INTO ", (?KEYSPACE)/binary, ".test_table(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)">>,
ok = erlcass:add_prepare_statement(add_load_test_record, InsertQuery),
AsciiValBin = <<"hello">>,
BigIntPositive = 9223372036854775807,
Blob = <<1,2,3,4,5,6,7,8,9,10>>,
BooleanTrue = true,
DecimalPositive = {erlang:integer_to_binary(1234), 5},
DoublePositive = 5.1235131241221e-6,
FloatPositive = 5.12351e-6,
IntPositive = 2147483647,
Timestamp = 2147483647,
{ok, Uuid} = erlcass_uuid:gen_random(),
Varchar1 = <<"Юникод"/utf8>>,
Varint1 = erlang:integer_to_binary(1928301970128391280192830198049113123),
{ok, Timeuuid} = erlcass_uuid:gen_time(),
Inet = <<"127.0.0.1">>,
ok = erlcass:execute(add_load_test_record, [
AsciiValBin,
BigIntPositive,
Blob,
BooleanTrue,
DecimalPositive,
DoublePositive,
FloatPositive,
IntPositive,
Timestamp,
Uuid,
Varchar1,
Varint1,
Timeuuid,
Inet
]).
profile(NrProc, RequestsNr) ->
start(),
profile(NrProc, RequestsNr, 1).
profile(NrProc, RequestsNr, RepeatNumber) ->
start(),
Fun = fun() -> do_profiling(NrProc, RequestsNr, RepeatNumber) end,
spawn(Fun).
do_profiling(NrProc, RequestsNr, RepeatNumber) ->
erlcass:add_prepare_statement(execute_query, ?QUERY),
eprof:start(),
eprof:start_profiling([self()]),
ok = application:set_env(erlcass, keyspace, ?KEYSPACE),
start(),
ProcsList = lists:seq(1, NrProc),
{Time, _} = timer:tc( fun() -> run_test(RepeatNumber, NrProc, RequestsNr, ProcsList) end),
io:format("Cpp Driver Metrics: ~p ~n", [erlcass:get_metrics()]),
eprof:stop_profiling(),
eprof:analyze(total),
io:format("Time to complete: ~p ms ~n", [Time/1000]).
run_test(0, _NrProc, _RequestsNr, _ProcsList) ->
ok;
run_test(RepeatNr, NrProc, RequestsNr, ProcsList) ->
load_test(NrProc, RequestsNr, ProcsList),
run_test(RepeatNr -1, NrProc, RequestsNr, ProcsList).
load_test(1, NrReq, _ProcsList) ->
producer_loop(NrReq),
consumer_loop(0, 0, 0, NrReq);
load_test(NrProcesses, NrReq, ProcsList) ->
ReqPerProcess = round(NrReq/NrProcesses),
Self = self(),
Fun = fun() ->
producer_loop(ReqPerProcess),
consumer_loop(0, 0, 0, ReqPerProcess),
Self ! {self(), done}
end,
wait_finish(Fun, ProcsList).
wait_finish(Fun, ProcsList) ->
Pids = [spawn_link(Fun) || _ <- ProcsList],
[receive {Pid, done} -> ok end || Pid <- Pids],
ok.
consumer_loop(TotalResults, SuccessResults, FailedResults, 0) ->
io:format("**** Test Completed => results: ~p success: ~p failed: ~p **** ~n",[TotalResults, SuccessResults, FailedResults]),
ok;
consumer_loop(TotalResults, SuccessResults, FailedResults, LimitReq) ->
receive
%success results
{execute_statement_result, _Tag, {ok, _Cols, _Rows}} ->
%io:format("Result:~p ~n", [Result]),
display_progress(TotalResults),
consumer_loop(TotalResults +1 , SuccessResults +1, FailedResults, LimitReq -1);
%failed results
{execute_statement_result, _Tag, Result} ->
io:format("Result:~p ~n", [Result]),
display_progress(TotalResults),
consumer_loop(TotalResults +1 , SuccessResults, FailedResults + 1, LimitReq -1)
end.
producer_loop(0) ->
ok;
producer_loop(NumRequests) ->
erlcass:async_execute(execute_query, ?QUERY_ARGS),
producer_loop(NumRequests -1).
display_progress(Results) ->
if
Results rem 10000 =:= 0 ->
io:format("Executed ~p requests ~n", [Results]);
true ->
ok
end.
datatypes_columns(Cols) ->
datatypes_columns(1, Cols, <<>>).
datatypes_columns(_I, [], Bin) -> Bin;
datatypes_columns(I, [ColumnType|Rest], Bin) ->
Column = list_to_binary(io_lib:format("col~B ~s, ", [I, ColumnType])),
datatypes_columns(I+1, Rest, << Bin/binary, Column/binary >>).