12

I wish to know the amount of time taken for execution of a program under linux in microseconds (or better accuracy). Currently I am using the time command, but it gives me at the max milliseconds accuracy. Is there some way to tweak the time command to give better accuracy or is there some other command for the same?

Pushpak Dagade
  • 6,280
  • 7
  • 28
  • 41

5 Answers5

8

Your question is meaningless: you will not get repeated measurements even within milliseconds time does report.

Adding more digits will just add noise. You might as well pull the extra digits from /dev/random.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • 1
    I don't understand your point. I said I want accuracy better than milliseconds which is not impossible on today's processors, where we can even get upto nanoseconds accuracy. How does adding more digits add more noise? – Pushpak Dagade Dec 21 '11 at 08:31
  • 7
    @Guidance Because code running on a non-realtime OS does not have determistic execution. All it takes is for the OS to process a some IP packets, or another arbitary process to run, or crond waking up to check if it should do something, or the filesystem deciding it should write out dirty pages, etc. and the process you're timing gets suspended for some (small amount of) time and the timings are off. The builtin timings of an OS, such as CPU time(as opposed to the wall clock time), are also usually counted in timeslices which have a certain resolution (often 1 kernel tick,1 milisecond or more) – nos Dec 21 '11 at 08:53
  • 4
    Quick tests with `time /bin/sleep 0.006` seems to indicate that the the noise is less than 1 millisecond. So while such measurements are definitely dangerous, Guanidene’s request is not meaningless per se. – Joachim Breitner Sep 28 '15 at 13:29
  • 1
    @JoachimBreitner You are measuring a command that doesn't do anything. For any command that actually does something, variability within the scheduler is likely to give you more than +/-1ms in final measurement. Even with `/bin/sleep`, you got sub-millisecond accuracy, *not* microsecond accuracy Guanidene asked for. – Employed Russian Oct 04 '15 at 15:18
  • @EmployedRussian Why would the scheduler make any difference between sleep and any other command? For measuring the noise, sleep is just as good. – ssmid Feb 08 '22 at 17:14
4

I do agree with Employed Russian's answer. It does not have much sense to want microsecond accuracy for such measures. So any additional digit you've got is meaningless (and essentially random).

If you have the source code of the application to measure, you might use the clock or clock_gettime functions, but don't hope for better than a dozen of microseconds of accuracy. There is also the RDTSC machine instruction.

Read the linux clock howto.

And don't forget that the timing of execution, is from an application point of view, non deterministic and non reproductible (think about context switches, cache misses, interrupts, etc... happenning at random time).

If you want to measure the performance of a whole program, make it run for at least several seconds, and measure the time several (e.g. 8) times, and take the average (perhaps dropping the best & worst timing).

If you want to measure timing for particular functions, learn how to profile your application (gprof, oprofile etc etc...) See also this question

Don't forget to read time(7)

Be aware that on current (laptop, desktop, server) out-of-order pipelined superscalar processors with complex CPU caches and TLB and branch predictors, the execution time of some tiny loop or sequence of machine instruction is not reproducible (the nanosecond count will vary from one run to the next). And the OS also adds randomness (scheduling, context switches, interrupts, page cache, copy-on-write, demand-paging ...) so it does not make any sense to measure the execution of some command with more than one millisecond -or perhaps 100µs if you are lucky- of precision. You should benchmark your command several times.

To get significant measures, you should change the benchmarked application to run in more than a few seconds (perhaps adding some loop in main, or run with a bigger data set...), and repeat the benchmarked command a dozen times. That take the mean (or the worst, or the best, depending what you are after) of the measures.

If the system time(1) is not enough, you might make your own measurement facility; see also getrusage(2); I'm skeptical about you getting more accurate measures.

BTW on my i3770K recent GNU/Linux (4.2 kernel, Debian/Sid/x86-64) desktop computer, "system"-calls like time(2) or clock_gettime(2) runs in about 3 or 4 nanoseconds (thanks to vdso(7) which avoid the burden of a real syscall...) so you could use them inside your program quite often.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • clock() is pretty useless, at least on my machine. Inaccuracy of clock() over time (in seconds): `time_t t0 = time(NULL); clock_t c0 = clock(); while (1) { printf("\r%ld", (clock() - c0) / CLOCKS_PER_SEC - (time(NULL) - t0)); }` – ssmid Feb 08 '22 at 17:02
  • On my machine it's -180 after 15 min btw – ssmid Feb 08 '22 at 17:17
4

Use gettimeofday -- gives microsecond accuracy

1

See if current_kernel_time() is helpful for you in your requirement. I have used it and found useful as it gives granularity to nanosecond level.. More details are here.

TheCottonSilk
  • 8,662
  • 2
  • 26
  • 37
0

Linux perf CLI tool

Like others mentioned, times of the order of microsecond are just noise in a modern system.

Microsecond accurate (or better) process timing in Linux asks if there is any way to reduce variability produced by the kernel.

The perf CLI tool does print microseconds and more, and that will allow us to see just how such measurements are just noise.

Ubuntu 22.04 setup:

sudo apt install linux-tools-common linux-tools-generic
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid

x86 assembly program that loops CYCLES cycles:

main.S

.text
.global _start
_start:
    mov $0, %rax
    mov $CYCLES, %rcx
.Lloop_label:
    inc %rax
    loop .Lloop_label

    /* exit */
    mov $60, %rax   /* syscall number */
    mov $0, %rdi    /* exit status */
    syscall

Assemble and run:

cpp -DCYCLES=100000 main.S main.cpp.S
as -o main.o main.cpp.S
ld -o main.out main.o
perf stat ./main.out

Some sample results on my Lenovo ThinkPad P51:

CYCLES seconds time elapsed
10^9 1.3 s
10^8 0.13 s
10^7 0.014 s
10^6 1.9 ms
10^5 0.6 - 0.8 ms
10^4 0.4 - 0.8 ms

From this we see that numbers down to the millisecond were somehow meaningful and scaled with size somewhat: 10x less cycles meant 10x less time.

But somewhere around the 0.1 ms thigs stopped scaling completely, and instead of program execution we must be measuring something else completely random.

You could also try to create baremetal programs: How to run a program without an operating system? I wonder how much noise the BIOS and hardware itself create in such cases, would be an interesting thing to try out.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985