summaryrefslogtreecommitdiffstats
path: root/libnetdata/buffer/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/buffer/buffer.c')
-rw-r--r--libnetdata/buffer/buffer.c67
1 files changed, 48 insertions, 19 deletions
diff --git a/libnetdata/buffer/buffer.c b/libnetdata/buffer/buffer.c
index 8ea90985..88041755 100644
--- a/libnetdata/buffer/buffer.c
+++ b/libnetdata/buffer/buffer.c
@@ -136,6 +136,24 @@ void buffer_print_llu(BUFFER *wb, unsigned long long uvalue)
wb->len += wstr - str;
}
+void buffer_fast_strcat(BUFFER *wb, const char *txt, size_t len) {
+ if(unlikely(!txt || !*txt)) return;
+
+ buffer_need_bytes(wb, len + 1);
+
+ char *s = &wb->buffer[wb->len];
+ const char *end = &txt[len + 1];
+
+ while(txt != end)
+ *s++ = *txt++;
+
+ wb->len += len;
+
+ // keep it NULL terminating
+ // not counting it at wb->len
+ wb->buffer[wb->len] = '\0';
+}
+
void buffer_strcat(BUFFER *wb, const char *txt)
{
// buffer_sprintf(wb, "%s", txt);
@@ -159,8 +177,7 @@ void buffer_strcat(BUFFER *wb, const char *txt)
if(*txt) {
debug(D_WEB_BUFFER, "strcat(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
len = strlen(txt);
- buffer_increase(wb, len);
- buffer_strcat(wb, txt);
+ buffer_fast_strcat(wb, txt, len);
}
else {
// terminate the string
@@ -236,15 +253,23 @@ void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args)
{
if(unlikely(!fmt || !*fmt)) return;
- buffer_need_bytes(wb, 2);
+ size_t wrote = 0, need = 2, space_remaining = 0;
- size_t len = wb->size - wb->len - 1;
+ do {
+ need += space_remaining * 2;
- wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
+ debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu, by %zu bytes (wrote = %zu)\n", wb->len, wb->size, need, wrote);
+ buffer_need_bytes(wb, need);
- buffer_overflow_check(wb);
+ space_remaining = wb->size - wb->len - 1;
- // the buffer is \0 terminated by vsnprintfz
+ wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], space_remaining, fmt, args);
+
+ } while(wrote >= space_remaining);
+
+ wb->len += wrote;
+
+ // the buffer is \0 terminated by vsnprintf
}
void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
@@ -252,22 +277,21 @@ void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
if(unlikely(!fmt || !*fmt)) return;
va_list args;
- size_t wrote = 0, need = 2, multiplier = 0, len;
+ size_t wrote = 0, need = 2, space_remaining = 0;
do {
- need += wrote + multiplier * WEB_DATA_LENGTH_INCREASE_STEP;
- multiplier++;
+ need += space_remaining * 2;
debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu, by %zu bytes (wrote = %zu)\n", wb->len, wb->size, need, wrote);
buffer_need_bytes(wb, need);
- len = wb->size - wb->len - 1;
+ space_remaining = wb->size - wb->len - 1;
va_start(args, fmt);
- wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
+ wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], space_remaining, fmt, args);
va_end(args);
- } while(wrote >= len);
+ } while(wrote >= space_remaining);
wb->len += wrote;
@@ -420,16 +444,21 @@ void buffer_increase(BUFFER *b, size_t free_size_required) {
buffer_overflow_check(b);
size_t left = b->size - b->len;
-
if(left >= free_size_required) return;
- size_t increase = free_size_required - left;
- if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
+ size_t wanted = free_size_required - left;
+ size_t minimum = WEB_DATA_LENGTH_INCREASE_STEP;
+ if(minimum > wanted) wanted = minimum;
+
+ size_t optimal = b->size;
+ if(b->size > 5*1024*1024) optimal = b->size / 2;
+
+ if(optimal > wanted) wanted = optimal;
- debug(D_WEB_BUFFER, "Increasing data buffer from size %zu to %zu.", b->size, b->size + increase);
+ debug(D_WEB_BUFFER, "Increasing data buffer from size %zu to %zu.", b->size, b->size + wanted);
- b->buffer = reallocz(b->buffer, b->size + increase + sizeof(BUFFER_OVERFLOW_EOF) + 2);
- b->size += increase;
+ b->buffer = reallocz(b->buffer, b->size + wanted + sizeof(BUFFER_OVERFLOW_EOF) + 2);
+ b->size += wanted;
buffer_overflow_init(b);
buffer_overflow_check(b);