The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Measure sizeof() of Perl's C Structures

Description

This document describes the sizeof various structures, as determined by util/sizeof.pl. These measurements are mainly for research purposes into making Perl things smaller, or rather, how to use less Perl things.

Perl Structures

Structures diagrams are courtesy gdb (print pretty) and a bit of hand crafting.

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:

name of the subroutine: GvNAMELEN(CvGV(cv))+1
symbol table entry: HvENTRY (25 + GvNAMELEN(CvGV(cv))+1)
minimum sizeof(AV) * 3: xcv_padlist if !CvXSUB(cv)
CvROOT(cv) optree
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.

HvENTRY - 25 + HeKLEN+1
  sizeof(HE *) + sizeof(HE) + sizeof(HEK)
HE - 12
  he = {
     hent_next = 0x0, // HE *
     hent_hek = 0x0,  // HEK *
     hent_val = 0x0   // SV *
  };
HEK - 9 + hek_len
  hek = {
     hek_hash = 0, // U32
     hek_len = 0,  // I32
     hek_key = 0,  // char
  };
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:

AvFILL(av) * sizeof(SV *)

SEE ALSO

perlguts(3), B::Size(3),

http://gisle.aas.no/perl/illguts/

Maintainers

Maintainer is the person(s) you should contact with updates, corrections and patches.

  • Doug MacEachern <dougm (at) covalent.net>

Authors

  • Doug MacEachern <dougm (at) covalent.net>