Change 29886 by [EMAIL PROTECTED] on 2007/01/19 20:40:06

        Integrate:
        [ 27079]
        Subject: [patch] arena rework - arena sets
        From: Jim Cromie <[EMAIL PROTECTED]>
        Message-ID: <[EMAIL PROTECTED]>
        Date: Tue, 31 Jan 2006 04:52:06 -0700
        
        [ 27080]
        Tweak arena sets to avoid assignment between different pointers.
        
        [ 27081]
        Rejig the definition of ARENAS_PER_SET to maximise the size of the
        array whilst keeping the structure within PERL_ARENA_SIZE.
        
        [ 27097]
        Subject: [patch] rework arenas - repair arenasets
        From: Jim Cromie <[EMAIL PROTECTED]>
        Message-ID: <[EMAIL PROTECTED]>
        Date: Sun, 05 Feb 2006 05:31:14 -0700

Affected files ...

... //depot/maint-5.8/perl/embed.fnc#168 integrate
... //depot/maint-5.8/perl/embed.h#127 integrate
... //depot/maint-5.8/perl/hv.c#94 integrate
... //depot/maint-5.8/perl/proto.h#157 integrate
... //depot/maint-5.8/perl/sv.c#289 integrate

Differences ...

==== //depot/maint-5.8/perl/embed.fnc#168 (text) ====
Index: perl/embed.fnc
--- perl/embed.fnc#167~29862~   2007-01-17 14:53:30.000000000 -0800
+++ perl/embed.fnc      2007-01-19 12:40:06.000000000 -0800
@@ -1057,6 +1057,10 @@
 s      |void   |require_errno  |NN GV *gv
 #endif
 
+: #if defined(PERL_IN_HV_C) || defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
+paRxo  |void*  |get_arena      |int svtype
+: #endif
+
 #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT)
 s      |void   |hsplit         |NN HV *hv
 s      |void   |hfreeentries   |NN HV *hv

==== //depot/maint-5.8/perl/embed.h#127 (text+w) ====
Index: perl/embed.h
--- perl/embed.h#126~29854~     2007-01-17 10:52:01.000000000 -0800
+++ perl/embed.h        2007-01-19 12:40:06.000000000 -0800
@@ -3132,6 +3132,8 @@
 #define require_errno(a)       S_require_errno(aTHX_ a)
 #endif
 #endif
+#ifdef PERL_CORE
+#endif
 #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT)
 #ifdef PERL_CORE
 #define hsplit(a)              S_hsplit(aTHX_ a)

==== //depot/maint-5.8/perl/hv.c#94 (text) ====
Index: perl/hv.c
--- perl/hv.c#93~29858~ 2007-01-17 13:17:52.000000000 -0800
+++ perl/hv.c   2007-01-19 12:40:06.000000000 -0800
@@ -38,9 +38,8 @@
 {
     HE* he;
     HE* heend;
-    Newx(he, PERL_ARENA_SIZE/sizeof(HE), HE);
-    HeNEXT(he) = (HE*) PL_body_arenas;
-    PL_body_arenas = he;
+
+    he = (HE*) Perl_get_arena(aTHX_ PERL_ARENA_SIZE);
 
     heend = &he[PERL_ARENA_SIZE / sizeof(HE) - 1];
     PL_body_roots[HE_SVSLOT] = ++he;

==== //depot/maint-5.8/perl/proto.h#157 (text+w) ====
Index: perl/proto.h
--- perl/proto.h#156~29862~     2007-01-17 14:53:30.000000000 -0800
+++ perl/proto.h        2007-01-19 12:40:06.000000000 -0800
@@ -1567,6 +1567,11 @@
 STATIC void    S_require_errno(pTHX_ GV *gv);
 #endif
 
+PERL_CALLCONV void*    Perl_get_arena(pTHX_ int svtype)
+                       __attribute__malloc__
+                       __attribute__warn_unused_result__;
+
+
 #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT)
 STATIC void    S_hsplit(pTHX_ HV *hv);
 STATIC void    S_hfreeentries(pTHX_ HV *hv);

==== //depot/maint-5.8/perl/sv.c#289 (text) ====
Index: perl/sv.c
--- perl/sv.c#288~29864~        2007-01-17 15:29:13.000000000 -0800
+++ perl/sv.c   2007-01-19 12:40:06.000000000 -0800
@@ -503,6 +503,52 @@
     return cleaned;
 }
 
