Front page | perl.perl5.porters |
Postings from June 2010
Re: [patch 0/3] rework sv.c body-inventory mechanics
Thread Previous
|
Thread Next
From:
Jim Cromie
Date:
June 3, 2010 12:15
Subject:
Re: [patch 0/3] rework sv.c body-inventory mechanics
Message ID:
AANLkTil4wHOgQWJ7cpRnU6NF9iPvW0l1zldUQWHaQec9@mail.gmail.com
On Sun, Feb 7, 2010 at 6:21 AM, Nicholas Clark <nick@ccl4.org> wrote:
> On Mon, Feb 01, 2010 at 02:42:24PM +0000, Nicholas Clark wrote:
>
>> This analysis makes me think that actually, yes, the PTE allocation code *is*
>> sub-optimal. But not in the way that you're proposing to fix it.
>>
>> Instead, I think that the following would improve performance, *and* return
>> more memory to malloc()
>>
>> * Remove PTEs from the common arena code/data structures
>> * Give each ptr_table its own arena chain
>> * Don't bother with creating the linked list - use two pointers to operate a
>> slab allocator for the arena
>> * Don't bother with deleting PTEs - just walk and free() the arena chain in
>> ptr_table_clear
>
> Something like the appended.
now that 5.13 is open, is it time to commit this ?
>
> $ git diff --stat
> perl.h | 6 +++---
> sv.c | 57 +++++++++++++++++++++++++++++++--------------------------
> sv.h | 5 +----
> 3 files changed, 35 insertions(+), 33 deletions(-)
>
> If we got rid of ptr_table_clear, which I don't think that anyone else uses,
> then the code would be smaller still, and more efficient, because we could
> avoid Zero()ing the array.
>
> Nicholas Clark
>
> diff --git a/perl.h b/perl.h
> index 5988e78..b2ad719 100644
> --- a/perl.h
> +++ b/perl.h
> @@ -3453,9 +3453,6 @@ typedef struct magic_state MGS; /* struct magic_state defined in mg.c */
> struct scan_data_t; /* Used in S_* functions in regcomp.c */
> struct regnode_charclass_class; /* Used in S_* functions in regcomp.c */
>
> -/* Keep next first in this structure, because sv_free_arenas take
> - advantage of this to share code between the pte arenas and the SV
> - body arenas */
> struct ptr_tbl_ent {
> struct ptr_tbl_ent* next;
> const void* oldval;
> @@ -3466,6 +3463,9 @@ struct ptr_tbl {
> struct ptr_tbl_ent** tbl_ary;
> UV tbl_max;
> UV tbl_items;
> + struct ptr_tbl_arena *tbl_arena;
> + struct ptr_tbl_ent *tbl_arena_next;
> + struct ptr_tbl_ent *tbl_arena_end;
> };
>
> #if defined(iAPX286) || defined(M_I286) || defined(I80286)
> diff --git a/sv.c b/sv.c
> index 3b16d7d..4712e34 100644
> --- a/sv.c
> +++ b/sv.c
> @@ -852,13 +852,6 @@ PL_body_roots[HE_SVSLOT=SVt_NULL] is filled by S_more_he, but the
> bodies_by_type[SVt_NULL] slot is not used, as the table is not
> available in hv.c.
>
> -PTEs also use arenas, but are never seen in Perl_sv_upgrade. Nonetheless,
> -they get their own slot in bodies_by_type[PTE_SVSLOT =SVt_IV], so they can
> -just use the same allocation semantics. At first, PTEs were also
> -overloaded to a non-body sv-type, but this yielded hard-to-find malloc
> -bugs, so was simplified by claiming a new slot. This choice has no
> -consequence at this time.
> -
> */
>
> struct body_details {
> @@ -10654,6 +10647,11 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *const param)
>
> #endif /* USE_ITHREADS */
>
> +struct ptr_tbl_arena {
> + struct ptr_tbl_arena *next;
> + struct ptr_tbl_ent array[1023/3]; /* as ptr_tbl_ent has 3 pointers. */
> +};
> +
> /* create a new pointer-mapping table */
>
> PTR_TBL_t *
> @@ -10665,6 +10663,9 @@ Perl_ptr_table_new(pTHX)
> Newx(tbl, 1, PTR_TBL_t);
> tbl->tbl_max = 511;
> tbl->tbl_items = 0;
> + tbl->tbl_arena = NULL;
> + tbl->tbl_arena_next = NULL;
> + tbl->tbl_arena_end = NULL;
> Newxz(tbl->tbl_ary, tbl->tbl_max + 1, PTR_TBL_ENT_t*);
> return tbl;
> }
> @@ -10672,14 +10673,6 @@ Perl_ptr_table_new(pTHX)
> #define PTR_TABLE_HASH(ptr) \
> ((PTR2UV(ptr) >> 3) ^ (PTR2UV(ptr) >> (3 + 7)) ^ (PTR2UV(ptr) >> (3 + 17)))
>
> -/*
> - we use the PTE_SVSLOT 'reservation' made above, both here (in the
> - following define) and at call to new_body_inline made below in
> - Perl_ptr_table_store()
> - */
> -
> -#define del_pte(p) del_body_type(p, PTE_SVSLOT)
> -
> /* map an existing pointer using a table */
>
> STATIC PTR_TBL_ENT_t *
> @@ -10724,7 +10717,18 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *const tbl, const void *const oldsv, void *
> } else {
> const UV entry = PTR_TABLE_HASH(oldsv) & tbl->tbl_max;
>
> - new_body_inline(tblent, PTE_SVSLOT);
> + if (tbl->tbl_arena_next == tbl->tbl_arena_end) {
> + struct ptr_tbl_arena *new_arena;
> +
> + Newx(new_arena, 1, struct ptr_tbl_arena);
> + new_arena->next = tbl->tbl_arena;
> + tbl->tbl_arena = new_arena;
> + tbl->tbl_arena_next = new_arena->array;
> + tbl->tbl_arena_end = new_arena->array
> + + sizeof(new_arena->array) / sizeof(new_arena->array[0]);
> + }
> +
> + tblent = tbl->tbl_arena_next++;
>
> tblent->oldval = oldsv;
> tblent->newval = newsv;
> @@ -10777,20 +10781,21 @@ void
> Perl_ptr_table_clear(pTHX_ PTR_TBL_t *const tbl)
> {
> if (tbl && tbl->tbl_items) {
> - register PTR_TBL_ENT_t * const * const array = tbl->tbl_ary;
> - UV riter = tbl->tbl_max;
> + struct ptr_tbl_arena *arena = tbl->tbl_arena;
>
> - do {
> - PTR_TBL_ENT_t *entry = array[riter];
> + Zero(tbl->tbl_ary, tbl->tbl_max + 1, struct ptr_tbl_ent **);
>
> - while (entry) {
> - PTR_TBL_ENT_t * const oentry = entry;
> - entry = entry->next;
> - del_pte(oentry);
> - }
> - } while (riter--);
> + while (arena) {
> + struct ptr_tbl_arena *next = arena->next;
> +
> + Safefree(arena);
> + arena = next;
> + };
>
> tbl->tbl_items = 0;
> + tbl->tbl_arena = NULL;
> + tbl->tbl_arena_next = NULL;
> + tbl->tbl_arena_end = NULL;
> }
> }
>
> diff --git a/sv.h b/sv.h
> index fc1b475..33d4fb9 100644
> --- a/sv.h
> +++ b/sv.h
> @@ -78,11 +78,8 @@ typedef enum {
> /* There is collusion here with sv_clear - sv_clear exits early for SVt_NULL
> and SVt_IV, so never reaches the clause at the end that uses
> sv_type_details->body_size to determine whether to call safefree(). Hence
> - body_size can be set no-zero to record the size of PTEs and HEs, without
> + body_size can be set no-zero to record the size of HEs, without
> fear of bogus frees. */
> -#ifdef PERL_IN_SV_C
> -#define PTE_SVSLOT SVt_IV
> -#endif
> #if defined(PERL_IN_HV_C) || defined(PERL_IN_XS_APITEST)
> #define HE_SVSLOT SVt_NULL
> #endif
>
Thread Previous
|
Thread Next