From be9bf3ebaa66644d286fd2cd073f9e2dc1f78f9d Mon Sep 17 00:00:00 2001 From: Dmitry Kolesnikov Date: Thu, 19 Nov 2015 20:55:19 +0200 Subject: [PATCH 1/3] a proxy driver to benchmark remote system --- README.org | 22 +++++++++++ examples/cluster.config | 27 ++++++++++++++ src/basho_bench_driver_cluster.erl | 59 ++++++++++++++++++++++++++++++ src/basho_bench_worker.erl | 5 +++ 4 files changed, 113 insertions(+) create mode 100644 examples/cluster.config create mode 100644 src/basho_bench_driver_cluster.erl diff --git a/README.org b/README.org index 339e297b3..2bf3574de 100644 --- a/README.org +++ b/README.org @@ -122,6 +122,28 @@ $ ./priv/gp_latencies.sh Also, you can plot multiple test runs on a single plot by using "-d" switch. +** Benchmarking Erlang cluster + + A typical benchmark scenario is that Basho Bench spawn Erlang VM and executes the driver inside. However, there is needs to catch performance metrics from an application executed remotely within dedicated environment (e.g. probe performance from live system; benchmark an application inside C or Java node, etc). Bash Bench implements a generic =basho_bench_driver_cluster= that acts as proxy. It uses Erlang distribution to delegate benchmark responsibility to remote actor, which is randomly selected from configured pool. + + Basho Bench do not define how the actors are spawned within SUT. It only defined a communication protocol. The actor is responsible to handle the message: + + ={pid(), atom(), key(), val()}= + + - =pid()= : request originator, actor shall respond to this process + - =atom()= : id of operation to execute as defined in config file + - =key()= : materialized key value as defined by key generator function + - =val()= : materialized value as defined by value generator function + + The actor executes the request, measures performance and respond to originator process =pid()= with one of the message ={ok, microsecond()}= or ={error, reason()}= + + See cluster.config example for details. Use following command to spawn benchmark + +#+BEGIN_SRC shell +./basho_bench -C nocookie -N bb@127.0.0.1 -J erlang@127.0.0.1 examples/cluster.config +#+END_SRC + + ** Contributing We encourage contributions to Basho Bench from the community. diff --git a/examples/cluster.config b/examples/cluster.config new file mode 100644 index 000000000..81b04c467 --- /dev/null +++ b/examples/cluster.config @@ -0,0 +1,27 @@ +%% +%% definition +{log_level, info}. +{report_interval, 1}. +{driver, basho_bench_driver_cluster}. + +%% +%% workload +{mode, max}. +{duration, 1}. +{concurrent, 10}. +{key_generator, {int_to_bin_bigendian, {uniform_int, 10000}}}. +{value_generator, {fixed_bin, 1000}}. + +{operations, [ + {put, 1} + ,{get, 1} +]}. + +%% +%% config +{cluster_actors, [ + {a, 'erlang@127.0.0.1'} + {b, 'erlang@127.0.0.1'} + {c, 'gnalre@127.0.0.1'} +]}. + diff --git a/src/basho_bench_driver_cluster.erl b/src/basho_bench_driver_cluster.erl new file mode 100644 index 000000000..0267c6030 --- /dev/null +++ b/src/basho_bench_driver_cluster.erl @@ -0,0 +1,59 @@ +%% ------------------------------------------------------------------- +%% +%% basho_bench: benchmark service on any within Erlang cluster +%% using distribution protocol +%% +%% Copyright (c) 2015 Dmitry Kolesnikov +%% +%% This file is provided to you under the Apache License, +%% Version 2.0 (the "License"); you may not use this file +%% except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, +%% software distributed under the License is distributed on an +%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%% KIND, either express or implied. See the License for the +%% specific language governing permissions and limitations +%% under the License. +%% +%% ------------------------------------------------------------------- +-module(basho_bench_driver_cluster). + +-export([ + new/1, + run/4 +]). + +-record(state, {actor}). + +%% ==================================================================== +%% API +%% ==================================================================== + +new(Id) -> + Actors = basho_bench_config:get(cluster_actors, []), + {Name, Node} = Actor = lists:nth(random:uniform(length(Actors)), Actors), + case net_adm:ping(Node) of + pang -> + lager:error("~s is not available", [Node]), + {ok, #state{actor = undefined}}; + + pong -> + lager:info("worker ~b is bound to ~s on ~s", [Id, Name, Node]), + {ok, #state{actor = Actor}} + end. + +run(Run, KeyGen, ValGen, #state{actor = Actor}=State) -> + Key = KeyGen(), + Val = ValGen(), + erlang:send(Actor, {self(), Run, Key, Val}), + receive + {ok, ElapsedT} -> + {ok, ElapsedT, State}; + + {error, Reason} -> + {error, Reason} + end. diff --git a/src/basho_bench_worker.erl b/src/basho_bench_worker.erl index bd3bf9a30..2681f98ca 100644 --- a/src/basho_bench_worker.erl +++ b/src/basho_bench_worker.erl @@ -265,6 +265,11 @@ worker_next_op(State) -> {Res, DriverState} when Res == silent orelse element(1, Res) == silent -> {ok, State#state { driver_state = DriverState}}; + {ok, ElapsedT, DriverState} -> + %% time is measured by external system + basho_bench_stats:op_complete(Next, ok, ElapsedT), + {ok, State#state { driver_state = DriverState}}; + {error, Reason, DriverState} -> %% Driver encountered a recoverable error basho_bench_stats:op_complete(Next, {error, Reason}, ElapsedUs), From b303e7a75809eefdbdcd6c83cf7f56158e89a939 Mon Sep 17 00:00:00 2001 From: Dmitry Kolesnikov Date: Fri, 4 Dec 2015 18:40:20 +0200 Subject: [PATCH 2/3] use sequential allocation of remote worker in cluster driver --- src/basho_bench_driver_cluster.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basho_bench_driver_cluster.erl b/src/basho_bench_driver_cluster.erl index 0267c6030..66be7b788 100644 --- a/src/basho_bench_driver_cluster.erl +++ b/src/basho_bench_driver_cluster.erl @@ -35,7 +35,8 @@ new(Id) -> Actors = basho_bench_config:get(cluster_actors, []), - {Name, Node} = Actor = lists:nth(random:uniform(length(Actors)), Actors), + Nth = ( Id rem length(Actors) ) + 1, + {Name, Node} = Actor = lists:nth(Nth, Actors), case net_adm:ping(Node) of pang -> lager:error("~s is not available", [Node]), From 4a6c257da31d5766c9b2b25ac549bfa9e0b86440 Mon Sep 17 00:00:00 2001 From: Dmitry Kolesnikov Date: Sat, 5 Dec 2015 23:23:20 +0200 Subject: [PATCH 3/3] align worker id with actor index --- src/basho_bench_driver_cluster.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basho_bench_driver_cluster.erl b/src/basho_bench_driver_cluster.erl index 66be7b788..08a983b00 100644 --- a/src/basho_bench_driver_cluster.erl +++ b/src/basho_bench_driver_cluster.erl @@ -35,7 +35,7 @@ new(Id) -> Actors = basho_bench_config:get(cluster_actors, []), - Nth = ( Id rem length(Actors) ) + 1, + Nth = (Id - 1) rem length(Actors) + 1, {Name, Node} = Actor = lists:nth(Nth, Actors), case net_adm:ping(Node) of pang ->