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);