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 */