+/*
+  ARENASETS: a meta-arena implementation which separates arena-info
+  into struct arena_set, which contains an array of struct
+  arena_descs, each holding info for a single arena.  By separating
+  the meta-info from the arena, we recover the 1st slot, formerly
+  borrowed for list management.  The arena_set is about the size of an
+  arena, avoiding the needless malloc overhead of a naive linked-list
+
+  The cost is 1 arena-set malloc per ~320 arena-mallocs, + the unused
+  memory in the last arena-set (1/2 on average).  In trade, we get
+  back the 1st slot in each arena (ie 1.7% of a CV-arena, less for
+  others)
+
+  union arena is declared with a fixed size, but is intended to vary
+  by type, allowing their use for big, rare body-types where theres
+  currently too much wastage (unused arena slots)
+*/
+#define ARENASETS 1
+
+struct arena_desc {
+    char       *arena;         /* the raw storage, allocated aligned */
+    size_t      size;          /* its size ~4k typ */
+    int         unit_type;     /* useful for arena audits */
+    /* info for sv-heads (eventually)
+       int count, flags;
+    */
+};
+
+struct arena_set;
+
+/* Get the maximum number of elements in set[] such that struct arena_set
+   will fit within PERL_ARENA_SIZE, which is probabably just under 4K, and
+   therefore likely to be 1 aligned memory page.  */
+
+#define ARENAS_PER_SET  ((PERL_ARENA_SIZE - sizeof(struct arena_set*) \
+                         - 2 * sizeof(int)) / sizeof (struct arena_desc))
+
+struct arena_set {
+    struct arena_set* next;
+    int   set_size;            /* ie ARENAS_PER_SET */
+    int   curr;                        /* index of next available arena-desc */
+    struct arena_desc set[ARENAS_PER_SET];
+};
+
+#if !ARENASETS
+
 static void 
 S_free_arena(pTHX_ void **root) {
     while (root) {
@@ -511,7 +557,8 @@
        root = next;
     }
 }
-    
+#endif
+
 /*
 =for apidoc sv_free_arenas
 
@@ -539,7 +586,23 @@
            Safefree(sva);
     }
 
+#if ARENASETS
+    {
+       struct arena_set *next, *aroot = (struct arena_set*) PL_body_arenas;
+       
+       for (; aroot; aroot = next) {
+           int max = aroot->curr;
+           for (i=0; i<max; i++) {
+               assert(aroot->set[i].arena);
+               Safefree(aroot->set[i].arena);
+           }
+           next = aroot->next;
+           Safefree(aroot);
+       }
+    }
+#else
     S_free_arena(aTHX_ (void**) PL_body_arenas);
+#endif
     PL_body_arenas = 0;
 
     for (i=0; i<PERL_ARENA_ROOTS_SIZE; i++) {
@@ -606,6 +669,54 @@
   contexts below (line ~10k)
 */
 
+/* get_arena(size): when ARENASETS is enabled, this creates
+   custom-sized arenas, otherwize it uses PERL_ARENA_SIZE, as
+   previously done.
+   TBD: export properly for hv.c: S_more_he().
+*/
+void*
+Perl_get_arena(pTHX_ int arena_size)
+{
+#if !ARENASETS
+    union arena* arp;
+
+    /* allocate and attach arena */
+    Newx(arp, PERL_ARENA_SIZE, char);
+    arp->next = PL_body_arenas;
+    PL_body_arenas = arp;
+    return arp;
+
+#else
+    struct arena_desc* adesc;
+    struct arena_set *newroot, **aroot = (struct arena_set**) &PL_body_arenas;
+    int curr;
+
+    /* shouldnt need this
+    if (!arena_size)   arena_size = PERL_ARENA_SIZE;
+    */
+
+    /* may need new arena-set to hold new arena */
+    if (!*aroot || (*aroot)->curr >= (*aroot)->set_size) {
+       Newxz(newroot, 1, struct arena_set);
+       newroot->set_size = ARENAS_PER_SET;
+       newroot->next = *aroot;
+       *aroot = newroot;
+       DEBUG_m(PerlIO_printf(Perl_debug_log, "new arenaset %p\n", *aroot));
+    }
+
+    /* ok, now have arena-set with at least 1 empty/available arena-desc */
+    curr = (*aroot)->curr++;
+    adesc = &((*aroot)->set[curr]);
+    assert(!adesc->arena);
+    
+    Newxz(adesc->arena, arena_size, char);
+    adesc->size = arena_size;
+    DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p\n", curr, 
aroot));
+
+    return adesc->arena;
+#endif
+}
+
 STATIC void *
 S_more_bodies (pTHX_ size_t size, svtype sv_type)
 {
@@ -614,16 +725,15 @@
     const char *end;
     const size_t count = PERL_ARENA_SIZE / size;
 
-    New(0, start, count*size, char);
-    *((void **) start) = PL_body_arenas;
-    PL_body_arenas = (void *)start;
+    start = (char*) Perl_get_arena(aTHX_ PERL_ARENA_SIZE);
 
     end = start + (count-1) * size;
 
+#if !ARENASETS
     /* 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.  */
-
     start += size;
+#endif
 
     *root = (void *)start;
 
End of Patch.

Reply via email to