Optimize memory usage a bit

Stop calling calloc() to allocate large amounts of tiny lists of
pointers but instead serialize these lists and keep offsets.
This commit is contained in:
Přemysl Eric Janouch 2017-01-27 01:17:16 +01:00
parent 2a0e968924
commit 973d12a84e
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 24 additions and 12 deletions

36
hex.c
View File

@ -130,7 +130,7 @@ struct mark
struct marks_by_offset
{
int64_t offset; ///< Offset in the file
struct mark **marks; ///< Sentinelled array of mark pointers
size_t marks; ///< Offset into "offset_entries"
int color; ///< Color of the area until next offset
};
@ -169,6 +169,7 @@ static struct app_context
struct str mark_strings; ///< Storage for mark descriptions
ARRAY (struct marks_by_offset, marks_by_offset)
ARRAY (struct mark *, offset_entries)
// View:
@ -288,6 +289,7 @@ app_init_context (void)
ARRAY_INIT (g_ctx.marks);
str_init (&g_ctx.mark_strings);
ARRAY_INIT (g_ctx.marks_by_offset);
ARRAY_INIT (g_ctx.offset_entries);
// This is also approximately what libunistring does internally,
// since the locale name is canonicalized by locale_charset().
@ -337,10 +339,8 @@ app_free_context (void)
free (g_ctx.marks);
str_free (&g_ctx.mark_strings);
for (size_t i = 0; i < g_ctx.marks_by_offset_len; i++)
free (g_ctx.marks_by_offset[i].marks);
free (g_ctx.marks_by_offset);
free (g_ctx.offset_entries);
free (g_ctx.message);
@ -419,6 +419,17 @@ app_mark_cmp (const void *first, const void *second)
return 0;
}
static size_t
app_store_marks (struct mark **entries, size_t len)
{
size_t result = g_ctx.offset_entries_len;
ARRAY_RESERVE (g_ctx.offset_entries, len);
memcpy (g_ctx.offset_entries + g_ctx.offset_entries_len, entries,
sizeof *entries * len);
g_ctx.offset_entries_len += len;
return result;
}
/// Flattens marks into sequential non-overlapping spans suitable for search
/// by offset, assigning different colors to them in the process:
/// @code
@ -439,6 +450,9 @@ app_flatten_marks (void)
ARRAY_INIT (current);
int current_color = 0;
// Make offset zero actually point to an empty entry
g_ctx.offset_entries[g_ctx.offset_entries_len++] = NULL;
struct mark *next = g_ctx.marks;
struct mark *end = next + g_ctx.marks_len;
while (current_len || next < end)
@ -461,19 +475,18 @@ app_flatten_marks (void)
// Add any new marks at "closest"
while (next < end && next->offset == closest)
{
ARRAY_RESERVE (current, 1);
current[current_len++] = next++;
ARRAY_RESERVE (current, 1);
}
current[current_len] = NULL;
// Save marks at that offset to be used by rendering
struct mark **marks = NULL;
size_t marks = 0;
int color = -1;
if (current_len)
{
marks = memcpy (xcalloc (sizeof *marks, current_len + 1),
current, sizeof *marks * current_len);
marks = app_store_marks (current, current_len + 1);
color = ATTRIBUTE_C1 + current_color++;
current_color %= 4;
}
@ -601,13 +614,12 @@ app_draw_info (void)
return;
int x_offset = 70;
struct mark **iter = marks->marks;
struct mark *mark, **iter = g_ctx.offset_entries + marks->marks;
for (int y = 0; y < app_visible_rows (); y++)
{
// TODO: we can use the field background
// TODO: we can keep going through subsequent fields to fill the column
struct mark *mark;
if (!iter || !(mark = *iter++))
if (!(mark = *iter++))
break;
struct row_buffer buf;