eliminated a string copy when generating json data
Costa Tsaousis (ktsaou) committed
Apr 16, 2014 at 23:02 UTC
30b9908bc7a6069137b942e44e3b05d724f2f1fd
1 file changed
+39
-72
netdata.c
+39
-72
@@ -1047,58 +1047,6 @@ long double rrd_stats_dimension_get(RRD_DIMENSION *rd, size_t position)
1047
return(0);
1048
}
1049
1050
-
1051
-struct web_line {
1052
- char *buffer;
1053
- int len;
1054
- int size;
1055
-};
1056
-
1057
-struct web_line *web_line_create(size_t size)
1058
-{
1059
- struct web_line *l;
1060
- l = calloc(1, sizeof(struct web_line));
1061
- if(!l) fatal("Cannot allocate %d bytes.", sizeof(struct web_line));
1062
-
1063
- l->buffer = calloc(size + 1, sizeof(char));
1064
- if(!l->buffer) fatal("Cannot allocate %d bytes.", (size + 1) * sizeof(char));
1065
-
1066
- l->len = 0;
1067
- l->size = size;
1068
-
1069
- return (l);
1070
-}
1071
-
1072
-int web_line_printf(struct web_line *wl, const char *fmt, ... )
1073
-{
1074
- if(wl->len < wl->size) {
1075
- va_list args;
1076
- va_start( args, fmt );
1077
- wl->len += vsnprintf(&wl->buffer[wl->len], wl->size - wl->len, fmt, args);
1078
- va_end( args );
1079
- wl->buffer[wl->len] = '\0';
1080
- }
1081
-
1082
- return (wl->len);
1083
-}
1084
-
1085
-char *web_line(struct web_line *wl)
1086
-{
1087
- return wl->buffer;
1088
-}
1089
-
1090
-void web_line_reset(struct web_line *wl)
1091
-{
1092
- wl->len = 0;
1093
- wl->buffer[wl->len] = 0;
1094
-}
1095
-
1096
-void web_line_free(struct web_line *wl)
1097
-{
1098
- free(wl->buffer);
1099
- free(wl);
1100
-}
1101
-
1050
unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, size_t entries_to_show, size_t group_count, int group_method)
1051
{
1052
pthread_mutex_lock(&st->mutex);
@@ -1152,10 +1100,12 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1100
return 0;
1101
}
1102
1155
- int line_size = 4096 + (dimensions * 200);
1156
- struct web_line *wl = web_line_create(line_size);
1103
int annotation_count = 0;
1104
1105
+ // temp for the printable values
1106
+ long double print_values[dimensions];
1107
+ int print_enabled[dimensions];
1108
+
1109
// temporary storage to keep track of group values and counts
1110
long double group_values[dimensions];
1111
int group_counts[dimensions];
@@ -1167,9 +1117,14 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1117
wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1118
wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1119
1170
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
1171
- if(!rd->hidden)
1120
+ for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1121
+ if(rd->hidden)
1122
+ print_enabled[c] = 0;
1123
+ else {
1124
+ print_enabled[c] = 1;
1125
wb->bytes += sprintf(&wb->buffer[wb->bytes], ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1126
+ }
1127
+ }
1128
1129
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ],\n %srows%s:\n [\n", kq, kq);
1130
@@ -1188,6 +1143,17 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1143
t++;
1144
if(t >= st->entries) t = 0;
1145
1146
+ // the minimum line length we expect
1147
+ int line_size = 4096 + (dimensions * 200);
1148
+
1149
+ char overflow_annotation[201];
1150
+ int overflow_annotation_len = snprintf(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
1151
+ overflow_annotation[200] = '\0';
1152
+
1153
+ char normal_annotation[201];
1154
+ int normal_annotation_len = snprintf(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1155
+ normal_annotation[200] = '\0';
1156
+
1157
// the loop in dimension data
1158
count -= 2;
1159
int annotate_reset = 0;
@@ -1224,7 +1190,6 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1190
wb->bytes += sprintf(&wb->buffer[wb->bytes], "%s {%sc%s:[{%sv%s:%s%s%s}", printed?"]},\n":"", kq, kq, kq, kq, sq, dtm, sq);
1191
1192
print_this = 1;
1227
- web_line_reset(wl);
1193
}
1194
1195
// if we need a PCENT_OVER_TOTAL, calculate the totals for the current and the last
@@ -1244,22 +1209,21 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1209
1210
switch(rd->type) {
1211
case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1247
- value = (long double)100 * (value - oldvalue) / (total - oldtotal);
1212
+ value = 100.0 * (value - oldvalue) / (total - oldtotal);
1213
break;
1214
1215
case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
1251
- value = (long double)100 * value / total;
1216
+ value = 100.0 * value / total;
1217
break;
1218
1219
case RRD_DIMENSION_INCREMENTAL:
1220
if(oldvalue > value) {
1256
- // reset
1221
annotate_reset = 1;
1222
value = 0;
1223
}
1224
else value -= oldvalue;
1225
1262
- value = value * (long double)1000000L / (long double)usec;
1226
+ value = value * 1000000.0 / (long double)usec;
1227
break;
1228
1229
default:
@@ -1281,30 +1245,35 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1245
default:
1246
case GROUP_AVERAGE:
1247
group_values[c] += value;
1284
- if(((count - pad) % group_count) == 0) group_values[c] /= (long double)group_counts[c];
1248
+ if(print_this) group_values[c] /= group_counts[c];
1249
break;
1250
}
1251
1252
if(print_this) {
1289
- if(!rd->hidden)
1290
- web_line_printf(wl, ",{%sv%s:%0.1Lf}", kq, kq, group_values[c]);
1291
-
1292
- group_values[c] = group_counts[c] = 0;
1253
+ print_values[c] = group_values[c];
1254
+ group_values[c] = 0;
1255
+ group_counts[c] = 0;
1256
}
1257
}
1258
1259
if(print_this) {
1260
if(annotate_reset) {
1261
annotation_count++;
1299
- wb->bytes += sprintf(&wb->buffer[wb->bytes], ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
1262
+ strcpy(&wb->buffer[wb->bytes], overflow_annotation);
1263
+ wb->bytes += overflow_annotation_len;
1264
annotate_reset = 0;
1265
}
1266
else {
1303
- wb->bytes += sprintf(&wb->buffer[wb->bytes], ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1267
+ strcpy(&wb->buffer[wb->bytes], normal_annotation);
1268
+ wb->bytes += normal_annotation_len;
1269
+ }
1270
+
1271
+ if(print_enabled[c]) {
1272
+ for(c = 0 ; c < dimensions ; c++) {
1273
+ wb->bytes += sprintf(&wb->buffer[wb->bytes], ",{%sv%s:%0.1Lf}", kq, kq, print_values[c]);
1274
+ }
1275
}
1276
1306
- strcpy(&wb->buffer[wb->bytes], wl->buffer);
1307
- wb->bytes += wl->len;
1277
printed++;
1278
}
1279
}
@@ -1312,8 +1281,6 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1281
if(printed) wb->bytes += sprintf(&wb->buffer[wb->bytes], "]}");
1282
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ]\n}\n");
1283
1315
- web_line_free(wl);
1316
-
1284
pthread_mutex_unlock(&st->mutex);
1285
return last_timestamp;
1286
}