@cryptotaxi247 / netdata-1 / commits / b57ec553c

80% speed increase in number printing on 32bit systems

Costa Tsaousis (ktsaou) committed Mar 20, 2015 at 00:41 UTC b57ec553cbbfa2fb4796e86054acb1b2aa95e3e6
4 files changed +96 -57
src/storage_number.c
+94
@@ -5,6 +5,14 @@
5 #include "log.h"
6 #include "storage_number.h"
7
8 +#if __GNUC__
9 +#if __x86_64__ || __ppc64__
10 +#define ENVIRONMENT64
11 +#else
12 +#define ENVIRONMENT32
13 +#endif
14 +#endif
15 +
16 storage_number pack_storage_number(calculated_number value)
17 {
18 storage_number r = 0;
@@ -92,3 +100,89 @@ calculated_number unpack_storage_number(storage_number value)
100 if(sign) n = -n;
101 return n;
102 }
103 +
104 +#ifdef ENVIRONMENT32
105 +// This trick seems to give an 80% speed increase in 32bit systems
106 +// print_calculated_number_llu_r() will just print the digits up to the
107 +// point the remaining value fits in 32 bits, and then calls
108 +// print_calculated_number_lu_r() to print the rest with 32 bit arithmetic.
109 +
110 +static char *print_calculated_number_lu_r(char *str, unsigned long uvalue) {
111 + char *wstr = str;
112 +
113 + // print each digit
114 + do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
115 + return wstr;
116 +}
117 +
118 +static char *print_calculated_number_llu_r(char *str, unsigned long long uvalue) {
119 + char *wstr = str;
120 +
121 + // print each digit
122 + do *wstr++ = (char)(48 + (uvalue % 10)); while((uvalue /= 10) && uvalue > (unsigned long long)0xffffffff);
123 + if(uvalue) return print_calculated_number_lu_r(wstr, uvalue);
124 + return wstr;
125 +}
126 +#endif
127 +
128 +int print_calculated_number(char *str, calculated_number value)
129 +{
130 + char *wstr = str;
131 +
132 + int sign = (value < 0) ? 1 : 0;
133 + if(sign) value = -value;
134 +
135 +#ifdef STORAGE_WITH_MATH
136 + // without llrint() there are rounding problems
137 + // for example 0.9 becomes 0.89
138 + unsigned long long uvalue = llrint(value * (calculated_number)100000);
139 +#else
140 + unsigned long long uvalue = value * (calculated_number)100000;
141 +#endif
142 +
143 +#ifdef ENVIRONMENT32
144 + if(uvalue > (unsigned long long)0xffffffff)
145 + wstr = print_calculated_number_llu_r(str, uvalue);
146 + else
147 + wstr = print_calculated_number_lu_r(str, uvalue);
148 +#else
149 + do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
150 +#endif
151 +
152 + // make sure we have 6 bytes at least
153 + while((wstr - str) < 6) *wstr++ = '0';
154 +
155 + // put the sign back
156 + if(sign) *wstr++ = '-';
157 +
158 + // reverse it
159 + char *begin = str, *end = --wstr, aux;
160 + while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
161 + // wstr--;
162 + // strreverse(str, wstr);
163 +
164 + // remove trailing zeros
165 + int decimal = 5;
166 + while(decimal > 0 && *wstr == '0') {
167 + *wstr-- = '\0';
168 + decimal--;
169 + }
170 +
171 + // terminate it, one position to the right
172 + // to let space for a dot
173 + wstr[2] = '\0';
174 +
175 + // make space for the dot
176 + int i;
177 + for(i = 0; i < decimal ;i++) {
178 + wstr[1] = wstr[0];
179 + wstr--;
180 + }
181 +
182 + // put the dot
183 + if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
184 + else wstr[1] = '.';
185 +
186 + // return the buffer length
187 + return ( (wstr - str) + 2 + decimal );
188 +}
src/storage_number.h
+2
@@ -18,6 +18,8 @@ typedef uint32_t ustorage_number;
18 storage_number pack_storage_number(calculated_number value);
19 calculated_number unpack_storage_number(storage_number value);
20
21 +int print_calculated_number(char *str, calculated_number value);
22 +
23 #define STORAGE_NUMBER_POSITIVE_MAX 167772150000000.0
24 #define STORAGE_NUMBER_POSITIVE_MIN 0.00001
25 #define STORAGE_NUMBER_NEGATIVE_MAX -0.00001
src/web_buffer.c
-56
@@ -20,62 +20,6 @@ void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
20 wb->bytes = bytes;
21 }
22
23 -int print_calculated_number(char *str, calculated_number value)
24 -{
25 - char *wstr = str;
26 -
27 - int sign = (value < 0) ? 1 : 0;
28 - if(sign) value = -value;
29 -
30 -#ifdef STORAGE_WITH_MATH
31 - // without llrint() there are rounding problems
32 - // for example 0.9 becomes 0.89
33 - unsigned long long uvalue = llrint(value * (calculated_number)100000);
34 -#else
35 - unsigned long long uvalue = value * (calculated_number)100000;
36 -#endif
37 -
38 - // print each digit
39 - do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
40 -
41 - // make sure we have 6 bytes at least
42 - while((wstr - str) < 6) *wstr++ = '0';
43 -
44 - // put the sign back
45 - if(sign) *wstr++ = '-';
46 -
47 - // reverse it
48 - char *begin = str, *end = --wstr, aux;
49 - while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
50 - // wstr--;
51 - // strreverse(str, wstr);
52 -
53 - // remove trailing zeros
54 - int decimal = 5;
55 - while(decimal > 0 && *wstr == '0') {
56 - *wstr-- = '\0';
57 - decimal--;
58 - }
59 -
60 - // terminate it, one position to the right
61 - // to let space for a dot
62 - wstr[2] = '\0';
63 -
64 - // make space for the dot
65 - int i;
66 - for(i = 0; i < decimal ;i++) {
67 - wstr[1] = wstr[0];
68 - wstr--;
69 - }
70 -
71 - // put the dot
72 - if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
73 - else wstr[1] = '.';
74 -
75 - // return the buffer length
76 - return ( (wstr - str) + 2 + decimal );
77 -}
78 -
23 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value)
24 {
25 if(wb->size - wb->bytes < 50) return;
src/web_buffer.h
-1
@@ -37,7 +37,6 @@ struct web_buffer {
37 #define web_buffer_reset(wb) wb->buffer[wb->bytes = 0] = '\0'
38
39 void web_buffer_strcpy(struct web_buffer *wb, const char *txt);
40 -int print_calculated_number(char *str, calculated_number value);
40 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value);
41
42 void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds);