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