Rate counter: Difference between revisions

From Rosetta Code
Content added Content deleted
m (update link names)
m (whitespace)
Line 13: Line 13:


=={{header|C}}==
=={{header|C}}==

This code stores all of the data of the rate counter and its configuration in an instance of a struct named '''rate_state_s''', and a function named '''tic_rate''' is called on that struct instance every time we complete a job. If a configured time has elapsed, '''tic_rate''' calculates and reports the tic rate, and resets the counter.
This code stores all of the data of the rate counter and its configuration in an instance of a struct named '''rate_state_s''', and a function named '''tic_rate''' is called on that struct instance every time we complete a job. If a configured time has elapsed, '''tic_rate''' calculates and reports the tic rate, and resets the counter.


Line 89: Line 88:


return 0;
return 0;
}</lang>
}
</lang>


=={{header|C++}}==
=={{header|C++}}==

This code defines the counter as a class, '''CRateState'''. The counter's period is configured as an argument to its constructor, and the rest of the counter state is kept as class members. A member function '''Tick()''' manages updating the counter state, and reports the tic rate if the configured period has elapsed.
This code defines the counter as a class, '''CRateState'''. The counter's period is configured as an argument to its constructor, and the rest of the counter state is kept as class members. A member function '''Tick()''' manages updating the counter state, and reports the tic rate if the configured period has elapsed.


Line 173: Line 170:


return 0;
return 0;
}</lang>
}
</lang>


=={{header|E}}==
=={{header|E}}==

<lang e>def makeLamportSlot := <import:org.erights.e.elib.slot.makeLamportSlot>
<lang e>def makeLamportSlot := <import:org.erights.e.elib.slot.makeLamportSlot>


Line 296: Line 291:
return times;
return times;
}</lang>
}</lang>

=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
{{incorrect|PARI/GP}}
{{incorrect|PARI/GP}}
<lang parigp>
<lang parigp>a=0;
a=0;
b=0;
b=0;
c=0;
c=0;
Line 349: Line 344:
<pre>1.761 sec
<pre>1.761 sec
-> "a"</pre>
-> "a"</pre>

=={{header|PureBasic}}==
=={{header|PureBasic}}==
===Counting frequence of an event===
===Counting frequence of an event===
Line 386: Line 382:
Until Event=#PB_Event_CloseWindow
Until Event=#PB_Event_CloseWindow
EndIf</lang>
EndIf</lang>

===Counting events for a time period===
===Counting events for a time period===
<lang PureBasic>Procedure DummyThread(arg)
<lang PureBasic>Procedure DummyThread(arg)
Line 463: Line 460:
First argument is the number of times to iterate. Additional arguments are command to execute.
First argument is the number of times to iterate. Additional arguments are command to execute.
<pre>C:>rateCounter.py 20 md5.exe</pre>
<pre>C:>rateCounter.py 20 md5.exe</pre>



=={{header|REXX}}==
=={{header|REXX}}==
<lang rexx>/*REXX program reports on the time 4 different tasks take (wall clock)*/
<lang rexx>
/*REXX program reports on the time 4 different tasks take (wall clock)*/


time.='' /*nullify times for all tasks. */
time.='' /*nullify times for all tasks. */
Line 507: Line 502:
end
end


say
say</lang>
</lang>
Output (of the tasks as well as the above REXX timer program):
Output (of the tasks as well as the above REXX timer program):
<pre style="height:50ex;overflow:scroll">
<pre style="height:50ex;overflow:scroll">
Line 677: Line 671:
time used for task 3 was 0 seconds.
time used for task 3 was 0 seconds.
time used for task 4 was 1 seconds.
time used for task 4 was 1 seconds.

</pre>
</pre>


Line 744: Line 737:


Part 1: file "foo.sh"
Part 1: file "foo.sh"
<br>

This script spins, executing '''task''' as many times as possible.
This script spins, executing '''task''' as many times as possible.
<lang bash>
<lang bash>#!/bin/bash
#!/bin/bash


while : ; do
while : ; do
task && echo >> .fc
task && echo >> .fc
done
done</lang>
</lang>


Part 2:
Part 2:
<br>
This script runs '''foo.sh''' in the background, and checks the rate count file every five seconds. After four such checks, twenty seconds will have elapsed.
This script runs '''foo.sh''' in the background, and checks the rate count file every five seconds. After four such checks, twenty seconds will have elapsed.
<lang bash>
<lang bash>./foo.sh &
./foo.sh &
sleep 5
sleep 5
mv .fc .fc2 2>/dev/null
mv .fc .fc2 2>/dev/null
Line 771: Line 762:
killall foo.sh
killall foo.sh
wc -l .fc 2>/dev/null
wc -l .fc 2>/dev/null
rm .fc
rm .fc</lang>
</lang>

Revision as of 17:49, 29 November 2010

Task
Rate counter
You are encouraged to solve this task according to the task description, using any language you may know.

Counting the frequency at which something occurs is a common activity in measuring performance and managing resources. In this task, we assume that there is some job which we want to perform repeatedly, and we want to know how quickly these jobs are being performed.

Of interest is the code that performs the actual measurements. Any other code (such as job implementation or dispatching) that is required to demonstrate the rate tracking is helpful, but not the focus.

Multiple approaches are allowed (even preferable), so long as they can accomplish these goals:

  • Run N seconds worth of jobs and/or Y jobs.
  • Report at least three distinct times.

Be aware of the precision and accuracy limitations of your timing mechanisms, and document them if you can.

See also: System time, Time a function

C

This code stores all of the data of the rate counter and its configuration in an instance of a struct named rate_state_s, and a function named tic_rate is called on that struct instance every time we complete a job. If a configured time has elapsed, tic_rate calculates and reports the tic rate, and resets the counter.

<lang c>#include <stdio.h>

  1. include <time.h>

// We only get one-second precision on most systems, as // time_t only holds seconds. struct rate_state_s {

   time_t lastFlush;
   time_t period;
   size_t tickCount;

};

void tic_rate(struct rate_state_s* pRate) {

   pRate->tickCount += 1;
   time_t now = time(NULL);
   if((now - pRate->lastFlush) >= pRate->period)
   {
       //TPS Report
       size_t tps = 0.0;
       if(pRate->tickCount > 0)
           tps = pRate->tickCount / (now - pRate->lastFlush);
       printf("%u tics per second.\n", tps);
       //Reset
       pRate->tickCount = 0;
       pRate->lastFlush = now;
   }

}

// A stub function that simply represents whatever it is // that we want to multiple times. void something_we_do() {

   // We use volatile here, as many compilers will optimize away
   // the for() loop otherwise, even without optimizations
   // explicitly enabled.
   //
   // volatile tells the compiler not to make any assumptions
   // about the variable, implying that the programmer knows more
   // about that variable than the compiler, in this case.
   volatile size_t anchor = 0;
   size_t x = 0;
   for(x = 0; x < 0xffff; ++x)
   {
       anchor = x;
   }

}

int main() {

   time_t start = time(NULL);
   struct rate_state_s rateWatch;
   rateWatch.lastFlush = start;
   rateWatch.tickCount = 0;
   rateWatch.period = 5; // Report every five seconds.
   time_t latest = start;
   // Loop for twenty seconds
   for(latest = start; (latest - start) < 20; latest = time(NULL))
   {
       // Do something.
       something_we_do();
       // Note that we did something.
       tic_rate(&rateWatch);
   }
   return 0;

}</lang>

C++

This code defines the counter as a class, CRateState. The counter's period is configured as an argument to its constructor, and the rest of the counter state is kept as class members. A member function Tick() manages updating the counter state, and reports the tic rate if the configured period has elapsed.

<lang cpp>#include <iostream>

  1. include <ctime>

// We only get one-second precision on most systems, as // time_t only holds seconds. class CRateState { protected:

   time_t m_lastFlush;
   time_t m_period;
   size_t m_tickCount;

public:

   CRateState(time_t period);
   void Tick();

};

CRateState::CRateState(time_t period) : m_lastFlush(std::time(NULL)),

                                       m_period(period),
                                       m_tickCount(0)

{ }

void CRateState::Tick() {

   m_tickCount++;
   time_t now = std::time(NULL);
   if((now - m_lastFlush) >= m_period)
   {
       //TPS Report
       size_t tps = 0.0;
       if(m_tickCount > 0)
           tps = m_tickCount / (now - m_lastFlush);
       std::cout << tps << " tics per second" << std::endl;
       //Reset
       m_tickCount = 0;
       m_lastFlush = now;
   }

}

// A stub function that simply represents whatever it is // that we want to multiple times. void something_we_do() {

   // We use volatile here, as many compilers will optimize away
   // the for() loop otherwise, even without optimizations
   // explicitly enabled.
   //
   // volatile tells the compiler not to make any assumptions
   // about the variable, implying that the programmer knows more
   // about that variable than the compiler, in this case.
   volatile size_t anchor = 0;
   for(size_t x = 0; x < 0xffff; ++x)
   {
       anchor = x;
   }

}

int main() {

   time_t start = std::time(NULL);
   CRateState rateWatch(5);
   // Loop for twenty seconds
   for(time_t latest = start; (latest - start) < 20; latest = std::time(NULL))
   {
       // Do something.
       something_we_do();
       // Note that we did something.
       rateWatch.Tick();
   }
   return 0;

}</lang>

E

<lang e>def makeLamportSlot := <import:org.erights.e.elib.slot.makeLamportSlot>

The rate counter:

/** Returns a function to call to report the event being counted, and an

   EverReporter slot containing the current rate, as a float64 in units of
   events per millisecond. */

def makeRateCounter(timer, reportPeriod) {

   var count := 0
   var start := timer.now()
   def &rate := makeLamportSlot(nullOk[float64], null)
 
   def signal() {
       def time := timer.now()
       count += 1
       if (time >= start + reportPeriod) {
           rate := count / (time - start)
           start := time
           count := 0
       }
   }
 
   return [signal, &rate]

}</lang>

The test code:

<lang e>/** Dummy task: Retrieve http://localhost/ and return the content. */ def theJob() {

   return when (def text := <http://localhost/> <- getText()) -> {
       text
   }

}

/** Repeatedly run 'action' and wait for it until five seconds have elapsed. */ def repeatForFiveSeconds(action) {

   def stopTime := timer.now() + 5000
   def loop() {
       if (timer.now() < stopTime) {
           when (action <- ()) -> {
               loop()
           }
       }
   }
   loop()

}

def whenever := <import:org.erights.e.elib.slot.whenever>

def [signal, &rate] := makeRateCounter(timer, 1000)

  1. Prepare to report the rate info.

whenever([&rate], fn {

   println(`Rate: ${rate*1000} requests/sec`)

}, fn {true})

  1. Do some stuff to be counted.

repeatForFiveSeconds(fn {

   signal()
   theJob()

})</lang>

HicEst

The script opens a modeless dialog with 3 buttons: "Hits++" to increase Hits, "Count 5 sec" to reset Hits and initialize a delayed call to F5 after 5 sec, "Rate" to display the current rate on the status bar. <lang HicEst>CHARACTER prompt='Count "Hits++" for 5 sec, get current rate'

DLG(Button="1:&Hits++", CALL="cb", B="2:&Count 5sec", B="3:&Rate", RC=retcod, TItle=prompt, WIN=hdl)

SUBROUTINE cb  ! callback after dialog buttons

 IF(retcod == 1) THEN     ! "Hits++" button
   Hits = Hits + 1
 ELSEIF(retcod == 2) THEN ! "Count 5 sec" button
   Hits = 0
   ALARM(5, 5)            ! call F5 in 5 seconds
   t_start = TIME()
 ELSE                     ! "Rate" button
   sec = TIME() - t_start
   WRITE(StatusBar) 'Average rate since last "5 sec" button = ', hits/sec, " Hz"
 ENDIF

END

SUBROUTINE F5 ! called 5 sec after button "5 sec"

 WRITE(StatusBar) Hits, "hits last 5 sec"

END</lang>

J

Solution
<lang j> x (6!:2) y</lang> The foreign conjunction 6!:2 will execute the code y (right argument), x times (left argument) and report the average time in seconds required for one execution.

Example: <lang j> list=: 1e6 ?@$ 100 NB. 1 million random integers from 0 to 99

  freqtable=: ~. ,. #/.~       NB. verb to calculate and build frequency table
  20 (6!:2) 'freqtable list'   NB. calculate and build frequency table for list, 20 times

0.00994106</lang>

Note, if instead we want distinct times instead of averaged times we can use a repeated counter for the number of times to execute the code

<lang j> 1 1 1 (6!:2) 'freqtable list' 0.0509995 0.0116702 0.0116266</lang>

JavaScript

The benchmark function below executes a given function n times, calling it with the specified arguments. After execution of all functions, it returns an array with the execution time of each execution, in milliseconds.

<lang javascript>function millis() { // Gets current time in milliseconds.

 return (new Date()).getTime();

}

/* Executes function 'func' n times, returns array of execution times. */ function benchmark(n, func, args) {

 var times = [];
 for (var i=0; i<n; i++) {
   var m = millis();
   func.apply(func, args);
   times.push(millis() - m);
 }
 return times;

}</lang>

PARI/GP

This example is incorrect. It does not accomplish the given task. Please fix the code and remove this message.

<lang parigp>a=0; b=0; c=0; for(n=1,20000000,

 a=a+gettime();
 if(a>60000,print(b);a=0;b=0);
 c=c+n;
 b=b+1;
 a=a+gettime();
 if(a>60000,print(b);a=0;b=0)

)</lang>

Perl

The Benchmark module can rate code per time, or per loops executed: <lang perl>use Benchmark;

timethese COUNT,{ 'Job1' => &job1, 'Job2' => &job2 };

sub job1 { ...job1 code... } sub job2 { ...job2 code... }</lang> A negative COUNT will run each job for at least COUNT seconds.
A positive COUNT will run each job COUNT times.

PicoLisp

usec returns a relative time in microseconds. This can be used, for example, to measure the time between two key strokes <lang PicoLisp>(prin "Hit a key ... ") (key) (prinl) (let Usec (usec)

  (prin "Hit another key ... ")
  (key)
  (prinl)
  (prinl "This took " (format (- (usec) Usec) 6) " seconds") )</lang>

Output:

Hit a key ... 
Hit another key ... 
This took 3.132058 seconds

The bench benchmark function could also be used. Here we measure the time until a key is pressed <lang PicoLisp>(bench (key))</lang>

1.761 sec
-> "a"

PureBasic

Counting frequence of an event

<lang PureBasic>Procedure.d TimesPSec(Reset=#False)

 Static starttime, cnt
 Protected Result.d, dt
 If Reset
   starttime=ElapsedMilliseconds(): cnt=0
 Else
   cnt+1
   dt=(ElapsedMilliseconds()-starttime)
   If dt
     Result=cnt/(ElapsedMilliseconds()-starttime)
   EndIf
 EndIf
 ProcedureReturn Result*1000

EndProcedure

If OpenWindow(0,#PB_Ignore,#PB_Ignore,220,110,"",#PB_Window_SystemMenu)

 Define Event, r.d, GadgetNumber
 ButtonGadget(0,10, 5,200,35,"Click me!")
 ButtonGadget(1,10,70,100,35,"Reset")
 TextGadget  (2,10,45,200,25,"")
 TimesPSec(1)
 Repeat
   Event=WaitWindowEvent()
   If Event=#PB_Event_Gadget 
     GadgetNumber =EventGadget()
     If GadgetNumber=0
       r=TimesPSec()
       SetGadgetText(2,"You are clicking at "+StrD(r,5)+" Hz.")
     ElseIf GadgetNumber=1
       TimesPSec(1)
       SetGadgetText(2,"Counter zeroed.")
     EndIf
   EndIf
 Until Event=#PB_Event_CloseWindow

EndIf</lang>

Counting events for a time period

<lang PureBasic>Procedure DummyThread(arg)

 Define.d dummy=#PI*Pow(arg,2)/4

EndProcedure

start=ElapsedMilliseconds() Repeat

 T=CreateThread(@DummyThread(),Random(100))
 WaitThread(T)
 cnt+1

Until start+10000<=ElapsedMilliseconds(); Count for 10 sec

msg$="We got "+Str(cnt)+" st."+Chr(10)+StrF(cnt/10,2)+" threads per sec." MessageRequester("Counting threads in 10 sec",msg$)</lang>

Python

<lang python>import subprocess import time

class Tlogger(object):

   def __init__(self):
       self.counts = 0
       self.tottime = 0.0
       self.laststart = 0.0
       self.lastreport = time.time()
   def logstart(self):
       self.laststart = time.time()
   def logend(self):
       self.counts +=1
       self.tottime += (time.time()-self.laststart)
       if (time.time()-self.lastreport)>5.0:   # report once every 5 seconds
          self.report()
   def report(self):
       if ( self.counts > 4*self.tottime):
           print "Subtask execution rate: %f times/second"% (self.counts/self.tottime);
       else:
           print "Average execution time: %f seconds"%(self.tottime/self.counts);
       self.lastreport = time.time()


def taskTimer( n, subproc_args ):

   logger = Tlogger()
   for x in range(n):
       logger.logstart()
       p = subprocess.Popen(subproc_args)
       p.wait()
       logger.logend()
   logger.report()


import timeit import sys

def main( ):

   # for accurate timing of code segments 
   s = """j = [4*n for n in range(50)]"""
   timer = timeit.Timer(s)
   rzlts = timer.repeat(5, 5000)
   for t in rzlts:
       print "Time for 5000 executions of statement = ",t
   
   # subprocess execution timing
   print "#times:",sys.argv[1]
   print "Command:",sys.argv[2:]
   print ""
   for k in range(3):
      taskTimer( int(sys.argv[1]), sys.argv[2:])

main()</lang> Usage Example: First argument is the number of times to iterate. Additional arguments are command to execute.

C:>rateCounter.py 20 md5.exe

REXX

<lang rexx>/*REXX program reports on the time 4 different tasks take (wall clock)*/

time.= /*nullify times for all tasks. */

/*----------------------------------------------------------------------*/ call time 'Reset' /*reset the REXX timer. */

                                      /*show  pi  in hexadecimal to    */
                                      /*2,000 decimal places.          */
                 task.1='base(pi,16)'
                 call '$CALC' task.1  /*perform task number one.       */

time.1=time('Elapsed') /*save the time used by task 1. */ /*----------------------------------------------------------------------*/ call time 'Reset' /*reset the REXX timer. */

                                      /*get primes # 40000-->40800 and */
                                      /*show their differences.        */
                 task.2='diffs[prime(40k,40.8k)] ;;; group 20'
                 call '$CALC' task.2  /*perform task number two.       */

time.2=time('Elapsed') /*save the time used by task 2. */ /*----------------------------------------------------------------------*/ call time 'Reset' /*reset the REXX timer. */

                                      /*show the Collatz sequence for  */
                                      /*a stupidly big number.         */
                 task.3='collatz(38**8) ;;; Horizontal'
                 call '$CALC' task.3  /*perform task number three.     */

time.3=time('Elapsed') /*save the time used by task 3. */ /*----------------------------------------------------------------------*/ call time 'Reset' /*reset the REXX timer. */

                                      /*plot SIN in ½ degree increments*/
                                      /*using 9 decimal digits  (¬ 60).*/
                 task.4='sind(-180,+180,0.5) ;;; Plot DIGits 9'
                 call '$CALC' task.4  /*perform task number four.      */

time.4=time('Elapsed') /*save the time used by task 4. */ /*----------------------------------------------------------------------*/

say

 do j=1 while time.j\==
 say 'time used for task' j "was" right(format(time.j,,0),4) 'seconds.'
 end

say</lang> Output (of the tasks as well as the above REXX timer program):

                                ╔═════════════╗
                                ║ base(pi,16) ║
                                ╚═════════════╝

3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01
377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD1310BA698DF
B5AC2FFD72DBD01ADFB7B8E1AFED6A267E96BA7C9045F12C7F9924A19947B3916CF70801F2E2858
EFC16636920D871574E69A458FEA3F4933D7E0D95748F728EB658718BCD5882154AEE7B54A41DC2
5A59B59C30D5392AF26013C5D1B023286085F0CA417918B8DB38EF8E79DCB0603A180E6C9E0E8BB
01E8A3ED71577C1BD314B2778AF2FDA55605C60E65525F3AA55AB945748986263E8144055CA396A
2AAB10B6B4CC5C341141E8CEA15486AF7C72E993B3EE1411636FBC2A2BA9C55D741831F6CE5C3E1
69B87931EAFD6BA336C24CF5C7A325381289586773B8F48986B4BB9AFC4BFE81B6628219361D809
CCFB21A991487CAC605DEC8032EF845D5DE98575B1DC262302EB651B8823893E81D396ACC50F6D6
FF383F442392E0B4482A484200469C8F04A9E1F9B5E21C66842F6E96C9A670C9C61ABD388F06A51
A0D2D8542F68960FA728AB5133A36EEF0B6C137A3BE4BA3BF0507EFB2A98A1F1651D39AF017666C
A593E82430E888CEE8619456F9FB47D84A5C33B8B5EBEE06F75D885C12073401A449F56C16AA64E
D3AA62363F77061BFEDF72429B023D37D0D724D00A1248DB0FEAD349F1C09B075372C980991B7B2
5D479D8F6E8DEF7E3FE501AB6794C3B976CE0BD04C006BAC1A94FB6409F60C45E5C9EC2196A2463
68FB6FAF3E6C53B51339B2EB3B52EC6F6DFC511F9B30952CCC814544AF5EBD09BEE3D004DE334AF
D660F2807192E4BB3C0CBA85745C8740FD20B5F39B9D3FBDB5579C0BD1A60320AD6A100C6402C72
79679F25FEFB1FA3CC8EA5E9F8DB3222F83C7516DFFD616B152F501EC8AD0552AB323DB5FAFD238
76053317B483E00DF829E5C57BBCA6F8CA01A87562EDF1769DBD542A8F6287EFFC3AC6732C68C4F
5573695B27B0BBCA58C8E1FFA35DB8F011A010FA3D98FD2183B84AFCB56C2DD1D35B9A53E479B6F
84565D28E49BC4BFB9790E1DDF2DAA4CB7E3362FB1341CEE4C6E8EF20CADA36774C01D07E9EFE2B
F11FB495DBDA4DAE909198EAAD8E716B93D5A0D08ED1D0AFC725E08E3C5B2F8E7594B78FF6E2FBF
2122B648CB209FDA49D89455E99887A81CF7DC407E83568CDC24FD608C80225F7ADA98BABF283A8
E1B06BBDBB6E99F6B4BC3E795E7BE1C57B21085778AB866F897578CEC3600FB01B0789912575FEF
DC4595BF054658D676F6323CD6DB1584BC6747713A2A431395D62DE6646642E9A995FB71811B93A
F99E6EB7B169C96740AA3A0F9EA3244AB192F10B595DC3E27CFEC33F1341A2830A7A30CC356B0A1
3AA06A5CFFB2B87F9AE0DAC27C0F649D4B5F0339
                          ╔═════════════════════════╗
                          ║ diffs[prime(40k,40.8k)] ║
                          ╚═════════════════════════╝
  1► 30 12  2  4 14 42  4  2  4 20  4  2 10  2 10 20 10  6  6 20
 21► 10 14 10  2 34  6 78 12 18 12 12  2  6 18  6  6  4  8 18 10
 41►  8 22  2 10  2 36  4  6  8  4  6  6  8 12 10  6 14  4 60 14
 61► 46  6 18  6 12 12 12 14 16 24 12 14 28 30  8 10  8  4 18  8
 81► 12 10 12  2  6 12 22  8 16  6 14  6  4 12 14 10  8  6  6  4
101► 14  6  4 18  8  4 20 18 48  4  2  4 36 20 10  6  8 22  8 16
121► 14 22 20 12 12 18 18 22  6 12 30 14  6 12 16  6  8 12  4  2
141► 22 30  2 16 18 14  6  6 24  6  4  2 12  6 12  4 26 30 24 34
161► 20  4  8  4  6 12 20 22  6  2 16  6 56 10 14 10 14  4  2 10
181► 20 18 28 14 24  4  8 12 16  6  6  2  6  6 10 14  4 42 18  6
201►  2  4  6  8 12 30 24  4 24  6  6  8 18  4 20  4  2 18  4  6
221►  2 12 12 10  6  8  6 16 14 16  8 10 24  2 10 24  2 18 24  6
241► 10 14 46 14 30 10 26 30 12 24  4 12 30  2 10  8  4  6  8  4
261► 30  8 28  6 14 10 20 10 12  8 10  2 24 10 24 14 10  8  4 20
281► 18 10  6  6 14 34  8 10 14  6 22 26 12 10  8  6 18  6  4  6
301►  6 14 22  2 16  2 10 14 10  6 14 24 22  8 16 18 20 28  8 10
321► 24  6 12 12 20  6  6  6 22  2 18 10 12  8  6 22 14 16 24 18
341►  2 24 12 22  8  4 24 14  6 22  8 10  2 28  2  4 38 12 34 20
361► 10  2  4  8 18  4 48 12 24  6 18 12  6  8 10 42 24 14 60 24
381► 36 12 22  8 12 12  6  4 18 20 12 10  8  6 24  6  4 30  6  2
401► 54 48 36  4 12  8 12  6 22  6  6 14 10 32 18 12 10 24 24 20
421►  6 10  6 38 10 14 18 12 16 12  2 22 24 42  8  4  2 60  6 10
441► 14 18 18 18 16 30 14  4  2 10  8 10 20 12 16 14  6 24 16  2
461► 12 10 18  2 24 34 12 14  6 10  6  2 10  8 28  2 10  2  6 10
481► 26 10  6 32 10 12  6  2 16 12 20 10 14  6 12 16 20  4  2 10
501► 14  4  6  2  4 14 16  8 36 10  2 12 16 20  4 12  6 30 38 16
521►  6 14  4  2 22  6 14 16  6  8 28  2  6 16  6 14  6 12 22 44
541►  6  4 24  2  6 28 14 22 20  4  6 36 14 18  6  4  6 26  4  2
561► 18 10  6  6  2  6  4  8 18 54 28 12  2  4 30 12  2  6 24 10
581► 12  6  8 10  6  8 16 12 14  6  4 18  8 10  2 12 30 16  2  6
601► 36 10 30  6 18  6  6  2 10 30  6 12 50 24  6  4  8 10 26  6
621►  4  2 18  4  2  6 10 12  2 24 16  6  2  6  4  8  4  6  8  6
641► 28 18  2  6 10  2 22 18 14 30 10 26 28  6 30  8  6 10  6  6
661►  2 10 36  2 12 10  6  6  6 14  6 10 20 12  6 24  6  6 28 18
681► 14  4 12 12 26 12 22 12  8 10  8 24 10  8 40  8  4 14  6 24
701►  4 18 12  6 20 22  2 16  6 20 16 30  8  6 18  6 22 18  2 18
721►  4  8 10  8 22  8  6 36 10 12  2  4 14 42 18 22  6 14  4  2
741► 10  2 42 10 18 30  2  6  4 14  6 10 14  4 18  2 16 14 10  2
761► 28  2 16  2 16 12 12  2 16 12  2 24 40  6  8  6  4 30  8 10
781► 14 18  6 16 18  6  2 18  4  6  6 26  4 26 28 26 24  4 32  6
                              ╔════════════════╗
                              ║ collatz(38**8) ║
                              ╚════════════════╝
4347792138496 2173896069248 1086948034624  543474017312  271737008656
 135868504328   67934252164   33967126082   16983563041   50950689124
  25475344562   12737672281   38213016844   19106508422    9553254211
  28659762634   14329881317   42989643952   21494821976   10747410988
   5373705494    2686852747    8060558242    4030279121   12090837364
   6045418682    3022709341    9068128024    4534064012    2267032006
   1133516003    3400548010    1700274005    5100822016    2550411008
   1275205504     637602752     318801376     159400688      79700344
     39850172      19925086       9962543      29887630      14943815
     44831446      22415723      67247170      33623585     100870756
     50435378      25217689      75653068      37826534      18913267
     56739802      28369901      85109704      42554852      21277426
     10638713      31916140      15958070       7979035      23937106
     11968553      35905660      17952830       8976415      26929246
     13464623      40393870      20196935      60590806      30295403
     90886210      45443105     136329316      68164658      34082329
    102246988      51123494      25561747      76685242      38342621
    115027864      57513932      28756966      14378483      43135450
     21567725      64703176      32351588      16175794       8087897
     24263692      12131846       6065923      18197770       9098885
     27296656      13648328       6824164       3412082       1706041
      5118124       2559062       1279531       3838594       1919297
      5757892       2878946       1439473       4318420       2159210
      1079605       3238816       1619408        809704        404852
       202426        101213        303640        151820         75910
        37955        113866         56933        170800         85400
        42700         21350         10675         32026         16013
        48040         24020         12010          6005         18016
         9008          4504          2252          1126           563
         1690           845          2536          1268           634
          317           952           476           238           119
          358           179           538           269           808
          404           202           101           304           152
           76            38            19            58            29
           88            44            22            11            34
           17            52            26            13            40
           20            10             5            16             8
            4             2             1
│1                                                      ∙∙∙∙∙∙
│                                                     ∙∙∙    ∙∙∙
│                                                    ∙∙        ∙∙
│                                                   ∙∙          ∙∙
│                                                  ∙              ∙
│                                                 ∙∙              ∙∙
│                                                ∙∙                ∙∙
│                                               ∙∙                  ∙∙
│                                               ∙                    ∙
│                                              ∙                      ∙
│                                             ∙∙                      ∙∙
│                                             ∙                        ∙∙
│                                            ∙                          ∙
│                                           ∙∙                          ∙∙
│                                           ∙                            ∙
│                                          ∙∙                            ∙∙
│                                          ∙                              ∙
│                                         ∙∙                               ∙
│                                         ∙                                ∙∙
│                                        ∙                                  ∙
│                                       ∙∙                                  ∙∙
│                                       ∙                                    ∙
│0                                     ∙∙                                    ∙∙
∙──────────────────────────────────────∙──────────────────────────────────────∙
∙∙                                    ∙∙                                    721
│∙                                    ∙
│ ∙                                  ∙∙
│ ∙                                  ∙
│  ∙                                ∙∙
│  ∙∙                               ∙
│   ∙                              ∙
│   ∙∙                            ∙∙
│    ∙                            ∙
│    ∙∙                          ∙∙
│     ∙∙                         ∙
│      ∙                        ∙
│      ∙∙                      ∙∙
│       ∙∙                     ∙
│        ∙                    ∙∙
│        ∙∙                  ∙∙
│         ∙∙                ∙∙
│          ∙∙              ∙∙
│           ∙∙             ∙
│            ∙∙          ∙∙∙
│             ∙∙        ∙∙
│              ∙∙∙    ∙∙∙
│-1              ∙∙∙∙∙∙

time used for task 1 was    0 seconds.
time used for task 2 was   11 seconds.
time used for task 3 was    0 seconds.
time used for task 4 was    1 seconds.

Scala

The solution below measures the number of tasks run in 5, 10 and 15 seconds. The tasks, however, run multithreaded, not sequentially. It also does not stop the remaining tasks once the time is up.

<lang scala>def task(n: Int) = Thread.sleep(n * 1000) def rate(fs: List[() => Unit]) = {

 val jobs = fs map (f => scala.actors.Futures.future(f()))
 val cnt1 = scala.actors.Futures.awaitAll(5000, jobs: _*).count(_ != None)
 val cnt2 = scala.actors.Futures.awaitAll(5000, jobs: _*).count(_ != None)
 val cnt3 = scala.actors.Futures.awaitAll(5000, jobs: _*).count(_ != None)
 println("%d jobs in 5 seconds" format cnt1)
 println("%d jobs in 10 seconds" format cnt2)
 println("%d jobs in 15 seconds" format cnt3)

} rate(List.fill(30)(() => task(scala.util.Random.nextInt(10)+1))) </lang>

The solution below runs a task repeatedly, for at most N seconds or Y times. The precision available is milliseconds, though the sampling was limited to seconds. It will wait until the current execution of the task is finished before announcing the result, if the time runs out.

<lang scala>def rate(n: Int, y: Int)(task: => Unit) {

 val startTime = System.currentTimeMillis
 var currTime = startTime
 var loops = 0
 do {
   task
   currTime = System.currentTimeMillis
   loops += 1
 } while (currTime - startTime < n * 1000 && loops < y)
 if (currTime - startTime > n * 1000)
   println("Rate %d times per %d seconds" format (loops - 1, n))
 else
   println("Rate %d times in %.3f seconds" format (y, (currTime - startTime).toDouble / 1000))

} rate(5, 20)(task(2))</lang>

Tcl

The standard Tcl mechanism to measure how long a piece of code takes to execute is the time command. The first word of the string returned (which is also always a well-formed list) is the number of microseconds taken (in absolute time, not CPU time). Tcl uses the highest performance calibrated time source available on the system to compute the time taken; on Windows, this is derived from the system performance counter and not the (poor quality) standard system time source. <lang tcl>set iters 10

  1. A silly example task

proc theTask {} {

   for {set a 0} {$a < 100000} {incr a} {
       expr {$a**3+$a**2+$a+1}
   }

}

  1. Measure the time taken $iters times

for {set i 1} {$i <= $iters} {incr i} {

   set t [lindex [time {
       theTask
   }] 0]
   puts "task took $t microseconds on iteration $i"

}</lang> When tasks are are very quick, a more accurate estimate of the time taken can be gained by repeating the task many times between time measurements. In this next example, the task (a simple assignment) is repeated a million times between measures (this is very useful when performing performance analysis of the Tcl implementation itself). <lang tcl>puts [time { set aVar 123 } 1000000]</lang>

UNIX Shell

This code stores the number of times the program task can complete in 20 seconds. It is two parts.

Part 1: file "foo.sh"
This script spins, executing task as many times as possible. <lang bash>#!/bin/bash

while : ; do task && echo >> .fc done</lang>

Part 2:
This script runs foo.sh in the background, and checks the rate count file every five seconds. After four such checks, twenty seconds will have elapsed. <lang bash>./foo.sh & sleep 5 mv .fc .fc2 2>/dev/null wc -l .fc2 2>/dev/null rm .fc2 sleep 5 mv .fc .fc2 2>/dev/null wc -l .fc2 2>/dev/null sleep 5 mv .fc .fc2 2>/dev/null wc -l .fc2 2>/dev/null sleep 5 killall foo.sh wc -l .fc 2>/dev/null rm .fc</lang>