Skip to main content

module util::Benchmark

rascal-0.34.0

Functions for time measurement and benchmarking.

Usage

import util::Benchmark;

The Benchmark library provides the following functions:

function heapDump

Write a JVM heap dump to a file.

void heapDump(loc file, bool live=true)
  • The file parameter has to be of the file scheme.
  • The live parameter restricts the dump to only live objects.

function getFreeMemory

Returns the free memory of the current JVM

int getFreeMemory()

This returns the number of bytes that can be allocated still against the current result of Get Total Memory.

function getTotalMemory

Returns the current total memory allocated by the current JVM

int getTotalMemory()

This returns the number of bytes currently allocated for use by the JVM. The number can change over time but it's never higher than Get Max Memory`

function getMaxMemory

Returns the maximum amount of memory that is available to the current JVM

int getMaxMemory()

function getUsedMemory

Returns the amount of memory that is currently in use by the programs running on this JVM

int getUsedMemory()

function getMaxFreeMemory

Returns the amount of memory that is yet available, in principle, on the current JVM

int getMaxFreeMemory()

function cpuTime

CPU time in nanoseconds (10^-9^ sec)

int cpuTime()
  • Current cpu time in nanoseconds (10^-9^ sec) since the start of the thread that runs the code that calls this function.
  • This number has nanoseconds resolution, but not necessarily nanosecond accuracy.

Examples

rascal>import util::Benchmark;
ok
rascal>int fac(int n) {
>>>>>>> if (n <= 1) return 1;
>>>>>>> else return n * fac(n - 1);
>>>>>>>}
int (int): function(|prompt:///|(0,72,<1,0>,<4,1>))

Here we measure time by using separate calls to cpuTime before and after a call to fac.

rascal>before = cpuTime();
int: 49348308384
rascal>fac(50);
int: 30414093201713378043612608166064768844377641568960512000000000000
rascal>cpuTime() - before;
int: 1427076

See also Cpu Time Of for a more convenient way of measuring the time spent during a block of code.

Pitfalls

  • The timings shown above may be significantly influenced by the documentation compilation process

function realTime

Returns wall clock time in milliseconds since the Unix epoch

int realTime()

Returns the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC

Pitfalls

  • The actual accuracy of the time may be not as good as a millisecond. This depends on OS and hardware specifics.
    • Note that the resolution is milliseconds here, while Cpu Time produces nanosecond resolution.

function getNanoTime

Return nanoseconds clock time of the JVM's high resolution clock.

int getNanoTime()

See System.nanoTime Java documentation. An excerpt:

Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds. This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary origin time (perhaps in the future, so values may be negative). The same origin is used by all invocations of this method in an instance of a Java virtual machine; other virtual machine instances are likely to use a different origin.

This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes).

function getMilliTime

Synonym for ((realTime))

int getMilliTime()

function cpuTimeOf

Measure the exact running time of a block of code, using ((cpuTime)).

int cpuTimeOf(void () block)

function systemTime

System time in nanoseconds (10^-9^ sec).

int systemTime()

Returns the CPU time that the current thread has executed in system mode in nanoseconds.

  • Current system time in nanoseconds (10^-9^ sec) since the start of the thread that runs the code that calls this function.
  • The returned value is of nanoseconds precision but not necessarily nanoseconds accuracy.
  • CPU time is the number of CPU cycles times the OS-registered clock speed.
  • The other CPU time, next to System time is spent in User time.

Examples

rascal>import util::Benchmark;
ok

Here we measure time by using separate calls to sytemTime before and after a call to fac.

rascal>before = systemTime();
int: 874290235
rascal>fac(50);
int: 30414093201713378043612608166064768844377641568960512000000000000
rascal>systemTime() - before;
int: 1705551

function systemTimeOf

Measure the exact running time of a block of code, using ((systemTime)).

int systemTimeOf(void () block)

Examples

rascal>import util::Benchmark;
ok
rascal>int fac(int n) = n <= 1 ? 1 : n * fac(n - 1);
int (int): function(|prompt:///|(0,45,<1,0>,<1,45>))
rascal>systemTimeOf(
>>>>>>> void() {
>>>>>>> fac(50);
>>>>>>> }
>>>>>>>);
int: 370640

function userTime

User time in nanoseconds (10^-9^ sec)

int userTime()

Returns the CPU time that the current thread has executed in user mode in nanoseconds.

  • The returned value is of nanoseconds precision but not necessarily nanoseconds accuracy.
  • As distinguished from Now which returns the wall clock time since the Unix epoch.
  • CPU time is the number of CPU cycles times the OS-registered clock speed.
  • The other CPU time, next to user time is spent in system time.

Examples

rascal>import util::Benchmark;
ok
rascal>int fac(0) = 1;
int (int): function(|prompt:///|(0,15,<1,0>,<1,15>))
rascal>default int fac(int n) = n * fac(n - 1);
int (int): function(|prompt:///|(0,40,<1,0>,<1,40>))

Here we measure time by using separate calls to userTime before and after a call to fac.

rascal>before = userTime();
int: 48530000000
rascal>fac(50);
int: 30414093201713378043612608166064768844377641568960512000000000000
rascal>userTime() - before;
int: 0

function userTimeOf

Measure the exact running time of a block of code in nanoseconds, doc combined with previous function.

int userTimeOf(void () block)

function realTimeOf

Measure the exact running time of a block of code in milliseconds, doc included in previous function.

int realTimeOf(void () block)

Pitfalls

  • watch out this is measured in milliseconds, not nanoseconds

function benchmark

Utility to measure and compare the execution time a set of code blocks

map[str,num] benchmark(map[str, void()] Cases)

map[str,num] benchmark(map[str, void()] Cases, int (void ()) duration)

Given is a map that maps strings (used as label to identify each case) to void-closures that execute the code to be benchmarked. An optional duration argument can be used to specify the function to perform the actual measurement. By default the function Real Time Of is used. A map of labels and durations is returned.

Examples

rascal>import util::Benchmark;
ok
rascal>int fac(int n) {
>>>>>>> if (n <= 1) return 1;
>>>>>>> else return n * fac(n - 1);
>>>>>>>}
int (int): function(|prompt:///|(0,72,<1,0>,<4,1>))

We measure two calls to the factorial function with arguments 100, respectively, 200 (using by default Real Time that returns milliseconds):

rascal>benchmark(
>>>>>>> ("fac100" : void() {
>>>>>>> fac(100);
>>>>>>> },
>>>>>>> "fac200" : void() {
>>>>>>> fac(200);
>>>>>>> })
>>>>>>> );
map[str, num]: ("fac100":0,"fac200":1)

We can do the same using User Time that returns nanoseconds:

rascal>benchmark( 
>>>>>>> ("fac100" : void() {
>>>>>>> fac(100);
>>>>>>> },
>>>>>>> "fac200" : void() {
>>>>>>> fac(200);
>>>>>>> })
>>>>>>> , userTimeOf);
map[str, num]: ("fac100":0,"fac200":0)

function gc

void gc()

This function tries to trigger a garbage collection. It may be useful to call this function just before measuring the efficiency of a code block, in order to factor out previous effects on the heap.

Benefits

  • This helps avoiding to restart the JVM, and optionally warming it up, for each individual measurement.
  • Long running terminals can be rejuvenated on demand by a call to Gc.

Pitfalls

  • Although a GC cycle is triggered by this function, it guarantees nothing about the effect of this cycle in terms of completeness or precision in removing garbage from the heap.
  • GC only works for real garbage. So if there is an unrelated accidental memory leak somewhere, it may better to start a fresh JVM to measure the current functionality under scrutiny.