]> arthur.barton.de Git - netdata.git/commitdiff
80% speed increase in number printing on 32bit systems
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Thu, 19 Mar 2015 22:41:46 +0000 (00:41 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Thu, 19 Mar 2015 22:41:46 +0000 (00:41 +0200)
src/storage_number.c
src/storage_number.h
src/web_buffer.c
src/web_buffer.h

index 6ef994def0f4f58972413789c17faf22c910c5a7..97eea1c90213322d1fee4e0d62f639a46a902a3a 100755 (executable)
@@ -5,6 +5,14 @@
 #include "log.h"
 #include "storage_number.h"
 
+#if __GNUC__
+#if __x86_64__ || __ppc64__
+#define ENVIRONMENT64
+#else
+#define ENVIRONMENT32
+#endif
+#endif
+
 storage_number pack_storage_number(calculated_number value)
 {
        storage_number r = 0;
@@ -92,3 +100,89 @@ calculated_number unpack_storage_number(storage_number value)
        if(sign) n = -n;
        return n;
 }
+
+#ifdef ENVIRONMENT32
+// This trick seems to give an 80% speed increase in 32bit systems
+// print_calculated_number_llu_r() will just print the digits up to the
+// point the remaining value fits in 32 bits, and then calls
+// print_calculated_number_lu_r() to print the rest with 32 bit arithmetic.
+
+static char *print_calculated_number_lu_r(char *str, unsigned long uvalue) {
+       char *wstr = str;
+       
+       // print each digit
+       do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
+       return wstr;
+}
+
+static char *print_calculated_number_llu_r(char *str, unsigned long long uvalue) {
+       char *wstr = str;
+
+       // print each digit
+       do *wstr++ = (char)(48 + (uvalue % 10)); while((uvalue /= 10) && uvalue > (unsigned long long)0xffffffff);
+       if(uvalue) return print_calculated_number_lu_r(wstr, uvalue);
+       return wstr;
+}
+#endif
+
+int print_calculated_number(char *str, calculated_number value)
+{
+       char *wstr = str;
+
+       int sign = (value < 0) ? 1 : 0;
+       if(sign) value = -value;
+
+#ifdef STORAGE_WITH_MATH
+       // without llrint() there are rounding problems
+       // for example 0.9 becomes 0.89
+       unsigned long long uvalue = llrint(value * (calculated_number)100000);
+#else
+       unsigned long long uvalue = value * (calculated_number)100000;
+#endif
+
+#ifdef ENVIRONMENT32
+       if(uvalue > (unsigned long long)0xffffffff)
+               wstr = print_calculated_number_llu_r(str, uvalue);
+       else
+               wstr = print_calculated_number_lu_r(str, uvalue);
+#else
+       do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
+#endif
+
+       // make sure we have 6 bytes at least
+       while((wstr - str) < 6) *wstr++ = '0';
+
+       // put the sign back
+       if(sign) *wstr++ = '-';
+
+       // reverse it
+    char *begin = str, *end = --wstr, aux;
+    while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
+       // wstr--;
+       // strreverse(str, wstr);
+
+       // remove trailing zeros
+       int decimal = 5;
+       while(decimal > 0 && *wstr == '0') {
+               *wstr-- = '\0';
+               decimal--;
+       }
+
+       // terminate it, one position to the right
+       // to let space for a dot
+       wstr[2] = '\0';
+
+       // make space for the dot
+       int i;
+       for(i = 0; i < decimal ;i++) {
+               wstr[1] = wstr[0];
+               wstr--;
+       }
+
+       // put the dot
+       if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
+       else wstr[1] = '.';
+
+       // return the buffer length
+       return ( (wstr - str) + 2 + decimal );
+}
index 2fba80a105554aae73c127de0255de5ed505b2d0..c21f42797620ddb1ed490f6a4b86c0c8bf7bea31 100755 (executable)
@@ -18,6 +18,8 @@ typedef uint32_t ustorage_number;
 storage_number pack_storage_number(calculated_number value);
 calculated_number unpack_storage_number(storage_number value);
 
+int print_calculated_number(char *str, calculated_number value);
+
 #define STORAGE_NUMBER_POSITIVE_MAX 167772150000000.0
 #define STORAGE_NUMBER_POSITIVE_MIN 0.00001
 #define STORAGE_NUMBER_NEGATIVE_MAX -0.00001
index 7c57ce8c6a9a034669d5531bb02107a38fdcbabc..d9eb11d54b93453f83da1306e98190097c3f8b15 100755 (executable)
@@ -20,62 +20,6 @@ void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
        wb->bytes = bytes;
 }
 
-int print_calculated_number(char *str, calculated_number value)
-{
-       char *wstr = str;
-
-       int sign = (value < 0) ? 1 : 0;
-       if(sign) value = -value;
-
-#ifdef STORAGE_WITH_MATH
-       // without llrint() there are rounding problems
-       // for example 0.9 becomes 0.89
-       unsigned long long uvalue = llrint(value * (calculated_number)100000);
-#else
-       unsigned long long uvalue = value * (calculated_number)100000;
-#endif
-
-       // print each digit
-       do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
-
-       // make sure we have 6 bytes at least
-       while((wstr - str) < 6) *wstr++ = '0';
-
-       // put the sign back
-       if(sign) *wstr++ = '-';
-
-       // reverse it
-    char *begin = str, *end = --wstr, aux;
-    while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
-       // wstr--;
-       // strreverse(str, wstr);
-
-       // remove trailing zeros
-       int decimal = 5;
-       while(decimal > 0 && *wstr == '0') {
-               *wstr-- = '\0';
-               decimal--;
-       }
-
-       // terminate it, one position to the right
-       // to let space for a dot
-       wstr[2] = '\0';
-
-       // make space for the dot
-       int i;
-       for(i = 0; i < decimal ;i++) {
-               wstr[1] = wstr[0];
-               wstr--;
-       }
-
-       // put the dot
-       if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
-       else wstr[1] = '.';
-
-       // return the buffer length
-       return ( (wstr - str) + 2 + decimal );
-}
-
 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value)
 {
        if(wb->size - wb->bytes < 50) return;
index 6000ec50dc221841c134e52b72645453c4ee422a..ae237afe3f54edc880b06b0dc6f176fb4ecc4b6b 100755 (executable)
@@ -37,7 +37,6 @@ struct web_buffer {
 #define web_buffer_reset(wb) wb->buffer[wb->bytes = 0] = '\0'
 
 void web_buffer_strcpy(struct web_buffer *wb, const char *txt);
-int print_calculated_number(char *str, calculated_number value);
 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value);
 
 void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds);