@cryptotaxi247 / netdata-1 / commits / de9cfcd69

removed all printf from the json data generation; now it is twice as fast

Costa Tsaousis (ktsaou) committed May 1, 2014 at 04:27 UTC de9cfcd69c37adbea1a55540ec1799bd6d76b35b
1 file changed +154 -23
netdata.c
+154 -23
@@ -679,15 +679,46 @@ const char *chart_type_name(int chart_type)
679 }
680
681
682 +// ----------------------------------------------------------------------------
683 +// FAST NUMBER TO STRING
684 +
685 +static void strreverse(char* begin, char* end)
686 +{
687 + char aux;
688 + while (end > begin)
689 + aux = *end, *end-- = *begin, *begin++ = aux;
690 +}
691 +
692 +// fast number to string
693 +// returns length of string
694 +int itoa(int32_t value, char *str)
695 +{
696 + char *wstr = str;
697 +
698 + // Take care of sign
699 + unsigned int uvalue = (value < 0) ? -value : value;
700 +
701 + // Conversion. Number is reversed.
702 + do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
703 + if (value < 0) *wstr++ = '-';
704 + *wstr='\0';
705 +
706 + // Reverse string
707 + strreverse(str,wstr-1);
708 +
709 + return(wstr - str);
710 +}
711 +
712 +
713 // ----------------------------------------------------------------------------
714 // RRD STATS
715
716 #define RRD_STATS_NAME_MAX 1024
717
687 -//typedef long double calculated_number;
688 -//#define CALCULATED_NUMBER_FORMAT "%0.1Lf"
689 -typedef long long calculated_number;
690 -#define CALCULATED_NUMBER_FORMAT "%lld"
718 +typedef long double calculated_number;
719 +#define CALCULATED_NUMBER_FORMAT "%0.1Lf"
720 +//typedef long long calculated_number;
721 +//#define CALCULATED_NUMBER_FORMAT "%lld"
722
723 typedef long long collected_number;
724 #define COLLECTED_NUMBER_FORMAT "%lld"
@@ -696,6 +727,7 @@ typedef long long total_number;
727 #define TOTAL_NUMBER_FORMAT "%lld"
728
729 typedef int32_t storage_number;
730 +typedef uint32_t ustorage_number;
731 #define STORAGE_NUMBER_FORMAT "%d"
732
733
@@ -1243,6 +1275,105 @@ struct web_buffer {
1275
1276 #define web_buffer_printf(wb, args...) wb->bytes += snprintf(&wb->buffer[wb->bytes], (wb->size - wb->bytes), ##args)
1277
1278 +void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
1279 +{
1280 + char *buffer = wb->buffer;
1281 + size_t bytes = wb->bytes, size = wb->size, i = 0;
1282 +
1283 + while(txt[i] && bytes < size)
1284 + buffer[bytes++] = txt[i++];
1285 +
1286 + wb->bytes = bytes;
1287 +}
1288 +
1289 +void web_buffer_rrd_value(struct web_buffer *wb, storage_number value)
1290 +{
1291 + if(wb->size - wb->bytes < 11) return;
1292 +
1293 + char *str = &wb->buffer[wb->bytes];
1294 + char *wstr = str;
1295 +
1296 + // make sure it is unsigned
1297 + ustorage_number uvalue = (value < 0) ? -value : value;
1298 +
1299 + // print each digit
1300 + do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
1301 +
1302 + // if it is just one byte, add a zero
1303 + if((wstr - str) == 1) *wstr++ = '0';
1304 +
1305 + // put the sign back
1306 + if (value < 0) *wstr++ = '-';
1307 +
1308 + // reverse it
1309 + strreverse(str, wstr-1);
1310 +
1311 + // move the last digit
1312 + wstr--;
1313 + wstr[1] = wstr[0];
1314 +
1315 + // put the dot
1316 + wstr[0] = '.';
1317 +
1318 + // terminate it
1319 + wstr += 2;
1320 + *wstr='\0';
1321 +
1322 + // update the buffer length
1323 + wb->bytes += (wstr - str);
1324 +}
1325 +
1326 +// generate a javascript date, the fastest possible way...
1327 +void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds, int milliseconds)
1328 +{
1329 + // 10 20 30 = 35
1330 + // 01234567890123456789012345678901234
1331 + // Date(2014, 04, 01, 03, 28, 20, 065)
1332 +
1333 + if(wb->size - wb->bytes < 36) return;
1334 +
1335 + char *b = &wb->buffer[wb->bytes];
1336 +
1337 + b[0]='D';
1338 + b[1]='a';
1339 + b[2]='t';
1340 + b[3]='e';
1341 + b[4]='(';
1342 + b[5]= 48 + year / 1000; year -= (year / 1000) * 1000;
1343 + b[6]= 48 + year / 100; year -= (year / 100) * 100;
1344 + b[7]= 48 + year / 10;
1345 + b[8]= 48 + year % 10;
1346 + b[9]=',';
1347 + b[10]=' ';
1348 + b[11]= 48 + month / 10;
1349 + b[12]= 48 + month % 10;
1350 + b[13]=',';
1351 + b[14]=' ';
1352 + b[15]= 48 + day / 10;
1353 + b[16]= 48 + day % 10;
1354 + b[17]=',';
1355 + b[18]=' ';
1356 + b[19]= 48 + hours / 10;
1357 + b[20]= 48 + hours % 10;
1358 + b[21]=',';
1359 + b[22]=' ';
1360 + b[23]= 48 + minutes / 10;
1361 + b[24]= 48 + minutes % 10;
1362 + b[25]=',';
1363 + b[26]=' ';
1364 + b[27]= 48 + seconds / 10;
1365 + b[28]= 48 + seconds % 10;
1366 + b[29]=',';
1367 + b[30]=' ';
1368 + b[31]= 48 + milliseconds / 100; milliseconds -= (milliseconds / 100) * 100;
1369 + b[32]= 48 + milliseconds / 10;
1370 + b[33]= 48 + milliseconds % 10;
1371 + b[34]=')';
1372 + b[35]='\0';
1373 +
1374 + wb->bytes += 35;
1375 +}
1376 +
1377 struct web_buffer *web_buffer_create(size_t size)
1378 {
1379 struct web_buffer *b;
@@ -1672,13 +1803,12 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1803 // the minimum line length we expect
1804 int line_size = 4096 + (dimensions * 200);
1805
1675 - char overflow_annotation[201];
1676 - 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);
1677 - overflow_annotation[200] = '\0';
1678 -
1679 - char normal_annotation[201];
1680 - int normal_annotation_len = snprintf(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1681 - normal_annotation[200] = '\0';
1806 + char overflow_annotation[201]; 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);
1807 + char normal_annotation[201]; snprintf(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1808 + char pre_date[51]; snprintf(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
1809 + char post_date[21]; snprintf(post_date, 20, "%s}", sq);
1810 + char pre_value[21]; snprintf(pre_value, 20, ",{%sv%s:", kq, kq);
1811 + char post_value[21]; snprintf(post_value, 20, "}");
1812
1813 // to allow grouping on the same values, we need a pad
1814 long pad = before % group;
@@ -1734,10 +1864,11 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1864 if(!tm) { error("localtime() failed."); continue; }
1865 if(now.tv_sec > last_timestamp) last_timestamp = now.tv_sec;
1866
1737 - web_buffer_printf(wb, "%s {%sc%s:[{%sv%s:%sDate(%d, %d, %d, %d, %d, %d, %d)%s}", printed?"]},\n":"",
1738 - kq, kq, kq, kq, sq,
1739 - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(now.tv_usec / 1000),
1740 - sq);
1867 + if(printed) web_buffer_strcpy(wb, "]},\n");
1868 + web_buffer_strcpy(wb, pre_date);
1869 + web_buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(now.tv_usec / 1000));
1870 + // web_buffer_printf(wb, "%d, %d, %d, %d, %d, %d, %d", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(now.tv_usec / 1000));
1871 + web_buffer_strcpy(wb, post_date);
1872
1873 print_this = 1;
1874 }
@@ -1768,19 +1899,19 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1899
1900 if(annotate_reset) {
1901 annotation_count++;
1771 - strcpy(&wb->buffer[wb->bytes], overflow_annotation);
1772 - wb->bytes += overflow_annotation_len;
1902 + web_buffer_strcpy(wb, overflow_annotation);
1903 annotate_reset = 0;
1904 }
1775 - else {
1776 - strcpy(&wb->buffer[wb->bytes], normal_annotation);
1777 - wb->bytes += normal_annotation_len;
1778 - }
1905 + else
1906 + web_buffer_strcpy(wb, normal_annotation);
1907
1908 for(c = 0 ; c < dimensions ; c++) {
1909 if(!print_hidden[c]) {
1782 - long double x = (long double)print_values[c] / 10.0;
1783 - web_buffer_printf(wb, ",{%sv%s:%0.1Lf}", kq, kq, x);
1910 + web_buffer_strcpy(wb, pre_value);
1911 + web_buffer_rrd_value(wb, print_values[c]);
1912 + // long double x = (long double)print_values[c] / 10.0;
1913 + // web_buffer_printf(wb, "%0.1Lf", x);
1914 + web_buffer_strcpy(wb, post_value);
1915 }
1916 }
1917