Suppose you are developing an application in MATLAB—an image processing program, for example, or financial data import/export. Testing has shown that the application gives the correct results, but the elapsed time for all or parts of the application seems too long. How do you make the application run faster?
First, you must figure out where the time is being spent and locate the parts of the application that take the most time. To do this, you can use the MATLAB Profiler, which automatically instruments your code and measures the frequency and relative elapsed time within and across functions (see the MATLAB User's Guide for guidelines on profiling for improved performance). To further analyze critical sections of these slower parts, you can create a simple test program and measure the absolute elapsed time of those sections.
Second, you must obtain a precise measurement of absolute elapsed time. MATLAB provides two sets of functions for measuring absolute elapsed time:
etime functions use dates to track elapsed time, and are useful if you need accuracy to only .01 second. Originally, the
toc functions relied on
clock for the time and had the same accuracy. This article describes the decoupling of
clock and the improvements that give
toc the highest accuracy and most predictable behavior.
What Makes a Good Instrumentation Tool?
A good instrumentation tool:
- Measures something useful
- Is easy to use
- Has low overhead
- Does not skew your results
- Does not interfere with scaling your problem
- Provides accurate results
What Is Time and How Is It Measured?
You expect time as measured on your computer to be uniform, in standard units like seconds, and accurate enough to be used to measure short computations. What limits the uniformity and accuracy of time measurement on your computer? To answer this question we must first understand what time is and how it is measured on a computer.
We perceive and witness time as a succession of transient nows. We attach a measurement to each now. By international agreement, the difference between two nows, or the elapsed time, is measured in seconds. The device that measures each now we call a clock. Real clocks depend on counting the repetition of a uniform and stable physical process, such as the swings of a pendulum, or the vibrations of a crystal, or the periods of the radiation from an excited atom. Each repetition is called a tick. The number of ticks per second, or the frequency, is measured in hertz.
The best clocks have a high frequency and very stable repetitions, or low drift. The current best clocks use the atomic frequency of radiation from an excited Cesium atom (~9.2*109 hertz), which has defined the second since 1967 and is the basis of International Atomic Time (TAI). Neither people nor computers use TAI time directly; they use local time or corrected Coordinated Universal Time (UTC), which is defined by international agreement based on the mean solar day with corrections. UTC time is corrected TAI time with constant second duration. All units larger than a second are variable. Leap seconds are added periodically to account for the slowing of the earth's rotation.
A computer system is constructed with its own internal clocks; the number and variety depend on your particular hardware. The hardware architecture probably includes several CPUs, or cores, all running at different speeds. Your operating system may run on your hardware or depend on hardware virtualization. Your operating system provides various time services that rely on access to hardware clocks. Some return values are synchronized with external clocks; others are not. For example, to return results in TAI Seconds requires synchronization with TAI sources. The Network Time Protocol (NTP) can be used to do this via the Internet, but maintaining consistently high accuracy is difficult because of server delay variability . Special client/server software is required to smooth out the variability, and OS providers have not agreed on a solution. As a result, those internal clocks on your computer system can appear to have an effective frequency of only 102 hertz (10 milliseconds).
Measuring Elapsed Time Using
Wall clock time is the best way to measure elapsed time performance. It is simple to understand and, with careful use, can show consistent changes in performance on a particular hardware or software platform. Increasing the accuracy of the underlying clock enables meaningful measurements using shorter computations and opens up opportunities to assign a performance number to a computation using fewer trials. This can mean better-performing test suites.
Before R2006b, the MATLAB
toc functions were connected to
tic command would get the current time as a local time date vector generated by
clock and save it. The
toc command would call
clock again to get the current time and subtract it from the saved local time date vector to get the elapsed time.
Clock calls a time service using API provided by the operating system: the
GetLocalTime function on Microsoft Windows and the POSIX.1-2001 (IEEE Portable Operating System Interface for Computing Environments)
localtime functions on Linux and Mac OS.
clock values suffer from several problems. Special handling must be used at the daylight saving time boundaries. On Microsoft Windows, the UTC time service used by the
GetLocalTime function has known low accuracy and, under certain conditions, can give negative elapsed times between successive calls to the service. Because other applications of
clock, such as
date, did not require higher accuracy, we did not attempt to improve the limited accuracy and non-uniform behavior of
clock, but instead focused on improving
Creating More Accurate Time Values
Our goal was to create more accurate time values for each
tic using units as close as possible to standard seconds. We elected to stay with known interfaces, which compromised the requirement of keeping the units as standard seconds . On Linux and Mac OS, we stopped converting to local time and used the
gettimeofday function directly. On Microsoft Windows, we opted for a pure local time service, using
QueryPerformanceFrequency functions, with units in approximate standard Seconds.
With R2006b, the
toc functions started using these time services. The output from each service can be used to form a 64-bit counter value that is saved as a
tic value. When
toc is called, the service is called again, and a difference is formed with the last
tic value. That difference is divided by a frequency and returned as the elapsed time. The frequency used for
gettimeofday is 106 hertz. The frequency of the clock used by the
QueryPerformanceCounter function is returned by the
Here is a simple way to see the resolution of
>> tic; toc Elapsed time is 0.000001 seconds. >>
etime returns 0, as its resolution is not fine enough to detect the very short time interval.
>> t =clock; etime(clock,t) ans = 0 >>
Accuracy issues such as the one caused by daylight saving time have been removed on all platforms. Handling leap seconds is still an issue on Linux and Mac OS, however. In addition, the counters underlying the services—for example, the counter in
gettimeofday—may be less than 64 bits wide. By 2038, the number of seconds since the Epoch (January 1, 1970) will exceed its capacity of 32 bits.
These time services can show hardware-dependent behavior. For example, on modern Intel architectures there is a timestamp counter (TSC) register on each CPU. This 64-bit register is incremented on each CPU cycle. We considered using a service to drive
toc using the RTSC instruction that reads the counter, giving very low overhead access to a clock with frequency in the gigahertz (109) range. Unfortunately, it failed as a general solution. The power management software on laptops often slows down a CPU to preserve battery usage and control chassis temperature. In addition, in multiple CPU configurations the TSC values on different processors may be different, and the RTSC instruction may not read the same processor at the
tic and the
toc steps, causing random results.
The time-service APIs hide the platform dependencies. For example, the
QueryPerformanceCounter function uses the best high-resolution counter configured by the operating system. This means that if the TSC cannot be used, it will use the Advanced Programmable Interrupt Controller (APIC) clock, which has lower resolution. In rare cases, the operating system selected the wrong clock, and
toc appeared to be broken. Operating system configuration or processor driver patches can be applied to make
toc work correctly. MATLAB does not need to be fixed.
In summary, use
toc to measure elapsed time in MATLAB, because the functions have the highest accuracy and most predictable behavior. The basic syntax is
tic; … computation … toc
toc lines are recognized by MATLAB for minimum overhead.
toc syntax was extended in R2008b to allow multiple nested
toc counters. Note that the new syntax that lets you save the counter from
tic and pass it to
REPS = 1000; minTime = Inf; nsum = 10; tic; for i=1:REPS tstart = tic; sum = 0; for j=1:nsum, sum = sum + besselj(j,REPS); end telapsed = toc(tstart); minTime = min(telapsed,minTime); end averageTime = toc/REPS;
can result in extra overhead. This issue will be fixed in a future version of MATLAB.