Fast time string to seconds
Investigating another code execution hotspot, the case involved converting a time string representing 24 hour time into the number of seconds elapsed since midnight.
The 24-hour time format is HH:MM:SS
.
Code was similar to the following:
int Convert2ByteToInt( char *s )
{
return (s[0] - '0') * 10 + (s[1] - '0');
}
// assme dt[] - array represent date & 24 hour time
// assume offset 11 is where the 24 hour time begins
int secs = Convert2ByteToInt( &dt[11] ) * 3600 +
Convert2ByteToInt( &dt[14] ) * 60 +
Convert2ByteToInt( &dt[17] );
Estimated cost is:
Convert2ByteToInt
function cost:
- 2 Loads
- 2 Subtracts, 1 Add
- 1 Multiply
Total: 5 ops, 1 Multiply
main code cost:
- 3 Adds for array indexing
- 2 Multiplies
- 2 Adds
Total: 5 ops, 2 Multiplies
Estimated total cost is 3 x (5 ops, 1 Multiply) + (5 ops, 2 Multiplies) = 20 ops, 5 Multiplies
Using the techniques from yesterday’s post Fast numeric string to int, we can write a faster version.
long long sum;
// 24 hour time string of form: "12:34:56"
// loaded into 64-bit register as: 0x36353A34333A3231
sum = *(long long *)dt & 0x0F07000F07000F03;
sum = (sum * 2561) >> 8;
// move seconds into ones position
// multiply mins by 60, multiply hours by 3600 and
// shift right into minutes position
// move converted hours & mins into ones pos
// sum = (sum >> 48) + ((sum & 0x000000003F00001F) *
// ( 60 + (((long long) 1<<24 ) * 3600)) ) >> 24;
sum = (sum >> 48) + ((sum & 0x000000003F00001F) * 0xE1000003C) >> 24;
// max number of secs is 24 * 60 * 60
int secs = (int)(sum) & 0x1FFFF;
Estimated cost is:
- 1 Load, 1 Bitwise AND
- 1 Multiply, 1 Shift right
- 2 Shift right, 1 Add, 1 Bitwise AND, 1 Multiply
- 1 Bitwise AND
Estimated total cost is 8 ops, 2 Multiplies
Algorithm | Ops | Multiplies |
---|---|---|
Original | 20 | 5 |
SIMD | 8 | 2 |
Written on November 29, 2016