=head1 NAME

Measure sizeof() of Perl's C Structures

=head1 Description

This document describes the I<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 C<sizeof(HvENTRY)>, minimum of 7 (initial C<xhv_max>).
Note that keys of the same value share C<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 Maintainers

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

=over

=item *

Doug MacEachern E<lt>dougm (at) covalent.netE<gt>

=back

=head1 Authors

=over

=item *

Doug MacEachern E<lt>dougm (at) covalent.netE<gt>

=back

=cut
