You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by do...@apache.org on 2001/01/07 23:43:36 UTC

cvs commit: modperl-2.0/util sizeof.pl

dougm       01/01/07 14:43:36

  Added:       pod      modperl_sizeof.pod
               util     sizeof.pl
  Log:
  researching sizeof() things
  
  Revision  Changes    Path
  1.1                  modperl-2.0/pod/modperl_sizeof.pod
  
  Index: modperl_sizeof.pod
  ===================================================================
  =head1 NAME
  
  modperl_sizeof - measure sizeof structures
  
  =head1 DESCRIPTION
  
  This pod documents the sizeof various structures, as determined by
  I<util/sizeof.pl>.  These measurements are mainly for research
  purposes into making Perl things smaller, or rather, how to use less
  Perl things.
  
  =head1 Perl Structures
  
  Structures diagrams are courtesy gdb (print pretty) and a bit of hand crafting.
  
  =over 4
  
  =item CV - 229 minimum, 254 minimum w/ symbol table entry
  
   cv = {
      sv_any = {        // XPVCV *
          xpv_pv = 0x0, // char *
          xpv_cur = 0,  // STRLEN
          xpv_len = 0,  // STRLEN
          xof_off = 0 , // IV
          xnv_nv = 0,   // NV
          xmg_magic = 0x0, // MAGIC *
          xmg_stash = 0x0, // HV *
          xcv_stash = 0x0, // HV *
          xcv_start = 0x0, // OP *
          xcv_root = 0x0,  // OP *
          xcv_xsub = 0x0,  // void (*)(register PerlInterpreter *, CV *)
          xcv_xsubany = {  // ANY
              any_ptr = 0x0, 
              any_i32 = 0, 
              any_iv = 0, 
              any_long = 0, 
              any_dptr = 0, 
              any_dxptr = 0
          }, 
          xcv_gv = { // GV *
              sv_any = { // void *
                  xpv_pv = 0x0, // char *
                  xpv_cur = 0,  // STRLEN
                  xpv_len = 0,  // STRLEN
                  xiv_iv = 0,   // IV
                  xnv_nv = 0,   // NV
                  xmg_magic =  { // MAGIC *
                      mg_moremagic = 0x0, // MAGIC *
                      mg_virtual = 0x0,   // MGVTBL *
                      mg_private = 0,     // U16
                      mg_type = 0,        // char
                      mg_flags = 0,       // U8
                      mg_obj = 0x0,       // SV *
                      mg_ptr = 0x0,       // char *
                      mg_len = 0,         // I32
                  }, 
                  xmg_stash = 0x0, // HV *
                  xgv_gp = { // GP *
                      gp_sv = { // SV *
                          sv_any = 0x0,  // void *
                          sv_refcnt = 0, // U32
                          sv_flags = 0   // U32
                      }, 
                      gp_refcnt = 0, // U32
                      gp_io = 0x0,   // struct io *
                      gp_form = 0x0, // CV *
                      gp_av = 0x0,   // AV *
                      gp_hv = 0x0,   // HV *
                      gp_egv = 0x0,  // GV *
                      gp_cv = 0x0,   // CV *
                      gp_cvgen = 0,  // U32
                      gp_flags = 0,  // U32
                      gp_line = 0,   // line_t
                      gp_file = 0x0, // char *
                  }, 
                  xgv_name = 0x0,  // char *
                  xgv_namelen = 0, // STRLEN
                  xgv_stash = 0x0, // void *
                  xgv_flags = 0,   // U8
              },
              sv_refcnt = 0, // U32
              sv_flags = 0,  // U32
          },
          xcv_file = 0x0, // char *
          xcv_depth = 0, // long
          xcv_padlist = 0x0, // AV *
          xcv_outside = 0x0, // CV *
          xcv_flags = 0, // cv_flags_t
      }
      sv_refcnt = 0, // U32
      sv_flags = 0,  // U32
   };
  
  In addition to the minimum bytes:
  
  =over 4
  
  =item name of the subroutine: GvNAMELEN(CvGV(cv))+1
  
  =item symbol table entry: HvENTRY (25 + GvNAMELEN(CvGV(cv))+1)
  
  =item minimum sizeof(AV) * 3: xcv_padlist if !CvXSUB(cv)
  
  =item CvROOT(cv) optree
  
  =back
  
  =item HV - 60 minmum
  
   hv = {
      sv_any = { // SV *
          xhv_array = 0x0,  // char *
          xhv_fill = 0,     // STRLEN
          xhv_max = 0,      // STRLEN
          xhv_keys = 0,     // IV
          xnv_nv = 0,       // NV
          xmg_magic = 0x0,  // MAGIC *
          xmg_stash = 0x0,  // HV *
          xhv_riter = 0,    // I32
          xhv_eiter = 0x0,  // HE *
          xhv_pmroot = 0x0, // PMOP *
          xhv_name = 0x0    // char *
      }, 
      sv_refcnt = 0, // U32
      sv_flags = 0,  // U32
   };
  
  Each entry adds sizeof(HvENTRY), minimum of 7 (initial xhv_max).
  Note that keys of the same value share sizeof(HEK), across all hashes.
  
  =item HvENTRY - 25 + HeKLEN+1
  
   sizeof(HE *) + sizeof(HE) + sizeof(HEK)
  
  =item HE - 12
  
   he = {
      hent_next = 0x0, // HE *
      hent_hek = 0x0,  // HEK *
      hent_val = 0x0   // SV *
   };
  
  =item HEK - 9 + hek_len
  
   hek = {
      hek_hash = 0, // U32
      hek_len = 0,  // I32
      hek_key = 0,  // char
   };
  
  =item AV - 53
  
   av = {
      sv_any =  { // SV *
          xav_array = 0x0,  // char *
          xav_fill = 0,     // size_t
          xav_max = 0,      // size_t
          xof_off = 0,      // IV
          xnv_nv = 0,       // NV
          xmg_magic = 0x0,  // MAGIC *
          xmg_stash = 0x0,  // HV *
          xav_alloc = 0x0,  // SV **
          xav_arylen = 0x0, // SV *
          xav_flags = 0,    // U8
      },
      sv_refcnt = 0, // U32
      sv_flags = 0   // U32
   };
  
  In addition to the minimum bytes:
  
  =over 4
  
  =item AvFILL(av) * sizeof(SV *)
  
  =back
  
  =back
  
  =head1 SEE ALSO
  
  perlguts(3), B::Size(3),
  
  http://gisle.aas.no/perl/illguts/
  
  =head1 AUTHOR
  
  Doug MacEachern
  
  
  
  1.1                  modperl-2.0/util/sizeof.pl
  
  Index: sizeof.pl
  ===================================================================
  #calculate structure sizes listed in pod/modperl_sizeof.pod via sizeof()
  
  use strict;
  
  use ExtUtils::Embed;
  use Config;
  
  my $file = shift || 'pod/modperl_sizeof.pod';
  
  open my $pod, $file or die "open $file: $!";
  
  FINDSTRUCT: {
      while (<$pod>) {
          next unless /^\s*(\w+)\s*=\s*\{/;
          my $name = $1;
          my $size = sizeof($name, $pod);
          print "sizeof $name => $size\n";
          redo FINDSTRUCT;
      }
  }
  
  sub sizeof {
      my($struct, $h) = @_;
  
      my @elts;
  
      while (<$h>) {
          last if /^\s*\}\;$/;
          next unless m:(\w+).*?//\s*(.*):;
          push @elts, "sizeof($2) /* $1 */";
      }
  
      my $name = "perl_sizeof_$struct";
      my $tmpfile = "$name.c";
      open my $fh, '>', $tmpfile or die "open $tmpfile: $!";
  
      local $" = " + \n";
  
      print $fh <<EOF;
  #include <stdio.h>
  static FILE *outfp = stdout;
  #define PERLIO_NOT_STDIO 0
  #include "EXTERN.h"
  #include "perl.h"
  #include "XSUB.h"
  
  int main(void) {
      int size = @elts;
      fprintf(outfp, "%d", size);
      return 1;
  }
  EOF
  
      my $opts = ccopts();
      system "$Config{cc} -o $name $tmpfile $opts";
  
      my $size = `$name`;
  
      unlink $name, $tmpfile;
  
      return $size;
  }