Permalink
Browse files

add option to use weights instead of probabilities for sessions (TSUN…

…-231)
  • Loading branch information...
1 parent 12cdf33 commit 2c7ba4600e5c0215b414d1fd04c3d80d2c657978 @nniclausse nniclausse committed Aug 20, 2012
View
@@ -96,7 +96,7 @@
<!--CUT DEF section 1 --><H1 ALIGN=center>Tsung User’s manual</H1><DIV CLASS="center">
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1><TR><TD ALIGN=left NOWRAP bgcolor="#F2F2F2"> Version:</TD><TD ALIGN=left NOWRAP>1.4.2</TD></TR>
-<TR><TD ALIGN=left NOWRAP bgcolor="#F2F2F2"> Date :</TD><TD ALIGN=left NOWRAP>August 17, 2012</TD></TR>
+<TR><TD ALIGN=left NOWRAP bgcolor="#F2F2F2"> Date :</TD><TD ALIGN=left NOWRAP>August 20, 2012</TD></TR>
</TABLE>
</DIV><!--TOC section Contents-->
<H2 CLASS="section"><!--SEC ANCHOR -->Contents</H2><!--SEC END --><UL CLASS="toc"><LI CLASS="li-toc">
@@ -1452,7 +1452,26 @@ <H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc55">6.6</A>  Sessions</H
<A NAME="sec:sessions"></A></P><P>Sessions define the content of the scenario itself. They describe
the requests to execute.</P><P>Each session has a given probability. This is used to decide which
session a new user will execute. The sum of all session<CODE>'</CODE>s
-probabilities must be 100.</P><P>A transaction is just a way to have customized statistics. Say if you
+probabilities must be 100.</P><P><B>Since Tsung 1.4.3</B>, you can use weights instead of
+probabilities. In the following example, there will be twice as many
+sessions of type s1 than s2.
+</P><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><TABLE BORDER=0 CELLPADDING=0
+CELLSPACING=0><TR><TD BGCOLOR=black COLSPAN="3"><TABLE CELLSPACING="1" CELLPADDING=0 BORDER=0><TR><TD>
+</TD></TR>
+</TABLE></TD></TR>
+<TR><TD BGCOLOR=black COLSPAN="1"><TABLE CELLSPACING="1" CELLPADDING=0 BORDER=0><TR><TD>
+</TD></TR>
+</TABLE></TD><TD><TABLE BORDER=0 CELLPADDING="1" CELLSPACING=0><TR><TD><PRE CLASS="verbatim"> &lt;session name="s1" weight="2" type="ts_http"&gt;
+ &lt;session name="s2" weight="1" type="ts_http"&gt;
+</PRE></TD></TR>
+</TABLE></TD><TD BGCOLOR=black COLSPAN="1"><TABLE CELLSPACING="1" CELLPADDING=0 BORDER=0><TR><TD>
+</TD></TR>
+</TABLE></TD></TR>
+<TR><TD BGCOLOR=black COLSPAN="3"><TABLE CELLSPACING="1" CELLPADDING=0 BORDER=0><TR><TD>
+</TD></TR>
+</TABLE></TD></TR>
+</TABLE></TD></TR>
+</TABLE><P>A transaction is just a way to have customized statistics. Say if you
want to know the response time of the login page of your website, you
just have to put all the requests of this page (HTML + embedded
pictures) within a transaction. In the example above, the transaction
View
@@ -1183,11 +1183,17 @@ \subsection{Sessions}
Sessions define the content of the scenario itself. They describe
the requests to execute.
-
Each session has a given probability. This is used to decide which
session a new user will execute. The sum of all session\verb|'|s
probabilities must be 100.
+\strong{Since Tsung 1.4.3}, you can use weights instead of
+probabilities. In the following example, there will be twice as many
+sessions of type s1 than s2.
+\begin{Verbatim}
+ <session name="s1" weight="2" type="ts_http">
+ <session name="s2" weight="1" type="ts_http">
+\end{Verbatim}
A transaction is just a way to have customized statistics. Say if you
View
@@ -70,6 +70,8 @@
user_server_maxuid = none, % user_id max
oids=[],
rate_limit,
+ total_popularity = 0, % should be 100 if we use probabilites; sum of all weights if we use weights
+ use_weights , % true if we use weights instead of probabilities
job_notify_port
}).
@@ -16,6 +16,18 @@
test()->
ok.
+
+popularity_test() ->
+ ?assertError({"can't mix probabilites and weights",10,10}, ts_config:get_popularity(10,10,undefined,100)),
+ ?assertError({"can't use probability when using weight"}, ts_config:get_popularity(10,0,true,100)),
+ ?assertError({"can't use weights when using probabilities"}, ts_config:get_popularity(0,10,false,100)),
+ ?assertEqual({10,false,110}, ts_config:get_popularity(10,0,false,100)),
+ ?assertEqual({10,true,110}, ts_config:get_popularity(0,10,true,100)),
+ ?assertEqual({30,false,60}, ts_config:get_popularity(30,0,false,30)),
+ ?assertEqual({0,false,100}, ts_config:get_popularity(0,0,undefined,100)),
+ ?assertEqual({0,true,100}, ts_config:get_popularity(0,0,true,100)),
+ ?assertEqual({0,false,100}, ts_config:get_popularity(0,0,false,100)).
+
read_config_http_test() ->
myset_env(),
?assertMatch({ok, Config}, ts_config:read("./examples/http_simple.xml",".")).
@@ -358,7 +358,9 @@ parse(Element = #xmlElement{name=session, attributes=Attrs},
Name = getAttr(Attrs, name),
?LOGF("Session name for id ~p is ~p~n",[Id+1, Name],?NOTICE),
?LOGF("Session type: persistent=~p, bidi=~p~n",[Persistent,Bidi],?NOTICE),
- Probability = getAttr(float_or_integer, Attrs, probability),
+ Probability = getAttr(float_or_integer, Attrs, probability, 0),
+ Weight = getAttr(float_or_integer, Attrs, weight, 0),
+ {Popularity, NewUseWeights, NewTotal} = get_popularity(Probability, Weight, Conf#config.use_weights,Conf#config.total_popularity),
NewSList = case SList of
[] -> []; % first session
[Previous|Tail] ->
@@ -367,7 +369,7 @@ parse(Element = #xmlElement{name=session, attributes=Attrs},
end,
lists:foldl(fun parse/2,
Conf#config{sessions = [#session{id = Id + 1,
- popularity = Probability,
+ popularity = Popularity,
type = Type,
name = Name,
persistent = Persistent,
@@ -378,6 +380,8 @@ parse(Element = #xmlElement{name=session, attributes=Attrs},
}
|NewSList],
main_sess_type = Type,
+ use_weights=NewUseWeights,
+ total_popularity=NewTotal,
curid=0, cur_req_id=0},% re-initialize request id
Element#xmlElement.content);
@@ -1016,3 +1020,22 @@ get_dynvar_name(VarNameStr) ->
{match,[Name,Index]} -> {list_to_atom(Name),Index};
_ -> list_to_atom(VarNameStr)
end.
+
+
+%% @spec get_popularity(Proba::number(),Weight::number(),UseWeight:true|false|undefined, Total::number()) ->
+%% {Value::number(), UseWeight:boolean(), Total:: number()}
+%% check if we are using popularity or weights; keep the total up to date.
+get_popularity(Proba,Weight,_,_) when is_number(Proba), Proba > 0, is_number(Weight), Weight > 0 ->
+ erlang:error({"can't mix probabilites and weights", Proba, Weight} );
+get_popularity(Proba, Weight, true,_) when is_number(Proba), Proba > 0->
+ erlang:error({"can't use probability when using weight"});
+get_popularity(_, Weight, false,_) when is_number(Weight), Weight > 0->
+ erlang:error({"can't use weights when using probabilities"});
+get_popularity(_, Weight, undefined,_) when is_number(Weight), Weight > 0 ->
+ {Weight, true, Weight};
+get_popularity(Proba, _, undefined,Total) when is_number(Proba) ->
+ {Proba, false, Proba+Total};
+get_popularity(Proba, _, false,Total) when is_number(Proba) ->
+ {Proba, false, Proba+Total};
+get_popularity(_, Weight, true, Total) when is_number(Weight) ->
+ {Weight, true, Weight+Total}.
@@ -54,7 +54,7 @@
get_client_config/2, get_user_param/1, get_jobs_state/0 ]).
%%debug
--export([choose_client_ip/1, choose_session/1]).
+-export([choose_client_ip/1, choose_session/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
@@ -268,7 +268,7 @@ handle_call({get_next_session, HostName}, _From, State=#state{users=Users}) ->
Config = State#state.config,
{value, Client} = lists:keysearch(HostName, #client.host, Config#config.clients),
?DebugF("get new session for ~p~n",[_From]),
- case choose_session(Config#config.sessions) of
+ case choose_session(Config#config.sessions, Config#config.total_popularity) of
{ok, Session=#session{id=Id}} ->
?LOGF("Session ~p choosen~n",[Id],?INFO),
ts_mon:newclient({Id,now()}),
@@ -327,7 +327,7 @@ handle_call({status}, _From, State) ->
handle_call({get_jobs_state}, _From, State) when State#state.config == undefined ->
{reply, not_configured, State};
-handle_call({get_jobs_state}, {Pid,Tag}, State) ->
+handle_call({get_jobs_state}, {Pid,_Tag}, State) ->
Config = State#state.config,
Reply = case Config#config.job_notify_port of
{Ets,Port} ->
@@ -514,15 +514,15 @@ choose_rr(List, Key, _) ->
{ok, lists:nth(I, List)}.
%%----------------------------------------------------------------------
-%% Func: choose_session/1
+%% Func: choose_session/2
%% Args: List of #session
%% Purpose: choose an session randomly
%% Returns: #session
%%----------------------------------------------------------------------
-choose_session([Session]) -> %% only one Session
+choose_session([Session], _Total) -> %% only one Session
{ok, Session};
-choose_session(Sessions) ->
- choose_session(Sessions, random:uniform() * 100,0).
+choose_session(Sessions,Total) ->
+ choose_session(Sessions, random:uniform() * Total, 0).
choose_session([S=#session{popularity=P} | _],Rand,Cur) when Rand =< P+Cur->
{ok, S};
@@ -635,16 +635,17 @@ setup_user_servers(FileId,Val) when is_atom(FileId), is_integer(Val) ->
%% Func: check_config/1
%% Returns: ok | {error, ErrorList}
%%----------------------------------------------------------------------
-check_config(Config)->
- Pop= ts_utils:check_sum(Config#config.sessions, #session.popularity, ?SESSION_POP_ERROR_MSG),
+check_config(Config=#config{use_weights=true})->
%% FIXME: we should not depend on a protocol specific feature here
- Agents = ts_config_http:check_user_agent_sum(Config#config.session_tab),
- case lists:filter(fun(X)-> X /= ok end, [Pop, Agents]) of
- [] -> ok;
- ErrorList -> {error, ErrorList}
+ ts_config_http:check_user_agent_sum(Config#config.session_tab);
+check_config(Config)->
+ case abs(100-Config#config.total_popularity) < 0.05 of
+ false ->
+ {error, {bad_sum, Config#config.total_popularity ,?SESSION_POP_ERROR_MSG}};
+ true ->
+ ts_config_http:check_user_agent_sum(Config#config.session_tab)
end.
-
load_app(Name) when is_atom(Name) ->
FName = atom_to_list(Name) ++ ".app",
case code:where_is_file(FName) of
@@ -826,3 +827,5 @@ get_one_node_per_host([Node | Nodes], Dict) ->
NewDict = dict:store(Host, Node, Dict),
get_one_node_per_host(Nodes,NewDict)
end.
+
+
View
@@ -118,7 +118,8 @@ repeat | if | change_type | foreach | set_option)*>
name CDATA #REQUIRED
bidi CDATA #IMPLIED
persistent (true | false) #IMPLIED
- probability NMTOKEN #REQUIRED
+ probability NMTOKEN #IMPLIED
+ weight NMTOKEN #IMPLIED
type (ts_jabber | ts_http | ts_raw | ts_pgsql | ts_ldap | ts_webdav |ts_mysql| ts_fs |ts_shell|ts_job) #REQUIRED>
<!ELEMENT change_type EMPTY>

0 comments on commit 2c7ba46

Please sign in to comment.