diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2016-01-31 20:07:20 +0100 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2016-01-31 21:43:23 +0100 |
commit | a850ee45f189dc4afd935f967ee7e5fa4168a2d9 (patch) | |
tree | caf7e94445c37d4e638bbb8c2c14766e7597ca37 | |
parent | 10a264ec3d189ba0fc00e4c6f7b0e7e4a8043aff (diff) | |
download | xK-a850ee45f189dc4afd935f967ee7e5fa4168a2d9.tar.gz xK-a850ee45f189dc4afd935f967ee7e5fa4168a2d9.tar.xz xK-a850ee45f189dc4afd935f967ee7e5fa4168a2d9.zip |
degesch: optimize buffer memory usage
We have approximately 5 formatter_items per buffer_line. Let's assume
we're on a 64-bit machine. Then there were (5 * 2) + 3 useless pointers
(104 bytes) as well as 5 * (4 + 4) = 40 bytes of wasted space because
of needless padding. That's 144 bytes already. Compared to that, this
change adds 16 bytes of overhead for an array sentinel, i.e. 128B less.
With a limit of 1000 lines per buffer, we've saved ~128kB per buffer
on completely useless data, and code complexity stays roughly the same.
All in all, memory usage for buffers should be about 50% lower.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | degesch.c | 74 |
2 files changed, 41 insertions, 35 deletions
@@ -12,6 +12,8 @@ * degesch: backlog limit was made configurable + * degesch: optimize buffer memory usage + * kike: add support for IRCv3.2 server-time * Remote addresses are now resolved asynchronously @@ -968,6 +968,7 @@ REF_COUNTABLE_METHODS (channel) enum formatter_item_type { + FORMATTER_ITEM_END, ///< Sentinel value for arrays FORMATTER_ITEM_TEXT, ///< Text FORMATTER_ITEM_ATTR, ///< Formatting attributes FORMATTER_ITEM_FG_COLOR, ///< Foreground color @@ -978,26 +979,16 @@ enum formatter_item_type struct formatter_item { - LIST_HEADER (struct formatter_item) - - enum formatter_item_type type; ///< Type of this item + enum formatter_item_type type : 16; ///< Type of this item + int attribute : 16; ///< Attribute ID int color; ///< Color - int attribute; ///< Attribute ID - char *text; ///< Either text or an attribute string + char *text; ///< String }; -static struct formatter_item * -formatter_item_new (void) -{ - struct formatter_item *self = xcalloc (1, sizeof *self); - return self; -} - static void -formatter_item_destroy (struct formatter_item *self) +formatter_item_free (struct formatter_item *self) { free (self->text); - free (self); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1008,7 +999,8 @@ struct formatter struct server *s; ///< Server struct formatter_item *items; ///< Items - struct formatter_item *items_tail; ///< Tail of items + size_t items_len; ///< Items used + size_t items_alloc; ///< Items allocated }; static void @@ -1018,13 +1010,16 @@ formatter_init (struct formatter *self, memset (self, 0, sizeof *self); self->ctx = ctx; self->s = s; + self->items = xcalloc (sizeof *self->items, (self->items_alloc = 16)); + self->items_len = 0; } static void formatter_free (struct formatter *self) { - LIST_FOR_EACH (struct formatter_item, iter, self->items) - formatter_item_destroy (iter); + for (size_t i = 0; i < self->items_len; i++) + formatter_item_free (&self->items[i]); + free (self->items); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1045,21 +1040,31 @@ struct buffer_line int flags; ///< Flags time_t when; ///< Time of the event - struct formatter formatter; ///< Line data + struct formatter_item items[]; ///< Line data }; +/// Create a new buffer line stealing all data from the provided formatter struct buffer_line * buffer_line_new (struct formatter *f) { - struct buffer_line *self = xcalloc (1, sizeof *self); - self->formatter = *f; + // We make space for one more item that gets initialized to all zeros, + // meaning FORMATTER_ITEM_END (because it's the first value in the enum) + size_t items_size = f->items_len * sizeof *f->items; + struct buffer_line *self = + xcalloc (1, sizeof *self + items_size + sizeof *self->items); + memcpy (self->items, f->items, items_size); + + // We've stolen pointers from the formatter, let's destroy it altogether + free (f->items); + memset (f, 0, sizeof *f); return self; } static void buffer_line_destroy (struct buffer_line *self) { - formatter_free (&self->formatter); + for (struct formatter_item *iter = self->items; iter->type; iter++) + formatter_item_free (iter); free (self); } @@ -2619,9 +2624,10 @@ formatter_add_item (struct formatter *self, struct formatter_item template_) if (template_.text) template_.text = xstrdup (template_.text); - struct formatter_item *item = formatter_item_new (); - *item = template_; - LIST_APPEND_WITH_TAIL (self->items, self->items_tail, item); + if (self->items_len == self->items_alloc) + self->items = xreallocarray + (self->items, sizeof *self->items, (self->items_alloc <<= 1)); + self->items[self->items_len++] = template_; } #define FORMATTER_ADD_ITEM(self, type_, ...) formatter_add_item ((self), \ @@ -2911,13 +2917,6 @@ formatter_add (struct formatter *self, const char *format, ...) va_end (ap); } -static void -formatter_add_from (struct formatter *self, struct formatter *other) -{ - for (struct formatter_item *iter = other->items; iter; iter = iter->next) - formatter_add_item (self, *iter); -} - static bool formatter_flush_attr (struct attribute_printer *state, struct formatter_item *item) @@ -2969,9 +2968,12 @@ formatter_flush (struct formatter *self, FILE *stream, bool raw_attributes) { if (!raw_attributes && !get_attribute_printer (stream)) { - LIST_FOR_EACH (struct formatter_item, iter, self->items) + for (size_t i = 0; i < self->items_len; i++) + { + struct formatter_item *iter = &self->items[i]; if (iter->type == FORMATTER_ITEM_TEXT) fputs (iter->text, stream); + } return; } @@ -2980,8 +2982,9 @@ formatter_flush (struct formatter *self, FILE *stream, bool raw_attributes) attribute_printer_reset (&state); int attribute_ignore = 0; - LIST_FOR_EACH (struct formatter_item, iter, self->items) + for (size_t i = 0; i < self->items_len; i++) { + struct formatter_item *iter = &self->items[i]; if (iter->type == FORMATTER_ITEM_TEXT) formatter_flush_text (self->ctx, iter->text, stream); else if (iter->type == FORMATTER_ITEM_IGNORE_ATTR) @@ -3051,7 +3054,9 @@ buffer_line_flush (struct buffer_line *line, struct formatter *f, FILE *output, if (flags & BUFFER_LINE_STATUS) formatter_add (f, " - "); if (flags & BUFFER_LINE_ERROR) formatter_add (f, "#a=!=#r ", ATTR_ERROR); - formatter_add_from (f, &line->formatter); + for (struct formatter_item *iter = line->items; iter->type; iter++) + formatter_add_item (f, *iter); + formatter_add (f, "\n"); formatter_flush (f, output, raw_attributes); formatter_free (f); @@ -3141,7 +3146,6 @@ log_formatter (struct app_context *ctx, if (!buffer) buffer = ctx->global_buffer; - // Move the formatter inside struct buffer_line *line = buffer_line_new (f); line->flags = flags; // TODO: allow providing custom time (IRCv3.2 server-time) |