aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorMattias Engdegård2023-09-25 17:19:00 +0200
committerMattias Engdegård2023-09-25 17:33:21 +0200
commit091b8de586efc41c3dbd8606445c99c541e90076 (patch)
tree492d61f5c27b628eff5df7c332da384dcff4c41b /src/alloc.c
parentaa28527500210e542349cca3cd805a61a01c9dac (diff)
downloademacs-091b8de586efc41c3dbd8606445c99c541e90076.tar.gz
emacs-091b8de586efc41c3dbd8606445c99c541e90076.zip
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.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b2d3f734d4f..45a950c4f81 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3155,6 +3155,11 @@ static struct vector_block *vector_blocks;
3155 - For I = VECTOR_FREE_LIST_ARRAY_SIZE-1, VINDEX(BS(V)) ≥ I */ 3155 - For I = VECTOR_FREE_LIST_ARRAY_SIZE-1, VINDEX(BS(V)) ≥ I */
3156static struct Lisp_Vector *vector_free_lists[VECTOR_FREE_LIST_ARRAY_SIZE]; 3156static struct Lisp_Vector *vector_free_lists[VECTOR_FREE_LIST_ARRAY_SIZE];
3157 3157
3158/* Index to the bucket in vector_free_lists into which we last inserted
3159 or split a free vector. We use this as a heuristic telling us where
3160 to start looking for free vectors when the exact-size bucket is empty. */
3161static ptrdiff_t last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
3162
3158/* Singly-linked list of large vectors. */ 3163/* Singly-linked list of large vectors. */
3159 3164
3160static struct large_vector *large_vectors; 3165static struct large_vector *large_vectors;
@@ -3191,6 +3196,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
3191 set_next_vector (v, vector_free_lists[vindex]); 3196 set_next_vector (v, vector_free_lists[vindex]);
3192 ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size); 3197 ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
3193 vector_free_lists[vindex] = v; 3198 vector_free_lists[vindex] = v;
3199 last_inserted_vector_free_idx = vindex;
3194} 3200}
3195 3201
3196/* Get a new vector block. */ 3202/* Get a new vector block. */
@@ -3256,7 +3262,8 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3256 /* Next, check free lists containing larger vectors. Since 3262 /* Next, check free lists containing larger vectors. Since
3257 we will split the result, we should have remaining space 3263 we will split the result, we should have remaining space
3258 large enough to use for one-slot vector at least. */ 3264 large enough to use for one-slot vector at least. */
3259 for (index = VINDEX (nbytes + VBLOCK_BYTES_MIN); 3265 for (index = max (VINDEX (nbytes + VBLOCK_BYTES_MIN),
3266 last_inserted_vector_free_idx);
3260 index < VECTOR_FREE_LIST_ARRAY_SIZE; index++) 3267 index < VECTOR_FREE_LIST_ARRAY_SIZE; index++)
3261 if (vector_free_lists[index]) 3268 if (vector_free_lists[index])
3262 { 3269 {
@@ -3489,6 +3496,7 @@ sweep_vectors (void)
3489 gcstat.total_vectors = 0; 3496 gcstat.total_vectors = 0;
3490 gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0; 3497 gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0;
3491 memset (vector_free_lists, 0, sizeof (vector_free_lists)); 3498 memset (vector_free_lists, 0, sizeof (vector_free_lists));
3499 last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
3492 3500
3493 /* Looking through vector blocks. */ 3501 /* Looking through vector blocks. */
3494 3502