@cryptotaxi247 / netdata-1 / commits / 36199f449

incremental overflows should not show zeros values (#4538)

* incremental overflows do not show zeros; fixes #4533 * use the max per metric per session for detecting counter size

Costa Tsaousis committed Nov 4, 2018 at 21:53 UTC 36199f449852f8077ea915a3a14a33fa2aff6d85
6 files changed +272 -83
daemon/unit_test.c
+191 -35
@@ -130,13 +130,17 @@ int check_storage_number(calculated_number n, int debug) {
130 p, pdiff, pcdiff
131 );
132 if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %zu but it has %zu\n", buffer, len, strlen(buffer));
133 - if(dcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss " CALCULATED_NUMBER_FORMAT " %%\n", n, dcdiff);
134 - if(pcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " CALCULATED_NUMBER_FORMAT " has accuracy loss " CALCULATED_NUMBER_FORMAT " %%\n", n, pcdiff);
133 +
134 + if(dcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT)
135 + fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss " CALCULATED_NUMBER_FORMAT " %%\n", n, dcdiff);
136 +
137 + if(pcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT)
138 + fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " CALCULATED_NUMBER_FORMAT " has accuracy loss " CALCULATED_NUMBER_FORMAT " %%\n", n, pcdiff);
139 }
140
141 if(len != strlen(buffer)) return 1;
138 - if(dcdiff > ACCURACY_LOSS) return 3;
139 - if(pcdiff > ACCURACY_LOSS) return 4;
142 + if(dcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT) return 3;
143 + if(pcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT) return 4;
144 return 0;
145 }
146
@@ -159,6 +163,9 @@ void benchmark_storage_number(int loop, int multiplier) {
163 storage_number s;
164 unsigned long long user, system, total, mine, their;
165
166 + calculated_number storage_number_positive_min = unpack_storage_number(STORAGE_NUMBER_POSITIVE_MIN_RAW);
167 + calculated_number storage_number_positive_max = unpack_storage_number(STORAGE_NUMBER_POSITIVE_MAX_RAW);
168 +
169 char buffer[100];
170
171 struct rusage now, last;
@@ -181,11 +188,11 @@ void benchmark_storage_number(int loop, int multiplier) {
188 }
189
190 fprintf(stderr, "\nNETDATA FLOATING POINT\n");
184 - fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", storage_number_min(1));
185 - fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MAX);
186 - fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MIN);
187 - fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", -storage_number_min(1));
188 - fprintf(stderr, "Maximum accuracy loss: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS);
191 + fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_POSITIVE_MIN_RAW));
192 + fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_POSITIVE_MAX_RAW));
193 + fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_NEGATIVE_MIN_RAW));
194 + fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_NEGATIVE_MAX_RAW));
195 + fprintf(stderr, "Maximum accuracy loss accepted: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS_ACCEPTED_PERCENT);
196
197 // ------------------------------------------------------------------------
198
@@ -194,11 +201,11 @@ void benchmark_storage_number(int loop, int multiplier) {
201
202 // do the job
203 for(j = 1; j < 11 ;j++) {
197 - n = STORAGE_NUMBER_POSITIVE_MIN * j;
204 + n = storage_number_positive_min * j;
205
206 for(i = 0; i < loop ;i++) {
207 n *= multiplier;
201 - if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
208 + if(n > storage_number_positive_max) n = storage_number_positive_min;
209
210 print_calculated_number(buffer, n);
211 }
@@ -219,11 +226,11 @@ void benchmark_storage_number(int loop, int multiplier) {
226
227 // do the job
228 for(j = 1; j < 11 ;j++) {
222 - n = STORAGE_NUMBER_POSITIVE_MIN * j;
229 + n = storage_number_positive_min * j;
230
231 for(i = 0; i < loop ;i++) {
232 n *= multiplier;
226 - if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
233 + if(n > storage_number_positive_max) n = storage_number_positive_min;
234 snprintfz(buffer, 100, CALCULATED_NUMBER_FORMAT, n);
235 }
236 }
@@ -250,13 +257,13 @@ void benchmark_storage_number(int loop, int multiplier) {
257
258 // do the job
259 for(j = 1; j < 11 ;j++) {
253 - n = STORAGE_NUMBER_POSITIVE_MIN * j;
260 + n = storage_number_positive_min * j;
261
262 for(i = 0; i < loop ;i++) {
263 n *= multiplier;
257 - if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
264 + if(n > storage_number_positive_max) n = storage_number_positive_min;
265
259 - s = pack_storage_number(n, 1);
266 + s = pack_storage_number(n, SN_EXISTS);
267 d = unpack_storage_number(s);
268 print_calculated_number(buffer, d);
269 }
@@ -282,7 +289,7 @@ void benchmark_storage_number(int loop, int multiplier) {
289 }
290
291 static int check_storage_number_exists() {
285 - uint32_t flags = SN_EXISTS;
292 + uint32_t flags;
293
294
295 for(flags = 0; flags < 7 ; flags++) {
@@ -309,10 +316,12 @@ static int check_storage_number_exists() {
316 return 0;
317 }
318
312 -int unit_test_storage()
313 -{
319 +int unit_test_storage() {
320 if(check_storage_number_exists()) return 0;
321
322 + calculated_number storage_number_positive_min = unpack_storage_number(STORAGE_NUMBER_POSITIVE_MIN_RAW);
323 + calculated_number storage_number_negative_max = unpack_storage_number(STORAGE_NUMBER_NEGATIVE_MAX_RAW);
324 +
325 calculated_number c, a = 0;
326 int i, j, g, r = 0;
327
@@ -325,14 +334,15 @@ int unit_test_storage()
334 a += 0.0000001;
335 c = a * g;
336 for(i = 0; i < 21 ;i++, c *= 10) {
328 - if(c > 0 && c < STORAGE_NUMBER_POSITIVE_MIN) continue;
329 - if(c < 0 && c > STORAGE_NUMBER_NEGATIVE_MAX) continue;
337 + if(c > 0 && c < storage_number_positive_min) continue;
338 + if(c < 0 && c > storage_number_negative_max) continue;
339
340 if(check_storage_number(c, 1)) return 1;
341 }
342 }
343 }
344
345 + // if(check_storage_number(858993459.1234567, 1)) return 1;
346 benchmark_storage_number(1000000, 2);
347 return r;
348 }
@@ -575,28 +585,36 @@ struct test test4 = {
585 };
586
587 // --------------------------------------------------------------------------------------------------------------------
578 -// test5
588 +// test5 - 32 bit overflows
589
590 struct feed_values test5_feed[] = {
581 - { 500000, 1000 },
582 - { 1000000, 2000 },
583 - { 1000000, 2000 },
584 - { 1000000, 2000 },
585 - { 1000000, 3000 },
586 - { 1000000, 2000 },
587 - { 1000000, 2000 },
588 - { 1000000, 2000 },
589 - { 1000000, 2000 },
590 - { 1000000, 2000 },
591 + { 0, 0x00000000FFFFFFFFULL / 3 * 0 },
592 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 1 },
593 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 2 },
594 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 0 },
595 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 1 },
596 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 2 },
597 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 0 },
598 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 1 },
599 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 2 },
600 + { 1000000, 0x00000000FFFFFFFFULL / 3 * 0 },
601 };
602
603 calculated_number test5_results[] = {
594 - 1000, 500, 0, 500, 500, 0, 0, 0, 0
604 + 0x00000000FFFFFFFFULL / 3,
605 + 0x00000000FFFFFFFFULL / 3,
606 + 0x00000000FFFFFFFFULL / 3,
607 + 0x00000000FFFFFFFFULL / 3,
608 + 0x00000000FFFFFFFFULL / 3,
609 + 0x00000000FFFFFFFFULL / 3,
610 + 0x00000000FFFFFFFFULL / 3,
611 + 0x00000000FFFFFFFFULL / 3,
612 + 0x00000000FFFFFFFFULL / 3,
613 };
614
615 struct test test5 = {
616 "test5", // name
599 - "test incremental values ups and downs",
617 + "test 32-bit incremental values overflow",
618 1, // update_every
619 1, // multiplier
620 1, // divisor
@@ -609,6 +627,135 @@ struct test test5 = {
627 NULL // results2
628 };
629
630 +// --------------------------------------------------------------------------------------------------------------------
631 +// test5b - 16 bit overflows
632 +
633 +struct feed_values test5b_feed[] = {
634 + { 0, 0x000000000000FFFFULL / 3 * 0 },
635 + { 1000000, 0x000000000000FFFFULL / 3 * 1 },
636 + { 1000000, 0x000000000000FFFFULL / 3 * 2 },
637 + { 1000000, 0x000000000000FFFFULL / 3 * 0 },
638 + { 1000000, 0x000000000000FFFFULL / 3 * 1 },
639 + { 1000000, 0x000000000000FFFFULL / 3 * 2 },
640 + { 1000000, 0x000000000000FFFFULL / 3 * 0 },
641 + { 1000000, 0x000000000000FFFFULL / 3 * 1 },
642 + { 1000000, 0x000000000000FFFFULL / 3 * 2 },
643 + { 1000000, 0x000000000000FFFFULL / 3 * 0 },
644 +};
645 +
646 +calculated_number test5b_results[] = {
647 + 0x000000000000FFFFULL / 3,
648 + 0x000000000000FFFFULL / 3,
649 + 0x000000000000FFFFULL / 3,
650 + 0x000000000000FFFFULL / 3,
651 + 0x000000000000FFFFULL / 3,
652 + 0x000000000000FFFFULL / 3,
653 + 0x000000000000FFFFULL / 3,
654 + 0x000000000000FFFFULL / 3,
655 + 0x000000000000FFFFULL / 3,
656 +};
657 +
658 +struct test test5b = {
659 + "test5b", // name
660 + "test 16-bit incremental values overflow",
661 + 1, // update_every
662 + 1, // multiplier
663 + 1, // divisor
664 + RRD_ALGORITHM_INCREMENTAL, // algorithm
665 + 10, // feed entries
666 + 9, // result entries
667 + test5b_feed, // feed
668 + test5b_results, // results
669 + NULL, // feed2
670 + NULL // results2
671 +};
672 +
673 +// --------------------------------------------------------------------------------------------------------------------
674 +// test5c - 8 bit overflows
675 +
676 +struct feed_values test5c_feed[] = {
677 + { 0, 0x00000000000000FFULL / 3 * 0 },
678 + { 1000000, 0x00000000000000FFULL / 3 * 1 },
679 + { 1000000, 0x00000000000000FFULL / 3 * 2 },
680 + { 1000000, 0x00000000000000FFULL / 3 * 0 },
681 + { 1000000, 0x00000000000000FFULL / 3 * 1 },
682 + { 1000000, 0x00000000000000FFULL / 3 * 2 },
683 + { 1000000, 0x00000000000000FFULL / 3 * 0 },
684 + { 1000000, 0x00000000000000FFULL / 3 * 1 },
685 + { 1000000, 0x00000000000000FFULL / 3 * 2 },
686 + { 1000000, 0x00000000000000FFULL / 3 * 0 },
687 +};
688 +
689 +calculated_number test5c_results[] = {
690 + 0x00000000000000FFULL / 3,
691 + 0x00000000000000FFULL / 3,
692 + 0x00000000000000FFULL / 3,
693 + 0x00000000000000FFULL / 3,
694 + 0x00000000000000FFULL / 3,
695 + 0x00000000000000FFULL / 3,
696 + 0x00000000000000FFULL / 3,
697 + 0x00000000000000FFULL / 3,
698 + 0x00000000000000FFULL / 3,
699 +};
700 +
701 +struct test test5c = {
702 + "test5c", // name
703 + "test 8-bit incremental values overflow",
704 + 1, // update_every
705 + 1, // multiplier
706 + 1, // divisor
707 + RRD_ALGORITHM_INCREMENTAL, // algorithm
708 + 10, // feed entries
709 + 9, // result entries
710 + test5c_feed, // feed
711 + test5c_results, // results
712 + NULL, // feed2
713 + NULL // results2
714 +};
715 +
716 +// --------------------------------------------------------------------------------------------------------------------
717 +// test5d - 64 bit overflows
718 +
719 +struct feed_values test5d_feed[] = {
720 + { 0, 0xFFFFFFFFFFFFFFFFULL / 3 * 0 },
721 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 1 },
722 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 2 },
723 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 0 },
724 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 1 },
725 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 2 },
726 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 0 },
727 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 1 },
728 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 2 },
729 + { 1000000, 0xFFFFFFFFFFFFFFFFULL / 3 * 0 },
730 +};
731 +
732 +calculated_number test5d_results[] = {
733 + 0xFFFFFFFFFFFFFFFFULL / 3,
734 + 0xFFFFFFFFFFFFFFFFULL / 3,
735 + 0xFFFFFFFFFFFFFFFFULL / 3,
736 + 0xFFFFFFFFFFFFFFFFULL / 3,
737 + 0xFFFFFFFFFFFFFFFFULL / 3,
738 + 0xFFFFFFFFFFFFFFFFULL / 3,
739 + 0xFFFFFFFFFFFFFFFFULL / 3,
740 + 0xFFFFFFFFFFFFFFFFULL / 3,
741 + 0xFFFFFFFFFFFFFFFFULL / 3,
742 +};
743 +
744 +struct test test5d = {
745 + "test5d", // name
746 + "test 64-bit incremental values overflow",
747 + 1, // update_every
748 + 1, // multiplier
749 + 1, // divisor
750 + RRD_ALGORITHM_INCREMENTAL, // algorithm
751 + 10, // feed entries
752 + 9, // result entries
753 + test5d_feed, // feed
754 + test5d_results, // results
755 + NULL, // feed2
756 + NULL // results2
757 +};
758 +
759 // --------------------------------------------------------------------------------------------------------------------
760 // test6
761
@@ -1131,7 +1278,7 @@ int run_test(struct test *test)
1278 unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries;
1279 for(c = 0 ; c < max ; c++) {
1280 calculated_number v = unpack_storage_number(rd->values[c]);
1134 - calculated_number n = test->results[c];
1281 + calculated_number n = unpack_storage_number(pack_storage_number(test->results[c], SN_EXISTS));
1282 int same = (calculated_number_round(v * 10000000.0) == calculated_number_round(n * 10000000.0))?1:0;
1283 fprintf(stderr, " %s/%s: checking position %lu (at %lu secs), expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n",
1284 test->name, rd->name, c+1,
@@ -1267,6 +1414,15 @@ int run_all_mockup_tests(void)
1414 if(run_test(&test5))
1415 return 1;
1416
1417 + if(run_test(&test5b))
1418 + return 1;
1419 +
1420 + if(run_test(&test5c))
1421 + return 1;
1422 +
1423 + if(run_test(&test5d))
1424 + return 1;
1425 +
1426 if(run_test(&test6))
1427 return 1;
1428
database/rrd.h
+3 -1
@@ -176,7 +176,9 @@ struct rrddim {
176 char *cache_filename; // the filename we load/save from/to this set
177
178 size_t collections_counter; // the number of times we added values to this rrdim
179 - size_t unused[10];
179 + size_t unused[9];
180 +
181 + collected_number collected_value_max; // the absolute maximum of the collected value
182
183 unsigned int updated:1; // 1 when the dimension has been updated since the last processing
184 unsigned int exposed:1; // 1 when set what have sent this dimension to the central netdata
database/rrddim.c
+4
@@ -239,6 +239,7 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte
239 rd->last_calculated_value = 0;
240 rd->collected_value = 0;
241 rd->last_collected_value = 0;
242 + rd->collected_value_max = 0;
243 rd->collected_volume = 0;
244 rd->stored_volume = 0;
245 rd->last_stored_value = 0;
@@ -380,6 +381,9 @@ inline collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_
381
382 rd->collections_counter++;
383
384 + collected_number v = (value >= 0) ? value : -value;
385 + if(unlikely(v > rd->collected_value_max)) rd->collected_value_max = v;
386 +
387 // fprintf(stderr, "%s.%s %llu " COLLECTED_NUMBER_FORMAT " dt %0.6f" " rate " CALCULATED_NUMBER_FORMAT "\n", st->name, rd->name, st->usec_since_last_update, value, (float)((double)st->usec_since_last_update / (double)1000000), (calculated_number)((value - rd->last_collected_value) * (calculated_number)rd->multiplier / (calculated_number)rd->divisor * 1000000.0 / (calculated_number)st->usec_since_last_update));
388
389 return rd->last_collected_value;
database/rrdset.c
+24 -8
@@ -1080,7 +1080,7 @@ static inline size_t rrdset_done_interpolate(
1080 , get_storage_number_flags(rd->values[current_entry])
1081 , t1
1082 , accuracy
1083 - , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1083 + , (accuracy > ACCURACY_LOSS_ACCEPTED_PERCENT) ? " **TOO BIG** " : ""
1084 );
1085
1086 rd->collected_volume += t1;
@@ -1093,7 +1093,7 @@ static inline size_t rrdset_done_interpolate(
1093 , rd->stored_volume
1094 , rd->collected_volume
1095 , accuracy
1096 - , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1096 + , (accuracy > ACCURACY_LOSS_ACCEPTED_PERCENT) ? " **TOO BIG** " : ""
1097 );
1098 }
1099 #endif
@@ -1381,13 +1381,29 @@ void rrdset_done(RRDSET *st) {
1381 if(!(rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)))
1382 storage_flags = SN_EXISTS_RESET;
1383
1384 - rd->last_collected_value = rd->collected_value;
1385 - }
1384 + uint64_t last = (uint64_t)rd->last_collected_value;
1385 + uint64_t new = (uint64_t)rd->collected_value;
1386 + uint64_t max = (uint64_t)rd->collected_value_max;
1387 + uint64_t cap = 0;
1388 +
1389 + if(max > 0x00000000FFFFFFFFULL) cap = 0xFFFFFFFFFFFFFFFFULL;
1390 + else if(max > 0x000000000000FFFFULL) cap = 0x00000000FFFFFFFFULL;
1391 + else if(max > 0x00000000000000FFULL) cap = 0x000000000000FFFFULL;
1392 + else cap = 0x00000000000000FFULL;
1393 +
1394 + uint64_t delta = cap - last + new;
1395
1387 - rd->calculated_value +=
1388 - (calculated_number)(rd->collected_value - rd->last_collected_value)
1389 - * (calculated_number)rd->multiplier
1390 - / (calculated_number)rd->divisor;
1396 + rd->calculated_value +=
1397 + (calculated_number) delta
1398 + * (calculated_number) rd->multiplier
1399 + / (calculated_number) rd->divisor;
1400 + }
1401 + else {
1402 + rd->calculated_value +=
1403 + (calculated_number) (rd->collected_value - rd->last_collected_value)
1404 + * (calculated_number) rd->multiplier
1405 + / (calculated_number) rd->divisor;
1406 + }
1407
1408 #ifdef NETDATA_INTERNAL_CHECKS
1409 rrdset_debug(st, "%s: CALC INC PRE "
libnetdata/storage_number/storage_number.c
+37 -22
@@ -2,19 +2,20 @@
2
3 #include "../libnetdata.h"
4
5 -storage_number pack_storage_number(calculated_number value, uint32_t flags)
6 -{
5 +storage_number pack_storage_number(calculated_number value, uint32_t flags) {
6 // bit 32 = sign 0:positive, 1:negative
7 // bit 31 = 0:divide, 1:multiply
8 // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total)
10 - // bit 27, 26, 25 flags
9 + // bit 27 SN_EXISTS_100
10 + // bit 26 SN_EXISTS_RESET
11 + // bit 25 SN_EXISTS
12 // bit 24 to bit 1 = the value
13
14 storage_number r = get_storage_number_flags(flags);
15 if(!value) return r;
16
17 int m = 0;
17 - calculated_number n = value;
18 + calculated_number n = value, factor = 10;
19
20 // if the value is negative
21 // add the sign bit and make it positive
@@ -23,11 +24,16 @@ storage_number pack_storage_number(calculated_number value, uint32_t flags)
24 n = -n;
25 }
26
27 + if(n / 10000000.0 > 0x00ffffff) {
28 + factor = 100;
29 + r |= SN_EXISTS_100;
30 + }
31 +
32 // make its integer part fit in 0x00ffffff
33 // by dividing it by 10 up to 7 times
34 // and increasing the multiplier
35 while(m < 7 && n > (calculated_number)0x00ffffff) {
30 - n /= 10;
36 + n /= factor;
37 m++;
38 }
39
@@ -71,35 +77,44 @@ storage_number pack_storage_number(calculated_number value, uint32_t flags)
77 return r;
78 }
79
74 -calculated_number unpack_storage_number(storage_number value)
75 -{
80 +calculated_number unpack_storage_number(storage_number value) {
81 if(!value) return 0;
82
83 int sign = 0, exp = 0;
84 + int factor = 10;
85
80 - value ^= get_storage_number_flags(value);
81 -
82 - if(value & (1 << 31)) {
86 + // bit 32 = 0:positive, 1:negative
87 + if(unlikely(value & (1 << 31)))
88 sign = 1;
84 - value ^= 1 << 31;
85 - }
89
87 - if(value & (1 << 30)) {
90 + // bit 31 = 0:divide, 1:multiply
91 + if(unlikely(value & (1 << 30)))
92 exp = 1;
89 - value ^= 1 << 30;
90 - }
93
92 - int mul = value >> 27;
93 - value ^= mul << 27;
94 + // bit 27 SN_EXISTS_100
95 + if(unlikely(value & (1 << 26)))
96 + factor = 100;
97 +
98 + // bit 26 SN_EXISTS_RESET
99 + // bit 25 SN_EXISTS
100 +
101 + // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total)
102 + int mul = (value & ((1<<29)|(1<<28)|(1<<27))) >> 27;
103 +
104 + // bit 24 to bit 1 = the value, so remove all other bits
105 + value ^= value & ((1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<24));
106
107 calculated_number n = value;
108
97 - // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, n);
109 + // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, factor = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, factor, n);
110
99 - while(mul > 0) {
100 - if(exp) n *= 10;
101 - else n /= 10;
102 - mul--;
111 + if(exp) {
112 + for(; mul; mul--)
113 + n *= factor;
114 + }
115 + else {
116 + for( ; mul ; mul--)
117 + n /= 10;
118 }
119
120 if(sign) n = -n;
libnetdata/storage_number/storage_number.h
+13 -17
@@ -23,7 +23,7 @@ typedef double calculated_number;
23 #define LONG_DOUBLE_MODIFIER "f"
24 typedef double LONG_DOUBLE;
25
26 -#else
26 +#else // NETDATA_WITHOUT_LONG_DOUBLE
27
28 typedef long double calculated_number;
29 #define CALCULATED_NUMBER_FORMAT "%0.7Lf"
@@ -33,7 +33,7 @@ typedef long double calculated_number;
33 #define LONG_DOUBLE_MODIFIER "Lf"
34 typedef long double LONG_DOUBLE;
35
36 -#endif
36 +#endif // NETDATA_WITHOUT_LONG_DOUBLE
37
38 //typedef long long calculated_number;
39 //#define CALCULATED_NUMBER_FORMAT "%lld"
@@ -50,6 +50,7 @@ typedef long double collected_number;
50 #define calculated_number_llrint(x) llrintl(x)
51 #define calculated_number_round(x) roundl(x)
52 #define calculated_number_fabs(x) fabsl(x)
53 +#define calculated_number_pow(x, y) powl(x, y)
54 #define calculated_number_epsilon (calculated_number)0.0000001
55
56 #define calculated_number_equal(a, b) (calculated_number_fabs((a) - (b)) < calculated_number_epsilon)
@@ -57,18 +58,12 @@ typedef long double collected_number;
58 typedef uint32_t storage_number;
59 #define STORAGE_NUMBER_FORMAT "%u"
60
60 -#define SN_NOT_EXISTS (0x0 << 24)
61 -#define SN_EXISTS (0x1 << 24)
62 -#define SN_EXISTS_RESET (0x2 << 24)
63 -#define SN_EXISTS_UNDEF1 (0x3 << 24)
64 -#define SN_EXISTS_UNDEF2 (0x4 << 24)
65 -#define SN_EXISTS_UNDEF3 (0x5 << 24)
66 -#define SN_EXISTS_UNDEF4 (0x6 << 24)
67 -
68 -#define SN_FLAGS_MASK (~(0x6 << 24))
61 +#define SN_EXISTS (1 << 24) // the value exists
62 +#define SN_EXISTS_RESET (1 << 25) // the value has been overflown
63 +#define SN_EXISTS_100 (1 << 26) // very large value (multipler is 100 instead of 10)
64
65 // extract the flags
71 -#define get_storage_number_flags(value) ((((storage_number)(value)) & (1 << 24)) | (((storage_number)(value)) & (2 << 24)) | (((storage_number)(value)) & (4 << 24)))
66 +#define get_storage_number_flags(value) ((((storage_number)(value)) & (1 << 24)) | (((storage_number)(value)) & (1 << 25)) | (((storage_number)(value)) & (1 << 26)))
67 #define SN_EMPTY_SLOT 0x00000000
68
69 // checks
@@ -80,13 +75,14 @@ calculated_number unpack_storage_number(storage_number value);
75
76 int print_calculated_number(char *str, calculated_number value);
77
83 -#define STORAGE_NUMBER_POSITIVE_MAX (167772150000000.0)
84 -#define STORAGE_NUMBER_POSITIVE_MIN (0.0000001)
85 -#define STORAGE_NUMBER_NEGATIVE_MAX (-0.0000001)
86 -#define STORAGE_NUMBER_NEGATIVE_MIN (-167772150000000.0)
78 +// sign div/mul <--- multiplier / divider ---> 10/100 RESET EXISTS VALUE
79 +#define STORAGE_NUMBER_POSITIVE_MAX_RAW (storage_number)( (0 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff )
80 +#define STORAGE_NUMBER_POSITIVE_MIN_RAW (storage_number)( (0 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 )
81 +#define STORAGE_NUMBER_NEGATIVE_MAX_RAW (storage_number)( (1 << 31) | (0 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (0 << 26) | (0 << 25) | (1 << 24) | 0x00000001 )
82 +#define STORAGE_NUMBER_NEGATIVE_MIN_RAW (storage_number)( (1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1<<27) | (1 << 26) | (0 << 25) | (1 << 24) | 0x00ffffff )
83
84 // accepted accuracy loss
89 -#define ACCURACY_LOSS 0.0001
85 +#define ACCURACY_LOSS_ACCEPTED_PERCENT 0.0001
86 #define accuracy_loss(t1, t2) (((t1) == (t2) || (t1) == 0.0 || (t2) == 0.0) ? 0.0 : (100.0 - (((t1) > (t2)) ? ((t2) * 100.0 / (t1) ) : ((t1) * 100.0 / (t2)))))
87
88 #endif /* NETDATA_STORAGE_NUMBER_H */