scrolling: optimize row access by assuming number of rows is a power of 2

With this assumption, we can replace 'a % b' with 'a & (b - 1)'. In
terms of instructions, this means a fast 'and' instead of a slow
'div'.

Further optimize scrolling by:

* not double-initializing empty rows. Previously, grid_row_alloc()
  called calloc(), which was then followed by a memset() when
  scrolling. This is of course unnecessary.

* Don't loop the entire set of visible rows (this was done to ensure
  all visible rows had been allocated, and to prefetch the cell
  contents).

  This isn't necessary; only newly pulled in rows can be NULL. For
  now, don't prefetch at all.
This commit is contained in:
Daniel Eklöf 2019-08-22 17:33:23 +02:00
parent f0663c951e
commit 7c7720a3ab
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 107 additions and 56 deletions

37
grid.c
View file

@ -8,30 +8,39 @@
#include "log.h"
void
grid_swap_row(struct grid *grid, int row_a, int row_b)
grid_swap_row(struct grid *grid, int row_a, int row_b, bool initialize)
{
assert(grid->offset >= 0);
assert(row_a != row_b);
int real_a = (grid->offset + row_a + grid->num_rows) % grid->num_rows;
int real_b = (grid->offset + row_b + grid->num_rows) % grid->num_rows;
int real_a = (grid->offset + row_a) & (grid->num_rows - 1);
int real_b = (grid->offset + row_b) & (grid->num_rows - 1);
assert(real_a >= 0);
assert(real_b >= 0);
struct row *tmp = grid->rows[real_a];
grid->rows[real_a] = grid->rows[real_b];
grid->rows[real_b] = tmp;
struct row *a = grid->rows[real_a];
struct row *b = grid->rows[real_b];
#if 0
if (a == NULL)
a = grid_row_alloc(grid->num_cols, initialize);
if (b == NULL)
b = grid_row_alloc(grid->num_cols, initialize);
#endif
grid->rows[real_a] = b;
grid->rows[real_b] = a;
}
struct row *
grid_row_alloc(int cols)
grid_row_alloc(int cols, bool initialize)
{
struct row *row = malloc(sizeof(*row));
row->cells = calloc(cols, sizeof(row->cells[0]));
for (size_t c = 0; c < cols; c++)
row->cells[c].attrs.clean = 1;
row->dirty = false; /* TODO: parameter? */
row->dirty = false;
if (initialize) {
row->cells = calloc(cols, sizeof(row->cells[0]));
for (size_t c = 0; c < cols; c++)
row->cells[c].attrs.clean = 1;
} else
row->cells = malloc(cols * sizeof(row->cells[0]));
return row;
}