in reply to fork(): where does copy happen?

One thing you'll need to look for is places where a scalar's internal type might change. For example:

my $number = 10; print "$number\n";

That second line is going to actually write to $number by changing it from a pure integer (IV) into a string/integer (PVIV). You can prove this by using Devel::Peek:

use Devel::Peek; my $number = 10; Dump($number); print "Number is $number\n"; Dump($number);

Which outputs:

SV = IV(0x9a5cfe0) at 0x9a41774 REFCNT = 1 FLAGS = (PADBUSY,PADMY,IOK,pIOK) IV = 10 Number is 10 SV = PVIV(0x9a42b10) at 0x9a41774 REFCNT = 1 FLAGS = (PADBUSY,PADMY,IOK,POK,pIOK,pPOK) IV = 10 PV = 0x9a57758 "10"\0 CUR = 2 LEN = 4

If that variable was part of your shared pre-fork data then that data page just got unshared, all 4k of it! It's possible to avoid this in some cases, for example by using printf() instead of print() above, but it's quite difficult to find all the possible cases.

To learn more about how Perl manages memory check out perlguts.

-sam

Replies are listed 'Best First'.
Re^2: fork(): where does copy happen?
by almut (Canon) on Apr 16, 2008 at 18:06 UTC

    It might be worth pointing out that even the module Readonly will - contrary to what one might expect - not prevent the internal structures from being modified by implicit type conversions. (In addition, the structures are more complex to start with.)  E.g.

    use Devel::Peek; use Readonly; Readonly::Scalar my $number => 10; Dump($number); printf "Number is %d\n", $number; Dump($number); print "Number is $number\n"; Dump($number);

    Output:

    SV = PVMG(0x68ba80) at 0x65eb40
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,GMG,SMG,RMG)
      IV = 0
      NV = 0
      PV = 0
      MAGIC = 0x662c90
        MG_VIRTUAL = &PL_vtbl_packelem
        MG_TYPE = PERL_MAGIC_tiedscalar(q)
        MG_FLAGS = 0x02
          REFCOUNTED
        MG_OBJ = 0x63c410
        SV = RV(0x6ba0d0) at 0x63c410
          REFCNT = 1
          FLAGS = (ROK)
          RV = 0x6dc2e0
          SV = PVMG(0x68ba48) at 0x6dc2e0
            REFCNT = 1
            FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK)
            IV = 10
            NV = 0
            PV = 0
            STASH = 0x6dc120	"Readonly::Scalar"
    Number is 10
    SV = PVMG(0x68ba80) at 0x65eb40
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,GMG,SMG,RMG,pIOK)
      IV = 10
      NV = 0
      PV = 0
      MAGIC = 0x662c90
        MG_VIRTUAL = &PL_vtbl_packelem
        MG_TYPE = PERL_MAGIC_tiedscalar(q)
        MG_FLAGS = 0x02
          REFCOUNTED
        MG_OBJ = 0x63c410
        SV = RV(0x6ba0d0) at 0x63c410
          REFCNT = 1
          FLAGS = (ROK)
          RV = 0x6dc2e0
          SV = PVMG(0x68ba48) at 0x6dc2e0
            REFCNT = 1
            FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK)
            IV = 10
            NV = 0
            PV = 0
            STASH = 0x6dc120	"Readonly::Scalar"
    Number is 10
    SV = PVMG(0x68ba80) at 0x65eb40
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,GMG,SMG,RMG,pIOK,pPOK)
      IV = 10
      NV = 0
      PV = 0x6519b0 "10"\0
      CUR = 2
      LEN = 8
      MAGIC = 0x662c90
        MG_VIRTUAL = &PL_vtbl_packelem
        MG_TYPE = PERL_MAGIC_tiedscalar(q)
        MG_FLAGS = 0x02
          REFCOUNTED
        MG_OBJ = 0x63c410
        SV = RV(0x6ba0d0) at 0x63c410
          REFCNT = 1
          FLAGS = (ROK)
          RV = 0x6dc2e0
          SV = PVMG(0x68ba48) at 0x6dc2e0
            REFCNT = 1
            FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK)
            IV = 10
            NV = 0
            PV = 0
            STASH = 0x6dc120	"Readonly::Scalar"
    

    _____

    Update: ...similarly with Scalar::Readonly, btw  (though here the internal structures are as lean as without using the module):

    use Devel::Peek; use Scalar::Readonly ':all'; my $number = 10; readonly_on($number); Dump($number); print "Number is $number\n"; Dump($number);
    SV = IV(0x661dc8) at 0x65eb50
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,IOK,READONLY,pIOK)
      IV = 10
    Number is 10
    SV = PVIV(0x63e130) at 0x65eb50
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,IOK,POK,READONLY,pIOK,pPOK)
      IV = 10
      PV = 0x654fb0 "10"\0
      CUR = 2
      LEN = 8
    
Re^2: fork(): where does copy happen?
by Anonymous Monk on Apr 16, 2008 at 16:47 UTC
    ouch, if even your example causes a copy, then there will be alot to be cleaned up ;)