Skip to content

Commit

Permalink
Add an option to start a phase after all generated users in the previous
Browse files Browse the repository at this point in the history
phase have finished their session (fix #201)
  • Loading branch information
nniclausse committed Sep 20, 2016
1 parent 68c5ce2 commit 52ee7b3
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 9 deletions.
23 changes: 21 additions & 2 deletions docs/conf-load.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ The load progression is set-up by defining several arrival phases:
<arrivalphase phase="1" duration="10" unit="minute">
<users interarrival="2" unit="second"></users>
</arrivalphase>
<arrivalphase phase="2" duration="10" unit="minute">
<users interarrival="1" unit="second"></users>
</arrivalphase>
<arrivalphase phase="3" duration="10" unit="minute">
<users interarrival="0.1" unit="second"></users>
</arrivalphase>
Expand Down Expand Up @@ -86,6 +86,25 @@ specific phase, using ``session_setup``:
</arrivalphase>
.. versionadded:: 1.6.1

Be default, a phase ends when it's duration has been reached, even if
all started sessions during the phase are not finished. You can
override this behavior If you want to start a new phase only after
all generated users in the previous phase have finished their
sessions, use the ``wait_all_sessions_end`` attribute, like this:

.. code-block:: xml
<arrivalphase phase="1" duration="10" unit="minute" wait_all_sessions_end="true">
<users interarrival="1" unit="second"/>
</arrivalphase>
<arrivalphase phase="2" duration="10" unit="minute">
<users interarrival="5" unit="second"/>
</arrivalphase>
(In this case, the real duration of the phase 1 will probably be higher than it's configured one.)

.. index:: start_time

Statically generated users
Expand Down
1 change: 1 addition & 0 deletions include/ts_config.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,6 @@
maxnumber,
curnumber = 0,
popularities = [],
wait_all_sessions_end = false,
id
}).
27 changes: 24 additions & 3 deletions src/tsung/ts_launcher.erl
Original file line number Diff line number Diff line change
Expand Up @@ -314,19 +314,21 @@ skip_empty_phase(State=#launcher{phases=Phases,current_phase=Phase})->
%%% Purpose: decide if we need to change phase (if current users is
%%% reached or if max duration is reached)
%%% ----------------------------------------------------------------------
change_phase(N, [Phase|Rest], Duration, #phase{duration=PhaseDuration}) when N < 1 andalso Duration >= PhaseDuration ->
change_phase(N, [Phase|Rest], Duration, CurrentPhase = #phase{duration=PhaseDuration}) when N < 1 andalso Duration >= PhaseDuration ->
check_sessions_end(CurrentPhase),
{change, Phase, Rest};
change_phase(N, [Phase|Rest], Duration, #phase{duration=PhaseDuration}) when N < 1 ->
change_phase(N, [Phase|Rest], Duration, CurrentPhase = #phase{duration=PhaseDuration}) when N < 1 ->
%% no more users, check if we need to wait before changing phase (this can happen if maxnumber is set)
ToWait=round(PhaseDuration-Duration),
?LOGF("Need to wait ~p sec before changing phase, going to sleep~n", [ToWait/1000], ?WARN),
timer:sleep(ToWait),
?LOG("Waking up~n", ?NOTICE),
check_sessions_end(CurrentPhase),
{change, Phase, Rest};
change_phase(N, [], _, _) when N < 1 ->
?LOG("This was the last phase, wait for connected users to finish their session~n",?NOTICE),
{stop};
change_phase(N,NewPhases,Duration,#phase{duration=PhaseDuration, nusers=Users}) when Duration>PhaseDuration ->
change_phase(N,NewPhases,Duration, CurrentPhase=#phase{duration=PhaseDuration, nusers=Users}) when Duration>PhaseDuration ->
?LOGF("Check phase: ~p ~p~n",[N,Users],?DEB),
Percent = 100*N/Users,
case {Percent > ?MAX_PHASE_EXCEED_PERCENT, N > ?MAX_PHASE_EXCEED_NUSERS} of
Expand All @@ -339,6 +341,7 @@ change_phase(N,NewPhases,Duration,#phase{duration=PhaseDuration, nusers=Users})
end,
case NewPhases of
[NextPhase|Rest] ->
check_sessions_end(CurrentPhase),
{change, NextPhase,Rest};
[] ->
?LOG("This was the last phase, wait for connected users to finish their session~n",?NOTICE),
Expand All @@ -347,6 +350,24 @@ change_phase(N,NewPhases,Duration,#phase{duration=PhaseDuration, nusers=Users})
change_phase(_N, _, _, _) ->
{continue}.


check_sessions_end(Phase= #phase{wait_all_sessions_end = true}) ->
case ts_client_sup:active_clients() of
0 ->
ok;
ActiveClients when ActiveClients > 1000 ->
?LOGF("Wait for all sessions to finish before starting next phase (still ~p sessions active)", [ActiveClients], ?NOTICE),
timer:sleep(?check_noclient_timeout),
check_sessions_end(Phase);
ActiveClients ->
?LOGF("Wait for all sessions to finish before starting next phase (still ~p sessions active)", [ActiveClients], ?NOTICE),
timer:sleep(?fast_check_noclient_timeout),
check_sessions_end(Phase)
end;
check_sessions_end(_) ->
ok.


%%%----------------------------------------------------------------------
%%% Func: check_max_raised/1
%%%----------------------------------------------------------------------
Expand Down
8 changes: 5 additions & 3 deletions src/tsung_controller/ts_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,16 @@ parse(Element = #xmlElement{name=iprange, attributes=Attrs},
parse(Element = #xmlElement{name=arrivalphase, attributes=Attrs},
Conf = #config{arrivalphases=AList}) ->

Phase = getAttr(integer,Attrs, phase),
IDuration = getAttr(integer, Attrs, duration),
Unit = getAttr(string,Attrs, unit, "second"),
Phase = getAttr(integer, Attrs, phase),
IDuration = getAttr(integer, Attrs, duration),
Unit = getAttr(string, Attrs, unit, "second"),
WaitSessionsEnd = getAttr(atom,Attrs, wait_all_sessions_end, false),
D = to_milliseconds(Unit, IDuration),
case lists:keysearch(Phase,#arrivalphase.phase,AList) of
false ->
lists:foldl(fun parse/2,
Conf#config{arrivalphases = [#arrivalphase{phase=Phase,
wait_all_sessions_end=WaitSessionsEnd,
duration=D
}
|AList]},
Expand Down
4 changes: 3 additions & 1 deletion src/tsung_controller/ts_config_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ choose_session([S=#session{popularity=PopList} | SList],Rand,Cur,PhaseId) ->
get_client_cfg(Arrival=#arrivalphase{duration = Duration,
intensity= PhaseIntensity,
curnumber= CurNumber,
wait_all_sessions_end = WaitSessionsEnd,
maxnumber= MaxNumber },
{TotalWeight,Client,IsLast} ) ->
Weight = Client#client.weight,
Expand All @@ -638,7 +639,8 @@ get_client_cfg(Arrival=#arrivalphase{duration = Duration,
end),
?LOGF("New arrival phase ~p for client ~p (last ? ~p): will start ~p users~n",
[Arrival#arrivalphase.phase,Client#client.host, IsLast,NUsers],?NOTICE),
{Arrival#arrivalphase{curnumber=CurNumber+NUsers}, #phase{intensity=ClientIntensity, nusers=NUsers, duration= Duration}}.
Phase = #phase{intensity=ClientIntensity, nusers=NUsers, duration= Duration, wait_all_sessions_end = WaitSessionsEnd },
{Arrival#arrivalphase{curnumber=CurNumber+NUsers}, Phase}.

%%----------------------------------------------------------------------
%% Func: encode_filename/1
Expand Down
1 change: 1 addition & 0 deletions tsung-1.0.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
<!ATTLIST arrivalphase
duration NMTOKEN #REQUIRED
phase NMTOKEN #REQUIRED
wait_all_sessions_end NMTOKEN "false"
unit (hour | minute | second | millisecond) #REQUIRED>

<!ELEMENT users EMPTY>
Expand Down

0 comments on commit 52ee7b3

Please sign in to comment.