Skip to content

Instantly share code, notes, and snippets.

@mattsta
Created September 11, 2014 03:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattsta/65a07e304db4f99604c7 to your computer and use it in GitHub Desktop.
Save mattsta/65a07e304db4f99604c7 to your computer and use it in GitHub Desktop.
Quick redis integer size parsing tests
/* Usage: ./size_parse INTEGER [1-5] */
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
static long long ustime(void) {
struct timeval tv;
long long ust;
gettimeofday(&tv, NULL);
ust = ((long long)tv.tv_sec)*1e6;
ust += tv.tv_usec;
return ust;
}
inline int decDigitCount_div10(int64_t d) {
int l;
if (d < 0) {
l = 1;
d = -d;
} else {
l = 0;
}
while (d) {
l++;
d /= 10;
}
return l;
}
/* Return the number of digits of 'v' when converted to string in radix 10.
* See ll2string() for more information. */
uint32_t digits10(uint64_t v) {
if (v < 10) return 1;
if (v < 100) return 2;
if (v < 1000) return 3;
if (v < 1000000000000UL) {
if (v < 100000000UL) {
if (v < 1000000) {
if (v < 10000) return 4;
return 5 + (v >= 100000);
}
return 7 + (v >= 10000000UL);
}
if (v < 10000000000UL) {
return 9 + (v >= 1000000000UL);
}
return 11 + (v >= 100000000000UL);
}
return 12 + digits10(v / 1000000000000UL);
}
size_t decDigitCount(int64_t d) {
size_t l = 0;
if (d < 0) {
d = -d;
l = 1;
} else {
l = 0;
}
if (d > 10000000000) goto its_really_big;
if (d < 10) return 1 + l;
if (d < 100) return 2 + l;
if (d < 1000) return 3 + l;
if (d < 10000) return 4 + l;
if (d < 100000) return 5 + l;
if (d < 1000000) return 6 + l;
if (d < 10000000) return 7 + l;
if (d < 100000000) return 8 + l;
if (d < 1000000000) return 9 + l;
if (d < 10000000000) return 10 + l;
its_really_big:
if (d < 100000000000) return 11 + l;
if (d < 1000000000000) return 12 + l;
if (d < 10000000000000) return 13 + l;
if (d < 100000000000000) return 14 + l;
if (d < 1000000000000000) return 15 + l;
if (d < 10000000000000000) return 16 + l;
if (d < 100000000000000000) return 17 + l;
if (d < 1000000000000000000) return 18 + l;
return 19 + l;
}
int main(int argc, char *argv[]) {
long long n = atoll(argv[1]);
long long init_n = n;
int which = atoi(argv[2]);
long long stopper = (long long)10e7;
size_t len = 0;
long long i;
long long start = ustime();
if (which == 1) {
for (i = 0; i < stopper; i++) {
n = init_n;
len = 1;
if (n < 0) {
len++;
n = -n;
}
while((n = n/10) != 0) {
len++;
}
}
} else if (which == 2) {
for (i = 0; i < stopper; i++) {
len = decDigitCount(n);
}
} else if (which == 3) {
for (i = 0; i < stopper; i++) {
len = digits10(n);
}
} else if (which == 4) {
for (i = 0; i < stopper; i++) {
len = decDigitCount_div10(n);
}
} else if (which == 5) {
for (i = 0; i < stopper; i++) {
n = init_n;
if (n < 0) {
len = 1;
n = -n;
} else {
len = 0;
}
while (n) {
len++;
n /= 10;
}
}
}
long long end = ustime();
printf("result: %lu for %d\n", len, which);
printf("duration: %llu\n", end-start);
}
@mattsta
Copy link
Author

mattsta commented Sep 11, 2014

Example results compiled with clang -O3 -o test test.c:

matt@ununoctium:/tmp/t% ./test 9999999999999 5
result: 14 for 5
duration: 1913116
matt@ununoctium:/tmp/t% ./test 9999999999999 4
result: 14 for 4
duration: 1895450
matt@ununoctium:/tmp/t% ./test 9999999999999 3
result: 14 for 3
duration: 0
matt@ununoctium:/tmp/t% ./test 9999999999999 2
result: 14 for 2
duration: 0
matt@ununoctium:/tmp/t% ./test 9999999999999 1
result: 14 for 1
duration: 1744538

Compile different ways and test the performance changes:

clang -O3 -o size_parse-clang-O3 size_parse.c
gcc -O3 -o size_parse-gcc-O3 size_parse.c
clang -O2 -o size_parse-clang-O2 size_parse.c
gcc -O2 -o size_parse-gcc-O2 size_parse.c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment