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; }