Anyway, i wonder what tools exist to test the speed/execution time, cpu cycles and ram usage of a c program in FreeBSD.
At first: congratulations. You are getting deeper, and having fun with it. Very good! Keep on that good work!
Exact measurement of speed/execution time is kind of a bit tricky.
You can use the
time.h in C:
C:
#include <stdio.h>
#include <time.h>
int main()
{
int t_start, t_end;
/* other code */
t_start = clock();
/*
....code to be measured ....
*/
t_end = clock();
printf("%d\n", t_end - t_start);
/* other code */
return 0;
}
You can use
getrusage(2) to get RAM usage. But also the debugger can help.
For to get exact execution times - 'how many [micro]seconds or clock cycles does this part of code needs to be executed on the CPU?' it's needed to be known how many clock cycles each machine command takes, knowing the machine code of a certain part of code (
objdump(1), e.g.
objdump -d a.out is one way to see it) which delivers the number of clock cycles needed for that part, those computed with the CPU's clock frequency gives the time.
Debuggers help you on that.
But the point is:
As long as it's just out of pure curiosity, you may get lost into details which are not important to know as long as you don't really need to meet
real time requirements, must have exact timing, e.g. control some fast technical process.
<[begin sidetrack]>
You also always need to keep in mind, that every new version of the compiler may produce a different object code. The exact same, unchanged source code you once wrote can deliver differences in machine code when compiled with different versions of the compiler, and certainly when using different compilers, e.g. gcc instead of clang. Depending on what was fixed/improved sometimes shorter, sometimes longer. In most situations for running under normal conditions on common PCs with common OS this doesn't matter at all. The change of execution time is negligibly tiny for those applications. But there are changes. This questions the term "exact timing". And you keep that in mind for the case if one day you may have to meet real time requirements at high frequencies. I personally prefer to write the time critical parts directly in assembler. This way I know the exact amount of clock cycles stay rock solid the same when there is a new version of the compiler, and so the control loops do not suddenly start behave strangely. And I dealt with some people in my life they then don't know why such things happen, since it seems there was no change at all, because they neither ever learned any assembling language, nor programmed any time critical software on microcontrollers before, but did programming in HOLs on OS on PCs only so far.
<[end sidetrack]>
The actual question is:
What means exact execution time on a modern personal computer, where there are different machines having 2 to 64 or even more CPUs/cores running at somewhere between 1 to 5GHz, doing such things like code prediction or running code parallel, but above all dealing with an OS?
How useful is this to know, or more correct: When is the usage worth to take the effort to get this value?
You see:
Just measuring how long a piece of code, or even the whole prog runs on your system is not always very meaningful.
When you place some code between both t_...=clock() in the example above, which does always the exact same and uses a couple of seconds to run (a few nested loops counting up to large numbers for example), compile it, and then run it unchanged a couple of times, you will not receive the same timespan by clock() every time.
Explanation:
You are using a
time sharing OS. So you're not running your prog directly on the CPU ("bare metal"), but let the OS handle this job. Doesn't matter if you're using BSD, Linux, MacOS, Windows or RaspPi OS - the principal on a time sharing OS is always the same.
Running a prog on an ts OS works this way: You tell the OS, 'Hey! Run this!' Then the OS (there is also communication between the shell and the kernel, and also the shell then has jobs to do, e.g. when you use printf; not going into details here) needs to see, when to fit it into its schedule, where to slip it between all the other jobs it currently does. Of course, under normal cicumstances there is way more capacity left to just execute a small piece of software you ask for en passant. And since you are the user, you get a higher priority for the jobs you ask for than the OS's jobs running in background when there is nothing else to do. But anyway it needs some CPU time to run, needs to slip in somewhere, needs to be loaded, and then executed, when there is time for it.
As the user infront of a machine you don't recognize anything of that. At least you shall not. Except of course the program takes a while to run, or waits for user interaction. But that's not what I mean here. If so then those are the so called 'lags'. Commonly known as a cause for unfair death on virtual battlefields in computer games, because the internet connection had a lag, and your game froze for a few tenth seconds. But it's also, when you realize your mousepointer is not running smoothly, there is a significant delay between pressing a key and seeing the letter appear, or something like that. It's when your machine's load is over 100% its capacity, and the OS gets problems to schedule enough CPU time for all the tasks asked to be done.
A modern time sharing OS has a bunch of jobs to do. Even organizing all the jobs is a job of its own. The point is, at least the jobs according directly with the user's interaction (UI) are all (shall be) done so damnd fokkin' quickly, that for a human it seems they are happening instantaneously at the same time, or at least fast enough not to be recognize there are any delays. Or delays happen very seldom and are very short, so not disturbing.
While other jobs not having a direct connection to the user's interactions with the machine, the time when they are started and the timespan they need to be done are of lower priority. It doesn't matter really how long those take to be finished, as long as they are done. For example it doesn't matter if the new version of the source code file you're writing is saved to disk within 31 ms or 329 ms - anyway fast enough for the job. Of course we are talking computer's time scales. Which means a couple of seconds are "just sometime in the future, doesn't matter when."
Anyway, and that's the core point, there are delays, constantly many, many delays. Most of the times they are too short for a human to be recognized, so his work at the machine feels smooth.
<[begin side track]>
There is a neuropsychological limit of perception - a minimum time that nerves respond to a stimulus. Since there is not only a very large difference between seeing, hearing,...feeling a touch with your fingertips or with your toes, but also between individual humans, to give a general number for it is not actually correct. But to give a rough idea which for many practical applications is not complete bogus, one could say anything shorter than app. 30 ms is recognized by a human as immediately, instantaneously, not even recognized there was a delay at all.
For a modern CPU 30 ms is a small eternity - you can do a lot many things in that time.
<[end side track]>
When you let a program run on an OS, supposing a very small C program doing just some short calculations with pregiven values (named "c" here), and there is no waiting for user interaction, the time line would look something like this:
[.................................- wait for the OS to begin execution -........................................][c][...............................- wait for and then printf("", result); - ..................................]
All this waiting happens in milliseconds. So an execution of a very small program seems to happen at the very moment you hit the enter key to start it, while in fact most of the time is not needed for the program's execution, but for the shell and OS to handle its "organization."
Point is, all that scheduling by the OS, wait to fit in, wait for to run it in most of the times is by far way more than short enough, so the user is not disturbed in his workflow on an "office machine" ("personal computer"). But there are those times. And above all they not always have the exact same length. So their timespan is not predictable. And, like in this example, they can exceed the actual execution time of a small prog by several times (even if not recognized.)
So, bottom line:
As long as you don't really need to deal with exact timing, e.g. having to control some fast technical process, or need to speed up your software, because it runs to slow to meet some real time requirements (producing lags), then just do what the majority does: Don't bother much, and simply rely on the machine will run it fast enough.

Besides, you can gain way much more speed by chosing the right algorithm, or tighten your code, than finetuning at clock cycles.
"Premature optimization is the root of all evil."
[Donald Knuth]