I am collecting the total elapsed time by using two inline functions (specified and implemented in my .h file) as follows:
extern double _elapsed_time_mf;
extern double _elapsed_time_b;
//this function returns the elapsed time in order to compute the total elapsed time of an operation
static inline struct timeval get_current_time() {
struct timeval time;
gettimeofday(&time, NULL);
return time;
}
//calculate the total processed time and return the elapsed total time in seconds
static inline double get_elapsed_time(struct timeval start, struct timeval end) {
long int tmili;
tmili = (int) (1000.0 * (end.tv_sec - start.tv_sec) +
(end.tv_usec - start.tv_usec) / 1000.0);
return (double) (tmili / (double) 1000.0);
}
Then, when I would like to know the total elapsed time of an operation I do this:
void my_function() {
#ifdef COLLECT_STATISTICAL_DATA
struct timeval start;
struct timeval end;
start = get_current_time();
#endif
//a processing....
#ifdef COLLECT_STATISTICAL_DATA
end = get_current_time();
_elapsed_time_mf = get_elapsed_time(start, end);
#endif
}
_elapsed_time_mf is defined in only one .c file.
However, I am getting strange results. For instance, consider that I have another function, called function_b, which also collects its elapsed time (which is stored in other global variable). Then, this function makes a call to my_function (that collects its elapsed time according to my previous code). However, the total elapsed time of function_b is sometimes lesser than the total elapsed time of my_function. An example of this situations is:
void function_b() {
#ifdef COLLECT_STATISTICAL_DATA
struct timeval start;
struct timeval end;
start = get_current_time();
#endif
//a processing....
my_function();
//another processing...
#ifdef COLLECT_STATISTICAL_DATA
end = get_current_time();
_elapsed_time_b = get_elapsed_time(start, end);
#endif
}
Sometimes _elapsed_time_b is lesser than _elapsed_time_mf. Why?
I would like to collect both elapsed times in seconds according to the clock/date/timestamp (not the CPU elapsed time).
You might want to reconsider the implementation of get_elapsed_time. From here: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
As Art has commented, I am using now clock_gettime. Thus, my code is now working as expected.
My functions are now written as:
static inline double get_elapsed_time(struct timespec start, struct timespec end) {
double start_in_sec = (double)start.tv_sec + (double)start.tv_nsec / 1000000000.0;
double end_in_sec = (double)end.tv_sec + (double)end.tv_nsec / 1000000000.0;
return end_in_sec - start_in_sec;
}
static inline struct timespec get_current_time() {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return time;
}
Related
I am working with an averaging function following the formula
new average = old average * (n-1) / n + (new value / n)
When passing in doubles this works great. My example code for a proof of concept is as follows.
double avg = 0;
uint16_t i;
for(i=1; i<10; i++) {
int32_t new_value = i;
avg = avg*(i-1);
avg /= i;
avg += new_value/i;
printf("I %d New value %d Avg %f\n",i, new_value, avg);
}
In my program I am keeping track of messages received. Each time I see a message its hit count is increased by 1, it is them timestamped using a timespec. My goal is to keep a moving average (like above) of the average time between messages of a certain type being received.
My initial attempt was to average the tv_nsec and tv_sec separately as follows
static int32_t calc_avg(const int32_t current_avg, const int32_t new_value, const uint64_t n) {
int32_t new__average = current_avg;
new__average = new__average*(n-1);
new__average /= n;
new__average += new_value/n;
return new__average;
}
void average_timespec(struct timespec* average, const struct timespec new_sample, const uint64_t n) {
if(n > 0) {
average->tv_nsec = calc_avg(average->tv_nsec, new_sample.tv_nsec, n);
average->tv_sec = calc_avg(average->tv_sec, new_sample.tv_sec, n);
}
}
My issue is I am using integers, the values are always rounded down and my averages are way off. Is there a smarter/easier way to average the time between timespec readings?
Below is some code that I've used a lot [in production S/W] for years.
The main idea is that just because clock_gettime uses struct timespec does not mean this has to be "carried around" everywhere:
It's easier to convert to a long long or double and propagate those values as soon as they're gotten from clock_gettime.
All further math is simple add/subtract, etc.
The overhead of the clock_gettime call dwarfs the multiply/divide time in the conversion.
Whether I use the fixed nanosecond value or the fractional seconds value depends upon the exact application.
In your case, I'd probably use the double since you already have calculations that work for that.
Anyway, this is what I use:
#include <time.h>
typedef long long tsc_t; // timestamp in nanoseconds
#define TSCSEC 1000000000LL
#define TSCSECF 1e9
tsc_t tsczero; // initial start time
double tsczero_f; // initial start time
// tscget -- get number of nanoseconds
tsc_t
tscget(void)
{
struct timespec ts;
tsc_t tsc;
clock_gettime(CLOCK_MONOTONIC,&ts);
tsc = ts.tv_sec;
tsc *= TSCSEC;
tsc += ts.tv_nsec;
tsc -= tsczero;
return tsc;
}
// tscgetf -- get fractional number of seconds
double
tscgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_MONOTONIC,&ts);
sec = ts.tv_nsec;
sec /= TSCSECF;
sec += ts.tv_sec;
sec -= tsczero_f;
return sec;
}
// tscsec -- convert tsc value to [fractional] seconds
double
tscsec(tsc_t tsc)
{
double sec;
sec = tsc;
sec /= TSCSECF;
return sec;
}
// tscinit -- initialize base time
void
tscinit(void)
{
tsczero = tscget();
tsczero_f = tscsec(tsczero);
}
Use better integer math.
Use signed math if new_value < 0 possible, else int64_t cast not needed below.
Form the sum first and then divide.
Round.
Sample code:
// new__average = new__average*(n-1);
// new__average /= n;
// new__average += new_value/n;
// v-------------------------------------v Add first
new__average = (new__average*((int64_t)n-1) + new_value + n/2)/n;
// Add n/2 to effect rounding ^-^
On review, the whole idea of doing averages in 2 parts is flawed. Instead use a 64-bit count of nanoseconds. Good until the year 2263.
Suggested code:
void average_timespec(int64_t* average, struct timespec new_sample, int64_t n) {
if (n > 0) {
int64_t t = new_sample.tv_sec + new_sample.tv_nsec*(int64_t)1000000000;
*average = (*average*(n-1) + t + n/2)/n;
}
}
If you must form a struct timespec from the average, easy to do when average >= 0.
int64_t average;
average_timespec(&average, new_sample, n);
struct timespec avg_ts = (struct timespec){.tm_sec = average/1000000000,
.tm_nsec = average%1000000000);
I'm sure the answer is simple, but I don't quite get it. I'm trying to calculate the delta between two struct timespec using this code:
struct timespec start, finish, diff;
int ndiff;
/* Structs are filled somewhere else */
diff.tv_sec = finish.tv_sec - start.tv_sec;
ndiff = finish.tv_nsec - start.tv_nsec;
if (ndiff < 0) {
diff.tv_sec--;
ndiff = 1L - ndiff;
}
diff.tv_nsec = ndiff;
printf("Elapsed time: %ld.%ld seconds.\n", diff.tv_sec, diff.tv_nsec);
However, the output is always something like Elapsed time: 0.300876000 seconds. which seems to indicate that I'm losing the last three digits of the nanoseconds (since those shouldn't always be zero). Can someone point out what's causing that?
Elapsed time: 0.300876000 seconds. which seems to indicate that I'm losing the last three digits of the nanoseconds (since those shouldn't always be zero). Can someone point out what's causing that?
The code's clock reported precision is 1000 ns. #John Bollinger #rici
and/or
diff.tv_sec is not necessarily a long. Use a matching specifier.
// printf("Elapsed time: %ld.%ld seconds.\n", diff.tv_sec, diff.tv_nsec);
// Also insure fraction is printed with 9 digits
printf("Elapsed time: %lld.%09ld seconds.\n", (long long) diff.tv_sec, diff.tv_nsec);
Also, incorrect "borrow" math when updating the ndiff.
ndiff = finish.tv_nsec - start.tv_nsec;
if (ndiff < 0) {
diff.tv_sec--;
// ndiff = 1L - ndiff;
ndiff += 1000000000;
}
Even better, drop the int diff variable.
diff.tv_sec = finish.tv_sec - start.tv_sec;
diff.tv_nsec = finish.tv_nsec - start.tv_nsec;
if (diff.tv_nsec < 0) {
diff.tv_sec--;
diff.tv_nsec += 1000000000;
}
Should finish occur before start, then other code may be desired to keep the 2 members of diff with the same sign.
I wrote a sample program to understand the time measurement in C.Below is a small self contained example.I have a function do_primes() that calculates prime numbers.In the main() function between timing code I call do_primes() and also sleep for 20 milliseconds.I am measure time using struct timeval (which I understand returns clock time.) and also cpu_time using CLOCKS_PER_SEC.Now as I understand it,this denotes the time for which the CPU was working.
The output of the program is as follows.
Calculated 9592 primes.
elapsed time 2.866976 sec.
cpu time used 2.840000 secs.
As you can see the differnece between the elapsed time and cpu time is
0.026976 seconds OR 26.976 milliseconds.
1) Are my assumptions correct?
2) 6.976 milliseconds is accounted for my the scheduler switch delay?
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#define MAX_PRIME 100000
void do_primes()
{
unsigned long i, num, primes = 0;
for (num = 1; num <= MAX_PRIME; ++num)
{
for (i = 2; (i <= num) && (num % i != 0); ++i);
if (i == num)
++primes;
}
printf("Calculated %ld primes.\n", primes);
}
int main()
{
struct timeval t1, t2;
double elapsedTime;
clock_t start, end;
double cpu_time_used;
int primes = 0;
int i = 0;
int num = 0;
start = clock();
/* start timer*/
gettimeofday(&t1, NULL);
/*do something */
usleep(20000);
do_primes();
/* stop timer*/
gettimeofday(&t2, NULL);
end = clock();
/*compute and print the elapsed time in millisec*/
elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; /* sec to ms*/
elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; /* us to ms */
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("elapsed time %f sec. \ncpu time used %f secs.\n",(elapsedTime/1000),cpu_time_used);
return 0;
}
Your understanding is correct.
The additional 6.976ms might not mean anything at all, because it's possible that the clock() function only has a resolution of 10ms.
With the "timeval_subtract" function to find the time elapsed between two struct timeval types, can someone please explain the purpose of and step by step maths used to "Perform the carry for the later subtraction by updating y" and other sections? I understand the purpose of the function and how to implement it within a program, but I would like to understand how it works inside and cannot find any explanations of this anywhere, and I can't seem to wrap my head around it.
int timeval_subtract (struct timeval *result, struct timeval *x,struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
It is a function described in relation to the GNU C library for determining an elapsed time https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.5/html_node/Elapsed-Time.html so I am not looking for improvements but simply an explanation of why the dividing and adding and subtracting and multiplying within it. What do these specific arithmetic operations achieve?/Why are they done/not done? I have done the stepping through but still can'y get my head around it. I will continue to do so until I do (and even after someone explains it to me) but I was hoping to get some insight from someone who understands it already. The platform is UNIX, which I am new to using, but I don't think it changes the operations that are taking place inside the function. It is more a question about the arithmetic being performed than the algorithm being used.
At first glance, it looks like struct timeval contains a time split into two parts:
tv_usec - microseconds, ideally should always be under 1000000, but greater values seem to be allowed as suggested by the code
tv_sec - seconds (the number of multiples of 1000000)
and the time in microseconds is tv_usec + tv_sec * 1000000.
Conversely, one would expect this to be true:
tv_sec = time in microseconds / 1000000
tv_usec = time in microseconds % 1000000.
The function appears to calculate the time difference between *x and *y (logically, *x - *y) and store it in another struct timeval, *result.
A simple test program gives us some hints:
#include <stdio.h>
struct timeval
{
long tv_sec;
long tv_usec;
};
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
// preserve *y
struct timeval yy = *y;
y = &yy;
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
struct timeval testData00 = { 0, 0 };
struct timeval testData01 = { 0, 1 };
int main(void)
{
struct timeval diff;
int res;
res = timeval_subtract(&diff, &testData00, &testData00);
printf("%d %ld:%ld\n", res, diff.tv_sec, diff.tv_usec);
res = timeval_subtract(&diff, &testData01, &testData01);
printf("%d %ld:%ld\n", res, diff.tv_sec, diff.tv_usec);
res = timeval_subtract(&diff, &testData01, &testData00);
printf("%d %ld:%ld\n", res, diff.tv_sec, diff.tv_usec);
res = timeval_subtract(&diff, &testData00, &testData01);
printf("%d %ld:%ld\n", res, diff.tv_sec, diff.tv_usec);
return 0;
}
Output (ideone):
0 0:0
0 0:0
0 0:1
1 -1:999999
From the last test result it appears that the function returns (-1):999999 instead of -(0:1). Both values represent the same negative time (or time difference) in microseconds:
-1 * 1000000 + 999999 = -1
-(0 * 1000000 + 1) = -1
So, how does it really work?
If x->tv_usec >= y->tv_usec then only the second if could probably* execute:
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
This if checks if the difference in the microseconds parts alone is greater than 1 second. If it is, it subtracts the whole seconds of this difference from y->tv_usec (as microseconds) and adds it to y->tv_sec (as seconds). This simply redistributes the time in *y without really changing it. You could rewrite this if equivalently like this to see it more clearly:
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
One important thing to note here is that when the input *x and *y have their tv_usec in the range from 0 to 999999 inclusive, the body of this if does not execute (hence, probably* is actually never when x->tv_usec >= y->tv_usec and when tv_usecs are in the range from 0 to 999999).
The net effect of this if is not readily clear now.
However, one interesting thing can be seen here. If we call this function with *x = 0:1000001 and *y = 0:0, the result is going to be wrong: difference = (-1):2000001 (instead of 1:1) and the return value of the function = 1 (instead of 0). This suggests that the function isn't really suited for tv_usec > 1000000 and even for tv_usec > 999999. And because of this behavior I'm going to claim that the function isn't suited for negative tv_usec in the inputs either. I'm just going to ignore those cases in the face of this behavior. It looks wrong enough already.
Let's look at the first if.
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
As the comment and the code suggests, when x->tv_usec < y->tv_usec we need to take care of the "carry" between the "digits" as if we were adding and not subtracting. But it's OK, we'll see it.
Let's go back to school for a moment.
How do you do 37 - 12?
You do it like this:
7 - 2 = 5
3 - 1 = 2
And so 37 - 12 = 25.
Now, how do you do 57 - 38?
You do it like this:
10/*because 7 < 8*/ + 7 - 8 = 9
5 - 3 - 1/*borrow, because of the above*/ = 1
And so 57 - 38 = 19. See?
And the check:
if (x->tv_usec < y->tv_usec) {
checks whether or not we need to take care of this borrowing.
So, what's happening here? Let's look again:
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
If y->tv_usec > x->tv_usec, it calculates the difference between the two in whole seconds and just like the other if it adds these whole seconds to y->tv_sec and subtracts them from y->tv_usec, simply redistributing the time in *y, without changing it.
The extra one (+ 1) that ends up added to y->tv_sec here will be subtracted from x->tv_sec at the end of the function (result->tv_sec = x->tv_sec - y->tv_sec;) and thus this 1 functions as the borrow I just reminded you of in the 57 - 38 = 19 example.
What else is happening here besides the borrow itself and some time redistribution?
Like I said earlier, I'm just going to ignore negative tv_usecs and greater than 999999 as likely handled incorrectly.
With this I take (y->tv_usec - x->tv_usec) / 1000000 to be 0 and I am left only with truly meaningful values of tv_usecs (0 to 999999 inclusive).
So, if the if's condition is true, I basically subtract 1000000 from y->tv_usec and add 1 (the borrow) to y->tv_sec.
This is the same thing we had in 57 - 38 = 19:
10/*because 7 < 8*/ + 7 - 8 = 9
5 - 3 - 1/*borrow, because of the above*/ = 1
Similarly to this 10, 1000000 is going to be added later in here: result->tv_usec = x->tv_usec - y->tv_usec;
And this first if is the meat of the function.
If I had to write a function with similar behavior, I'd require the input times to be non-negative and the microsecond parts to be no greater than 999999 and I'd write just this:
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
result->tv_sec = x->tv_sec - y->tv_sec;
if ((result->tv_usec = x->tv_usec - y->tv_usec) < 0)
{
result->tv_usec += 1000000;
result->tv_sec--; // borrow
}
return result->tv_sec < 0;
}
If for some odd reason I wanted to support tv_usec > 999999 in the inputs, I'd first move the excess from tv_usec to tv_sec and then do the above, something like this:
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
struct timeval xx = *x;
struct timeval yy = *y;
x = &xx; y = &yy;
if (x->tv_usec > 999999)
{
x->tv_sec += x->tv_usec / 1000000;
x->tv_usec %= 1000000;
}
if (y->tv_usec > 999999)
{
y->tv_sec += y->tv_usec / 1000000;
y->tv_usec %= 1000000;
}
result->tv_sec = x->tv_sec - y->tv_sec;
if ((result->tv_usec = x->tv_usec - y->tv_usec) < 0)
{
result->tv_usec += 1000000;
result->tv_sec--; // borrow
}
return result->tv_sec < 0;
}
Here, the intent is clear and the code is easy to understand.
Here's a timeval_subtract():
commented with why and how to carry usec <--> sec
with const input structs (copies y to the subtrahend sh)
that normalizes output microseconds (0-999999)
Recall that tv_usec are the microseconds elapsed since tv_sec.
So diff{-1,2000001} == diff{1,1} is true,
as is tv{0,-1} == tv{-1,999999}.
/* copied from
https://www.gnu.org/software/libc/manual/html_node/Calculating-Elapsed-Time.html
Changed input timevals to const, added // comments.
Changed condition of 2nd if.
*/
int
timeval_subtract (const struct timeval *x, const struct timeval *y, struct timeval *diff)
{
//subtraction found the difference, the minuend minus the subtrahend
timeval sh = *y; // mutable local copy of y, sh (the subtrahend)
/* Perform the carry for the later subtraction by updating sh. */
if (x->tv_usec < sh.tv_usec) {
// reduce sh.usecs so usec diff will be positive.
// carry or lend sh.usecs to sh.secs, in packages of 1e6 usecs (whole secs).
// as we are here, we know we must carry at least 1 sec (1 million usec)
int nsec = (sh.tv_usec - x->tv_usec) / 1000000 + 1;
sh.tv_usec -= 1000000 * nsec;
sh.tv_sec += nsec;
}
// if (x->tv_usec - sh.tv_usec > 1000000) { // could show tv{x,1000000}, not 'normal'
if (x->tv_usec - sh.tv_usec > 999999) { // normalize 0-999999
// normalize diff; increase sh.usecs so usec diff will be < 1000000.
// carry or lend whole sh.secs to sh.usecs
int nsec = (x->tv_usec - sh.tv_usec) / 1000000;
sh.tv_usec += 1000000 * nsec;
sh.tv_sec -= nsec;
}
// should now have the subtrahend sec/usec that will produce normalized difference
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
diff->tv_sec = x->tv_sec - sh.tv_sec;
diff->tv_usec = x->tv_usec - sh.tv_usec;
/* Return 1 if diff is negative. */
return x->tv_sec < sh.tv_sec;
// timeval_subtract
}
If you need to support both 32 and 64 bit time_t types, it complicates outputting results, but you might call timeval_subtract() with something like below:
// replace MY_SPECIFIC_PREPROC_8B_DEF with your own
// preprocessor time_t distinguishing define
#if defined MY_SPECIFIC_PREPROC_8B_DEF
#define LSPEC "lld" // format specifier input length
char fmt[] = "% 020" LSPEC " % 011ld "; // long long tv_sec"
#define MAX_TIME_T 0x7fffffffffffffff
#define MIN_TIME_T 0x8000000000000000
#else
#define LSPEC "ld"
char fmt[] = "% 011" LSPEC " % 011ld "; // less chars for long tv_sec"
#define MAX_TIME_T 0x7fffffff
#define MIN_TIME_T 0x80000000
#endif
const time_t max_time_t = MAX_TIME_T;
const time_t min_time_t = MIN_TIME_T;
// Test overflow of both timeval members, sec & usec
struct timeval a = {min_time_t, 1}; // 1 usec > negative overflow
struct timeval b = {0, 0}; // our subtrahend, ++1 usec in loop
struct timeval c = {0, 0}; // holds result; difference in this case
strcat (fmt, "= a{%" LSPEC ",%ld} - b{%" LSPEC ",%ld}\n");
for (auto i=0; i<3; i++) {
timeval_subtract (&a,&b,&c);
Serial.printf(fmt,
c.tv_sec, c.tv_usec, a.tv_sec, a.tv_usec, b.tv_sec, b.tv_usec);
b.tv_usec += 1; // normal time flow
}
// Without an appropriate preprocessor define this may compile
for (auto i=0; i<3; i++) {
timeval_subtract (&a,&b,&c);
// explicit casts try to quiet compiler on other sized type_t systems
if (8 == sizeof(time_t)) {
Serial.printf("% 020lld % 011ld = a{%lld,%ld} - b{%lld,%ld}\n",
(long long)c.tv_sec, c.tv_usec,
(long long)a.tv_sec, a.tv_usec,
(long long)b.tv_sec, b.tv_usec);
}
else if (4 == sizeof(time_t)) {
Serial.printf("% 011ld % 011ld = a{%ld,%ld} - b{%ld,%ld}\n",
(long)c.tv_sec, c.tv_usec,
(long)a.tv_sec, a.tv_usec,
(long)b.tv_sec, b.tv_usec);
}
b.tv_usec += 1; // normal time flow
}
I'm writing a socket program that maintains FIFO queues for two input sockets. When deciding which queue to service, the program pulls the most recent time-stamp from each queue.
I need a reliable method for comparing two timeval structs. I tried using timercmp(), but my version of gcc doesn't support it, and documentation states that the function is not POSIX compliant.
What should I do?
timercmp() is just a macro in libc (sys/time.h):
# define timercmp(a, b, CMP) \
(((a)->tv_sec == (b)->tv_sec) ? \
((a)->tv_usec CMP (b)->tv_usec) : \
((a)->tv_sec CMP (b)->tv_sec))
If you need timersub():
# define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
googling timeval give this first result. From that page:
It is often necessary to subtract two values of type struct timeval or struct timespec. Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.
/* Subtract the `struct timeval' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */
int
timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
This is slightly different, but I think clearly illustrates the logic involved.
I'm working on some MSP430 code in C, and have a timestamp struct very similar to timeval, but with nsecs instead of usecs.
This code keeps everything positive, so unsigned ints would work fine, and avoids overflows (I think). It also doesn't modify the timestamps/timevals being passed in, except the result of course.
typedef struct timestamp {
int32_t secs;
int32_t nsecs;
} timestamp_t;
int timestamp_sub(timestamp_t * x, timestamp_t * y, timestamp_t * result){
// returns 1 if difference is negative, 0 otherwise
// result is the absolute value of the difference between x and y
negative = 0;
if( x->secs > y->secs ){
if( x->nsecs > y->nsecs ){
result->secs = x->secs - y->secs;
result->nsecs = x->nsecs - y->nsecs;
}else{
result->secs = x->secs - y->secs - 1;
result->nsecs = (1000*1000*1000) - y->nsecs + x->nsecs;
}
}else{
if( x->secs == y->secs ){
result->secs = 0;
if( x->nsecs > y->nsecs ){
result->nsecs = x->nsecs - y->nsecs;
}else{
negative = 1;
result->nsecs = y->nsecs - x->nsecs;
}
}else{
negative = 1;
if( x->nsecs > y->nsecs ){
result->secs = y->secs - x->secs - 1;
result->nsecs = (1000*1000*1000) - x->nsecs + y->nsecs;
}else{
result->secs = y->secs - x->secs;
result->nsecs = y->nsecs - x->nsecs;
}
}
}
return negative;
}
For viewing timevals I just whipped this up. It returns a timeval as a string that you can print or send to a text file:
char *tv2str(struct timeval *intv) {
static char ans[200];
snprintf(ans,200,"%u.%u",(unsigned int)intv->tv_sec, \
(unsigned int) intv->tv_usec);
return ans;
}
Use like:
printf("nowtv: %s\n",tv2str(&nowtv));
nowtv: 1568407554.646623
Timercmp() didn't seem to work right so I wanted a way to check up on it by actually looking at some values.