1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-01 08:17:38 +00:00

Use heuristic to speed up allocation of small vectors (bug#65491)

Instead of scanning vector_free_lists from the appropriate size until
we find a nonempty bucket, start at the last bucket where we last put
something in.  This may favour splitting larger vectors than necessary
but in general saves a lot of time in the allocation of small vectors.

Original patch by Ihor Radchenko.

* src/alloc.c (last_inserted_vector_free_idx): New variable.
(setup_on_free_list): Set it.
(allocate_vector_from_block): Use it.
(sweep_vectors): Reset it.
This commit is contained in:
Mattias Engdegård 2023-09-25 17:19:00 +02:00
parent aa28527500
commit 091b8de586

View File

@ -3155,6 +3155,11 @@ static struct vector_block *vector_blocks;
- For I = VECTOR_FREE_LIST_ARRAY_SIZE-1, VINDEX(BS(V)) I */ - For I = VECTOR_FREE_LIST_ARRAY_SIZE-1, VINDEX(BS(V)) I */
static struct Lisp_Vector *vector_free_lists[VECTOR_FREE_LIST_ARRAY_SIZE]; static struct Lisp_Vector *vector_free_lists[VECTOR_FREE_LIST_ARRAY_SIZE];
/* Index to the bucket in vector_free_lists into which we last inserted
or split a free vector. We use this as a heuristic telling us where
to start looking for free vectors when the exact-size bucket is empty. */
static ptrdiff_t last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
/* Singly-linked list of large vectors. */ /* Singly-linked list of large vectors. */
static struct large_vector *large_vectors; static struct large_vector *large_vectors;
@ -3191,6 +3196,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
set_next_vector (v, vector_free_lists[vindex]); set_next_vector (v, vector_free_lists[vindex]);
ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size); ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
vector_free_lists[vindex] = v; vector_free_lists[vindex] = v;
last_inserted_vector_free_idx = vindex;
} }
/* Get a new vector block. */ /* Get a new vector block. */
@ -3256,7 +3262,8 @@ allocate_vector_from_block (ptrdiff_t nbytes)
/* Next, check free lists containing larger vectors. Since /* Next, check free lists containing larger vectors. Since
we will split the result, we should have remaining space we will split the result, we should have remaining space
large enough to use for one-slot vector at least. */ large enough to use for one-slot vector at least. */
for (index = VINDEX (nbytes + VBLOCK_BYTES_MIN); for (index = max (VINDEX (nbytes + VBLOCK_BYTES_MIN),
last_inserted_vector_free_idx);
index < VECTOR_FREE_LIST_ARRAY_SIZE; index++) index < VECTOR_FREE_LIST_ARRAY_SIZE; index++)
if (vector_free_lists[index]) if (vector_free_lists[index])
{ {
@ -3489,6 +3496,7 @@ sweep_vectors (void)
gcstat.total_vectors = 0; gcstat.total_vectors = 0;
gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0; gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0;
memset (vector_free_lists, 0, sizeof (vector_free_lists)); memset (vector_free_lists, 0, sizeof (vector_free_lists));
last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
/* Looking through vector blocks. */ /* Looking through vector blocks. */