in reply to Re^2: [XS] sv_setpv change in behaviour with perl-5.42.0 and later
in thread [XS] sv_setpv change in behaviour with perl-5.42.0 and later

Except that, with earlier perls, the new buffer is the same length as the old buffer

That's not true. When older Perls create a new buffer, they are just a bit larger than necessary, just like in 5.42.

In all the examples where you claim there's a new buffer was allocated based on the size of the old one, you are mistaken. As I explained, no new buffer was allocated in those cases. set_sv is simply modifying the existing buffer, something you can't do with shared buffer. And since Perl never shrinks a buffer, modifying the buffer does not shrink it.[1]


  1. It can free it, e.g. using undef $s; (as opposed to $s = undef;), which could eventually result with a shorter buffer in $s. But I don't know of any circumstances in which it directly shrinks a buffer.

Replies are listed 'Best First'.
Re^4: [XS] sv_setpv change in behaviour with perl-5.42.0 and later
by syphilis (Archbishop) on Jan 29, 2026 at 06:59 UTC
    ... modifying the buffer does not shrink it

    So what does SvLEN tell us about the buffer ?
    According to perlapi documentation:
    "SvLEN" Returns the size of the string buffer in the SV, not including any part attributable to "SvOOK". See "SvCUR".
    Now, I don't understand the reference to "SvOOK" and "SvCUR", but the bit that says "Returns the size of the string buffer in the SV" means (to me) that if the value of LEN (ie SvLEN) has been reduced, then size of the buffer has been reduced - ie the buffer has been shrunk.
    Not so ?

    Cheers,
    Rob
      I think this is a matter of semantics. A particular buffer, once allocated, has size SvLEN() and never shrinks. However, that buffer can (under some circumstances) be freed and a different buffer allocated with a smaller SvLEN().

      Dave.

        However, that buffer can (under some circumstances) be freed and a different buffer allocated with a smaller SvLEN().

        Yep - and my first little demo is one that hits one of those "circumstances" when run on perl-5.42.0, but not when run on perl-5.40.0.
        (That's the change in behaviour that bothered me a little.)
        The fact (AFAIK) that it hasn't broken any modules on cpan suggests that this change is not something to be too concerned about.

        And we don't have to invoke XS to demonstrate the change. The following one liner will do that quite well:
        $ perl -MDevel::Peek -le '$x = "x" x 65; Dump $x; $x = "y"; Dump $x;'
        On perl-5.40.0, the Dump() shows that the address associated with $x's "PV" retains it's initial setting, and the value of $x's SvLEN remains at its original value.
        Neither of those 2 things hold on perl-5.42.0, with SvLEN being significantly reduced.

        Thanks guys.

        Cheers,
        Rob

      SvLEN is the size of the buffer currently referenced by SvPVX.

      I didn't say a scalar's buffer couldn't be replaced with a smaller one (which would result in a reduction of a scalar's SvLEN). But even so, it doesn't replace a scalar's buffer unless necessary either.

      That's why copying a short string over a long one in a buffer doesn't affect the buffer size (in any version of Perl).

      use Devel::Peek qw( Dump ); $_ = "x" x 999; $_ .= "x"; # Force unsharing. Dump( $_ ); $_ = "abc"; Dump( $_ );
      SV = PV(0x5b5d1f3fdee0) at 0x5b5d1f439bc8 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x5b5d1f441580 "xxx[...]xxx"\0 CUR = 1000 LEN = 1001 SV = PV(0x5b5d1f3fdee0) at 0x5b5d1f439bc8 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x5b5d1f441580 "abc"\0 <-- Same buffer CUR = 3 LEN = 1001 <-- Same size

      And that's why the difference between when SvLEN goes down or not is whether Perl must allocate a fresh buffer or not.


      OOK is a mechanism which can be used used to efficiently delete from the start of a string. Rather than shifting the entire contents of the buffer, OOK can be used to fake the start and size of the buffer instead.

      use Devel::Peek qw( Dump ); $_ = "abcdefghi"; $_ .= "j"; # Force unsharing. Dump( $_ ); substr( $_ , 0 , 1 ) = ""; Dump( $_ );
      SV = PV(0x600760853ee0) at 0x6007608a35d8 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x60076086a2e0 "abcdefghij"\0 CUR = 10 LEN = 16 SV = PV(0x600760853ee0) at 0x6007608a35d8 REFCNT = 1 FLAGS = (POK,OOK,pPOK) OFFSET = 1 PV = 0x60076086a2e1 ( "\x01" . ) "bcdefghij"\0 CUR = 9 LEN = 15

      There's still a 16 byte buffer at 0x60076086a2e0, and the scalar's buffer was replaced with a a 15 byte virtual buffer at 0x60076086a2e1.


      SvCUR is offered as a contrast. SvLENis the size of the buffer, and SvCUR is the portion used. Also, someone looking for SvCUR might have landed on SvLEN.

        What's the logic behind freeing the old buffer and re-allocating if the new length exceeds some limit (and why "1250"?)? For huge initial size, it should be insignificant if new content length is 1249 or 1250. In fact, the "1250" can be replaced with "1e8" (or "1e8 minus something small" if that matters) and again Perl re-allocates. I'd expect the opposite behaviour: if new content is the same or almost as big as container, then re-use the container. If it's couple of droplets in huge vessel, then replace the vessel.

        use Devel::Peek qw( Dump ); $Devel::Peek::pv_limit = $Devel::Peek::pv_limit = 10; my $n; $_ = "x" x 1e8; $_ .= "x"; # Force unsharing. Dump( $_ ); $n = 1249; $_ = "x" x $n; Dump( $_ ); $_ = "x" x 1e8; $_ .= "x"; # Force unsharing. Dump( $_ ); $n = 1250; $_ = "x" x $n; Dump( $_ ); __END__ 5.042000 SV = PV(0x21d90461a70) at 0x21d9049cb58 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x21d9dd19060 "xxxxxxxxxx"...\0 CUR = 100000001 LEN = 100000002 SV = PV(0x21d90461a70) at 0x21d9049cb58 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x21d9dd19060 "xxxxxxxxxx"...\0 CUR = 1249 LEN = 100000002 SV = PV(0x21d90461a70) at 0x21d9049cb58 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x21d9dd1e060 "xxxxxxxxxx"...\0 CUR = 100000001 LEN = 100000002 SV = PV(0x21d90461a70) at 0x21d9049cb58 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x21d90497bd0 "xxxxxxxxxx"...\0 CUR = 1250 LEN = 1256