Rate counter: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added PicoLisp)
Line 285: Line 285:
A negative COUNT will run each job for at least COUNT seconds.<br>
A negative COUNT will run each job for at least COUNT seconds.<br>
A positive COUNT will run each job COUNT times.
A positive COUNT will run each job COUNT times.

=={{header|PicoLisp}}==
[http://software-lab.de/doc/refU.html#usec 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:
<pre>Hit a key ...
Hit another key ...
This took 3.132058 seconds</pre>
The [http://software-lab.de/doc/refB.html#bench bench] benchmark function could
also be used. Here we measure the time until a key is pressed
<lang PicoLisp>(bench (key))</lang>
<pre>1.761 sec
-> "a"</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 17:09, 11 March 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: Query Performance, System time

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>

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>

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>

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"

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

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>

  1. !/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>