This is a continuation to my previous post on choosing a glibc function that could potentially be optimized. Now I’ll discuss my proposed approach for potential optimization.

## difftime

difftime has a few handlers for calculating doubles and long doubles, but for any other types it will simply subtract the larger time value from the smaller one and return the result.

Let’s look at difftime first:

/* Return the difference between TIME1 and TIME0. */ double __difftime (time_t time1, time_t time0) { /* Convert to double and then subtract if no double-rounding error could result. */ if (TYPE_BITS (time_t) <= DBL_MANT_DIG || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double))) return (double) time1 - (double) time0; /* Likewise for long double. */ if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t)) return (long double) time1 - (long double) time0; /* Subtract the smaller integer from the larger, convert the difference to double, and then negate if needed. */ return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0); }

The IF condition for doubles does not contain any significantly expensive operations (i.e. multiply, divide), and since it doesn’t, it may not be necessary to change anything here, but, we know that if the first condition before the OR is not met, we won’t need to execute the second condition, so this could also be written as:

if (TYPE_BITS (time_t) <= DBL_MANT_DIG) {return (double) time1 - (double) time0;} if (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double))) {return (double) time1 - (double) time0;}

Since the first condition is the smaller of the two, we test it first and immediately return our result if the condition is met. If not, we can then check the next slightly larger condition.

We can apply a similar approach for the second condition:

if (TYPE_FLOATING (time_t)) {return (long double) time1 - (long double) time0;} if (TYPE_BITS (time_t) <= LDBL_MANT_DIG) {return (long double) time1 - (long double) time0;}

Something else I noticed inside the __difftime function was the checks for double and long double were always returning time1 minus time0 regardless of which was the larger value. On my particular machine (x86_64), the second IF condition was true since `TYPE_BITS(time_t)`

was lower than `LDBL_MANT_DIG`

, so line 11 was being executed.

double __difftime (time_t time1, time_t time0) { if (TYPE_BITS (time_t) <= DBL_MANT_DIG || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double))) { return (double) time1 - (double) time0; } if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t)) { //return time1 < time0 ? (long double) time0 - (long double) time1 : (long double) return (long double) time1 - (long double) time0; } return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0); }

I wrote a small tester for this:

int main() { // test difftime function time_t time1 = time(NULL); time_t time0 = time(NULL) + 10; printf("time1 = %d\ntime0 = %d\n", time1, time0); double result; result = __difftime(time1, time0); printf("difftime(time1, time0) = %f\n", result); result = __difftime(time0, time1); printf("difftime(time0, time1) = %f\n", result); return 0; }

Which outputs:

__difftime time1 = 1489180977 time0 = 1489180987 difftime(time1, time0) = -10.000000 __difftime time1 = 1489180987 time0 = 1489180977 difftime(time0, time1) = 10.000000

Both results should return 10, but we are missing the `time1 < time0`

comparison check for each of those conditions, so I included the ternary operators in both conditions:

double __difftime (time_t time1, time_t time0) { if (TYPE_BITS (time_t) <= DBL_MANT_DIG || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double))) { return time1 < time0 ? (double) time0 - (double) time1 : (double) time1 - (double) } if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t)) { return time1 < time0 ? (long double) time0 - (long double) time1 : (long double) } ... }

New output:

__difftime time1 = 1489181645 time0 = 1489181655 difftime(time1, time0) = 10.000000 __difftime time1 = 1489181655 time0 = 1489181645 difftime(time0, time1) = 10.000000

## subtract

This function is called for any number other than double or long double type. If the time_t type is not a signed type, then the function simply returns the result of `time1 - time0`

. If `time_t`

type *is* a signed type, handle optimization.