in reply to Re^3: perl5.10 Devel::Size behaviour changed? (bug report)
in thread perl5.10 Devel::Size behaviour changed?

If it's a bug, it's not attributable to Devel::Size. Any operation that queries the size does the same thing:

perl -MDevel::Peek -e "my @a; Dump \@a, 1; printf qq[SIZE :%d\n], $#a; + Dump \@a, 1" SV = RV(0x34e158) at 0x34e148 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x276630 SV = PVAV(0x34efb8) at 0x276630 REFCNT = 2 FLAGS = (PADMY) ARRAY = 0x0 FILL = -1 MAX = -1 ARYLEN = 0x0 FLAGS = (REAL) SIZE :-1 SV = RV(0x34e290) at 0x34e280 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x276630 SV = PVAV(0x34efb8) at 0x276630 REFCNT = 2 FLAGS = (PADMY,RMG) MAGIC = 0x27fde8 MG_VIRTUAL = &PL_vtbl_arylen_p MG_TYPE = PERL_MAGIC_arylen_p(@) MG_FLAGS = 0x02 REFCOUNTED MG_OBJ = 0x34e148 SV = PVMG(0x261f18) at 0x34e148 REFCNT = 1 FLAGS = (GMG,SMG,pIOK) IV = -1 NV = 0 PV = 0 MAGIC = 0x27fcf8 MG_VIRTUAL = &PL_vtbl_arylen MG_TYPE = PERL_MAGIC_arylen(#) MG_OBJ = 0x276630 ARRAY = 0x0 FILL = -1 MAX = -1 ARYLEN = 0x34e148 FLAGS = (REAL)

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP PCW It is as I've been saying!(Audio until 20090817)

Replies are listed 'Best First'.
Re^5: perl5.10 Devel::Size behaviour changed? (reason for magic)
by ikegami (Patriarch) on Sep 04, 2009 at 20:40 UTC

    The reason a change was made:

    FromNicholas Clark
    reply-toEric Brine,
    perl5 porters <perl5-porters@perl.org>
    toEric Brine
    ccperl5 porters <perl5-porters@perl.org>
    dateFri, Sep 4, 2009 at 2:55 PM
    subjectRe: rvalue $#a adds magic

    On Fri, Sep 04, 2009 at 02:46:26PM -0400, Eric Brine wrote:
    > Before 5.10, $#a didn't add magic to @a

    > Since 5.10.0, it does.

    > Is that intentional?
    > What's the purpose?

    It's storing the value for $#a in the magic. Most arrays don't use $#a, which means that before 5.10 nearly every array consumes 1 pointers-worth of memory just to store NULL.

    I did it in 2005: http://perl5.git.perl.org/perl.git/commitdiff/a3874608cd3b

      Hm. Pre-5.10, every array that didn't use $#array, wasted 1 pointer.

      Post 5.10, every array uses that pointer to point to a 12 or 24-byte block of memory whether it is ever used or not.

      And the very act of attempting to check to see if there is any magic attached, causes there to be magic attached.

      That makes no sense at all to me.

      Now the only way D::S can avoid causing the magic to be attached is to either not bother looking to see if there is any; or to dereference the magic pointer directly...

      A microscopic optimisation attempt that causes a macroscopic [sic] pessimisation. Autovivifying magic just because someone wants to know if there is any is...


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Commits 02d85cc37a4acecafdc2f0b45640b03cd1f4ac71 and 28c5b5bcd7f52e6b2219508a1066cd0ccc8dd19a fix this when $#array is used as a rvalue. You'll see these changes in 5.11.2 (next month's dev release) and 5.12 (early to mid 2010)
Re^5: perl5.10 Devel::Size behaviour changed? (bug report)
by ikegami (Patriarch) on Sep 04, 2009 at 18:38 UTC

    Any operation that queries the size does the same thing:

    Not so.
    >perl -MDevel::Peek -le"my @a = qw(a b c); print @a-1; Dump \@a,1" 2 SV = RV(0x238c60) at 0x238c54 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182a22c SV = PVAV(0x239a4c) at 0x182a22c REFCNT = 2 FLAGS = (PADMY) ARRAY = 0x182521c FILL = 2 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL)

    If it's a bug, it's not attributable to Devel::Size.

    If it's a bug that reading $#a adds magic to @a, then that's not attributable to D::S.

    The bug in D::S is that it should be using the method that doesn't add magic.

      I see you removed the "rvalue" reference...

      Anyway, the code of D::S does this:

      if (AvMAX(thing) != -1) { /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 * +/ total_size += sizeof(SV *) * (AvMAX(thing) + 1);

      And AvMAX is defined as:

      #define AvMAX(av) ((XPVAV*) SvANY(av))->xav_max

      Ie. It simply gets the value from a struct member.

      It also references AvALLOC & AvARYLEN, but neither of those does anything with magic either:

      #define AvARRAY(av) ((av)->sv_u.svu_array) #define AvALLOC(av) (*((SV***)&((XPVAV*) SvANY(av))->xav_alloc)) #define AvMAX(av) ((XPVAV*) SvANY(av))->xav_max #define AvFILLp(av) ((XPVAV*) SvANY(av))->xav_fill #define AvARYLEN(av) (*Perl_av_arylen_p(aTHX_ MUTABLE_AV(av)))

      The only "method" that touches magic is AvFILL:

      #define AvFILL(av) ((SvRMAGICAL((const SV *) (av))) \ ? mg_size(MUTABLE_SV(av)) : AvFILLp(av))

      And AvFILL doesn't appear anywhere in the D::S source.

      So, I say again, the bug does not lie with D::S.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        D::S also uses AvARRAY, AvALLOC and AvARYLEN.

        use strict; use warnings; use Devel::Peek qw( Dump ); use Inline C => <<'__EOI__'; void call_AvMAX(AV* av) { AvMAX(av); } void call_AvARRAY(AV* av) { AvARRAY(av); } void call_AvALLOC(AV* av) { AvALLOC(av); } void call_AvARYLEN(AV* av) { AvARYLEN(av); } __EOI__ my @a = qw( a b c ); print("After init:\n"); Dump(\@a, 1); call_AvMAX(\@a); print("\nAfter AvMAX:\n"); Dump(\@a, 1); call_AvARRAY(\@a); print("\nAfter AvARRAY:\n"); Dump(\@a, 1); call_AvALLOC(\@a); print("\nAfter AvALLOC:\n"); Dump(\@a, 1); call_AvARYLEN(\@a); print("\nAfter AvARYLEN:\n"); Dump(\@a, 1);
        After init: SV = RV(0x238c18) at 0x238c0c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182a68c SV = PVAV(0x2399f4) at 0x182a68c REFCNT = 2 FLAGS = (PADMY) ARRAY = 0x1824504 FILL = 2 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL) After AvMAX: SV = RV(0x238c18) at 0x238c0c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182a68c SV = PVAV(0x2399f4) at 0x182a68c REFCNT = 2 FLAGS = (PADMY) ARRAY = 0x1824504 FILL = 2 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL) After AvARRAY: SV = RV(0x238c18) at 0x238c0c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182a68c SV = PVAV(0x2399f4) at 0x182a68c REFCNT = 2 FLAGS = (PADMY) ARRAY = 0x1824504 FILL = 2 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL) After AvALLOC: SV = RV(0x238c18) at 0x238c0c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182a68c SV = PVAV(0x2399f4) at 0x182a68c REFCNT = 2 FLAGS = (PADMY) ARRAY = 0x1824504 FILL = 2 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL) After AvARYLEN: SV = RV(0x238c18) at 0x238c0c REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182a68c SV = PVAV(0x2399f4) at 0x182a68c REFCNT = 2 FLAGS = (PADMY,RMG) MAGIC = 0x23fdbc MG_VIRTUAL = &PL_vtbl_arylen_p MG_TYPE = PERL_MAGIC_arylen_p(@) MG_FLAGS = 0x02 REFCOUNTED ARRAY = 0x1824504 FILL = 2 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL)

        So AvARYLEN is the culprit. In 5.10.1, AvARYLEN is defined as

        #define AvARYLEN(av) (*Perl_av_arylen_p(aTHX_ MUTABLE_AV(av)))

        Sounds familiar.