@cryptotaxi247 / netdata-1 / commits / 30b9908bc

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 }