[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]
[RFC patch] linked list of arenas
This patch alters arena operation by using a
separate linked list node to chain arenas together,
rather than stealing the 1st element.
This recovers 1 lost element per arena, or 1 of every ~53 CVs,
but adds a pointer indirection when adding new arenas.
(also happens 1 of 50 times, arguably negligible)
It passes tests threaded & unthreaded, I havent benchmarked it.
One side-benefit here is that without the wasteage,
we can allocate smaller arenas effectively.
If we also add arena_size field to body_details,
we can set up small arenas for those types which were formerly
too large & rare, and big ones where application-tuning warrants it.
Later, we can define a pragma to expose the arena-size for user tuning,
with some interface thats consistent with what Devel::Arena reports.
an example usage is:
use arenas {
# keys should/will match those used by DA
default => 12, # ie 2**12 - 16, the current arena-size
FM => 5, # this app uses study() 32 times, try to avoid
additional arenas
IO => 5, # app is IO intensive, maybe with File::Cache
}
this is perhaps too literal wrt sizing, but its simple, and easy to
understand
how to use ( if not easy to actually use well ). Obviously, it could be
easily abused too ( default => 22 ) or ( default => 2 )
And, of course, its not clear that tuning will make any difference.
comments ?
diff -ruN -X exclude-diffs ../bleadperl/sv.c arena-lists/sv.c
--- ../bleadperl/sv.c 2005-11-19 04:48:54.000000000 -0700
+++ arena-lists/sv.c 2005-11-19 21:25:01.000000000 -0700
@@ -1110,36 +1110,43 @@
contexts below (line ~10k)
*/
+/* Instead of reserving the 1st (svtyped) element in the arena-array
+ to chain multiple arenas together, we use a separate linked list.
+ This adds some overhead to arena allocation, but recovers the 1st
+ element, ie 1 of 53 CV elements that can be stored in a 4080 byte
+ arena (4080 leaves 16 bytes for malloc overhead).
+*/
+struct arenalist {
+ struct arenalist* next;
+ void* arena;
+};
+
STATIC void *
S_more_bodies (pTHX_ size_t size, svtype sv_type)
{
- void **arena_root = &PL_body_arenaroots[sv_type];
- void **root = &PL_body_roots[sv_type];
char *start;
- const char *end;
+ struct arenalist* link;
+ int i;
const size_t count = PERL_ARENA_SIZE / size;
- Newx(start, count*size, char);
- *((void **) start) = *arena_root;
- *arena_root = (void *)start;
-
- end = start + (count-1) * size;
+ Newx(link, 1 * sizeof(struct arenalist), void);
+ Newx(link->arena, count*size, char);
+ link->next = PL_body_arenaroots[sv_type];
- /* The initial slot is used to link the arenas together, so it isn't to be
- linked into the list of ready-to-use bodies. */
+ PL_body_arenaroots[sv_type] = link;
+ PL_body_roots[sv_type] = link->arena;
- start += size;
-
- *root = (void *)start;
-
- while (start < end) {
+ /* chain the free bodies together, treating the field at offset 0
+ as a pointer to the next sized element in the array
+ */
+ for (i=0,start=link->arena; i<count-1; i++) {
char * const next = start + size;
*(void**) start = (void *)next;
start = next;
}
- *(void **)start = 0;
+ *(void **)start = 0; /* undo the last chaining */
- return *root;
+ return PL_body_roots[sv_type];
}
/* grab a new thing from the free list, allocating more if necessary */
- Follow-Ups from:
-
Nicholas Clark <nick@ccl4.org>
Nicholas Clark <nick@ccl4.org>
[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]