[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]