aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2016-01-31 20:07:20 +0100
committerPřemysl Janouch <p.janouch@gmail.com>2016-01-31 21:43:23 +0100
commita850ee45f189dc4afd935f967ee7e5fa4168a2d9 (patch)
treecaf7e94445c37d4e638bbb8c2c14766e7597ca37
parent10a264ec3d189ba0fc00e4c6f7b0e7e4a8043aff (diff)
downloadxK-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--NEWS2
-rw-r--r--degesch.c74
2 files changed, 41 insertions, 35 deletions
diff --git a/NEWS b/NEWS
index f19388c..60e07d3 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/degesch.c b/degesch.c
index 26f0065..93d9316 100644
--- a/degesch.c
+++ b/degesch.c
@@ -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)