@cryptotaxi247 / netdata-1 / commits / 9da67ae21

better unit testing of storage numbers; added benchmarking

Costa Tsaousis (ktsaou) committed Mar 19, 2015 at 21:56 UTC 9da67ae21ab296027e229db0092b9019c717305e
3 files changed +187 -46
src/storage_number.h
+5
@@ -18,4 +18,9 @@ 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 +#define STORAGE_NUMBER_POSITIVE_MAX 167772150000000.0
22 +#define STORAGE_NUMBER_POSITIVE_MIN 0.00001
23 +#define STORAGE_NUMBER_NEGATIVE_MAX -0.00001
24 +#define STORAGE_NUMBER_NEGATIVE_MIN -167772150000000.0
25 +
26 #endif /* NETDATA_STORAGE_NUMBER_H */
src/unit_test.c
+178 -44
@@ -1,17 +1,186 @@
1 #include <stdio.h>
2 #include <stdlib.h>
3 +#include <string.h>
4 +#include <sys/resource.h>
5
6 #include "storage_number.h"
7 #include "rrd.h"
8 #include "log.h"
9 #include "web_buffer.h"
10
11 +#define ACCURACY_LOSS 0.0000001
12 +
13 +int check_storage_number(calculated_number n, int debug) {
14 + char buffer[100];
15 +
16 + storage_number s = pack_storage_number(n);
17 + calculated_number d = unpack_storage_number(s);
18 +
19 + calculated_number ddiff = d - n;
20 + calculated_number dcdiff = ddiff * 100.0 / n;
21 +
22 + if(dcdiff < 0) dcdiff = -dcdiff;
23 +
24 + size_t len = print_calculated_number(buffer, d);
25 + calculated_number p = strtold(buffer, NULL);
26 + calculated_number pdiff = n - p;
27 + calculated_number pcdiff = pdiff * 100.0 / n;
28 + if(pcdiff < 0) pcdiff = -pcdiff;
29 +
30 + if(debug) {
31 + fprintf(stderr,
32 + CALCULATED_NUMBER_FORMAT " original\n"
33 + CALCULATED_NUMBER_FORMAT " packed and unpacked, (stored as 0x%08X, diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n"
34 + "%s printed after unpacked (%lu bytes)\n"
35 + CALCULATED_NUMBER_FORMAT " re-parsed from printed (diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n\n",
36 + n,
37 + d, s, ddiff, dcdiff,
38 + buffer,
39 + len, p, pdiff, pcdiff
40 + );
41 + if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %lu but it has %lu\n", buffer, len, strlen(buffer));
42 + if(dcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, dcdiff);
43 + if(pcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, pcdiff);
44 + }
45 +
46 + if(len != strlen(buffer)) return 1;
47 + if(dcdiff > ACCURACY_LOSS) return 3;
48 + if(pcdiff > ACCURACY_LOSS) return 4;
49 + return 0;
50 +}
51 +
52 +void benchmark_storage_number(int loop, int multiplier) {
53 + int i, j;
54 + calculated_number n, d;
55 + storage_number s;
56 + unsigned long long user, system, total, mine, their;
57 +
58 + char buffer[100];
59 +
60 + struct rusage now, last;
61 +
62 + fprintf(stderr, "\n\nBenchmarking %d numbers, please wait...\n\n", loop);
63 +
64 + // ------------------------------------------------------------------------
65 +
66 + fprintf(stderr, "SYSTEM LONG DOUBLE SIZE: %lu bytes\n", sizeof(calculated_number));
67 + fprintf(stderr, "NETDATA FLOATING POINT SIZE: %lu bytes\n", sizeof(storage_number));
68 +
69 + mine = (calculated_number)sizeof(storage_number) * (calculated_number)loop;
70 + their = (calculated_number)sizeof(calculated_number) * (calculated_number)loop;
71 +
72 + if(mine > their) {
73 + fprintf(stderr, "\nNETDATA NEEDS %0.2Lf TIMES MORE MEMORY. Sorry!\n", (long double)(mine / their));
74 + }
75 + else {
76 + fprintf(stderr, "\nNETDATA INTERNAL FLOATING POINT ARITHMETICS NEEDS %0.2Lf TIMES LESS MEMORY.\n", (long double)(their / mine));
77 + }
78 +
79 + fprintf(stderr, "\nNETDATA FLOATING POINT\n");
80 + fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MIN);
81 + fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MAX);
82 + fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MIN);
83 + fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MAX);
84 + fprintf(stderr, "Maximum accuracy loss: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS);
85 +
86 + // ------------------------------------------------------------------------
87 +
88 + fprintf(stderr, "INTERNAL LONG DOUBLE PRINTING: ");
89 + getrusage(RUSAGE_SELF, &last);
90 +
91 + // do the job
92 + for(j = 1; j < 11 ;j++) {
93 + n = STORAGE_NUMBER_POSITIVE_MIN * j;
94 +
95 + for(i = 0; i < loop ;i++) {
96 + n *= multiplier;
97 + if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
98 +
99 + print_calculated_number(buffer, n);
100 + }
101 + }
102 +
103 + getrusage(RUSAGE_SELF, &now);
104 + user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
105 + system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
106 + total = user + system;
107 + mine = total;
108 +
109 + fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
110 +
111 + // ------------------------------------------------------------------------
112 +
113 + fprintf(stderr, "SYSTEM LONG DOUBLE PRINTING: ");
114 + getrusage(RUSAGE_SELF, &last);
115 +
116 + // do the job
117 + for(j = 1; j < 11 ;j++) {
118 + n = STORAGE_NUMBER_POSITIVE_MIN * j;
119 +
120 + for(i = 0; i < loop ;i++) {
121 + n *= multiplier;
122 + if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
123 + snprintf(buffer, 100, CALCULATED_NUMBER_FORMAT, n);
124 + }
125 + }
126 +
127 + getrusage(RUSAGE_SELF, &now);
128 + user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
129 + system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
130 + total = user + system;
131 + their = total;
132 +
133 + fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
134 +
135 + if(mine > total) {
136 + fprintf(stderr, "NETDATA CODE IS SLOWER %0.2Lf TIMES\n", (long double)(mine / their));
137 + }
138 + else {
139 + fprintf(stderr, "NETDATA CODE IS F A S T E R %0.2Lf TIMES\n", (long double)(their / mine));
140 + }
141 +
142 + // ------------------------------------------------------------------------
143 +
144 + fprintf(stderr, "\nINTERNAL LONG DOUBLE PRINTING WITH PACK / UNPACK: ");
145 + getrusage(RUSAGE_SELF, &last);
146 +
147 + // do the job
148 + for(j = 1; j < 11 ;j++) {
149 + n = STORAGE_NUMBER_POSITIVE_MIN * j;
150 +
151 + for(i = 0; i < loop ;i++) {
152 + n *= multiplier;
153 + if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
154 +
155 + s = pack_storage_number(n);
156 + d = unpack_storage_number(s);
157 + print_calculated_number(buffer, d);
158 + }
159 + }
160 +
161 + getrusage(RUSAGE_SELF, &now);
162 + user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
163 + system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
164 + total = user + system;
165 + mine = total;
166 +
167 + fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
168 +
169 + if(mine > their) {
170 + fprintf(stderr, "WITH PACKING UNPACKING NETDATA CODE IS SLOWER %0.2Lf TIMES\n", (long double)(mine / their));
171 + }
172 + else {
173 + fprintf(stderr, "EVEN WITH PACKING AND UNPACKING, NETDATA CODE IS F A S T E R %0.2Lf TIMES\n", (long double)(their / mine));
174 + }
175 +
176 + // ------------------------------------------------------------------------
177 +
178 +}
179 +
180 int unit_test_storage()
181 {
11 - char buffer[100], *msg;
12 - storage_number s;
13 - calculated_number c, a = 0, d, ddiff, dcdiff, f, p, pdiff, pcdiff, maxddiff = 0, maxpdiff = 0;
14 - int i, j, g, r = 0, l;
182 + calculated_number c, a = 0;
183 + int i, j, g, r = 0;
184
185 for(g = -1; g <= 1 ; g++) {
186 a = 0;
@@ -22,50 +191,15 @@ int unit_test_storage()
191 a += 0.0000001;
192 c = a * g;
193 for(i = 0; i < 21 ;i++, c *= 10) {
25 - if(c > 0 && c < 0.00001) continue;
26 - if(c < 0 && c > -0.00001) continue;
27 -
28 - s = pack_storage_number(c);
29 - d = unpack_storage_number(s);
30 -
31 - ddiff = d - c;
32 - dcdiff = ddiff * 100.0 / c;
33 - if(dcdiff < 0) dcdiff = -dcdiff;
34 - if(dcdiff > maxddiff) maxddiff = dcdiff;
35 -
36 - f = d / c;
37 -
38 - l = print_calculated_number(buffer, d);
39 - p = strtold(buffer, NULL);
40 - pdiff = c - p;
41 - pcdiff = pdiff * 100.0 / c;
42 - if(pcdiff < 0) pcdiff = -pcdiff;
43 - if(pcdiff > maxpdiff) maxpdiff = pcdiff;
44 -
45 - if(f < 0.99999 || f > 1.00001) {
46 - msg = "ERROR";
47 - r++;
48 - }
49 - else msg = "OK";
50 -
51 - fprintf(stderr, "%s\n"
52 - CALCULATED_NUMBER_FORMAT " original\n"
53 - CALCULATED_NUMBER_FORMAT " unpacked, (stored as 0x%08X, diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n"
54 - "%s printed (%d bytes)\n"
55 - CALCULATED_NUMBER_FORMAT " re-parsed with diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%\n\n",
56 - msg,
57 - c,
58 - d, s, ddiff, dcdiff,
59 - buffer,
60 - l, p, pdiff, pcdiff
61 - );
194 + if(c > 0 && c < STORAGE_NUMBER_POSITIVE_MIN) continue;
195 + if(c < 0 && c > STORAGE_NUMBER_NEGATIVE_MAX) continue;
196 +
197 + if(check_storage_number(c, 1)) return 1;
198 }
199 }
200 }
201
66 - fprintf(stderr, "Worst accuracy loss on unpacked numbers: " CALCULATED_NUMBER_FORMAT "%%\n", maxddiff);
67 - fprintf(stderr, "Worst accuracy loss on printed numbers: " CALCULATED_NUMBER_FORMAT "%%\n", maxpdiff);
68 -
202 + benchmark_storage_number(1000000, 2);
203 return r;
204 }
205
src/web_buffer.c
+4 -2
@@ -38,8 +38,10 @@ int print_calculated_number(char *str, calculated_number value)
38 if(sign) *wstr++ = '-';
39
40 // reverse it
41 - wstr--;
42 - strreverse(str, wstr);
41 + char *begin = str, *end = --wstr, aux;
42 + while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
43 + // wstr--;
44 + // strreverse(str, wstr);
45
46 // remove trailing zeros
47 int decimal = 5;