develooper Front page | perl.perl5.porters | Postings from January 2001

sharing GV's across perl_clone()

Thread Next
From:
Doug MacEachern
Date:
January 30, 2001 22:13
Subject:
sharing GV's across perl_clone()
Message ID:
Pine.LNX.4.21.0101302147300.12480-100000@mako.covalent.net
i've been looking into ways that modperl-2.0 can shave memory usage.  a
subroutine takes up at least 229 bytes (including the GV and GP), and
closer to 254 bytes when the symbol table entry is included.  if modperl
were to provide an xsub for every apache-2.0 api and access to all
structures, it adds to something close to 300K bytes.  multiply that times
the number of perl_clone()s, say 10, that's 3Mb, 20 clones, 6Mb,
etc.  granted this is worst-case, but it is possible.
xsubs are read-only for the most part, since they have no CvPADLIST.  the
patch below is a proof-of-concept for sharing GV's that point to 
xsubs.  for sharing to take place, the xsub writer must apply 
SvREADONLY_on() to the xsub before a clone is made, for example:

        cv = newXS("Apache::write", XS_Apache_write, file);
        SvREADONLY_on(cv);

attempts to modify another areas of the GV after the clone, e.g.: push
@Apache::uri, $foo; results in:
Modification of a read-only value attempted ...

the patch does not take into account the case if two threads were to
perl_destruct() and SvREFCNT_dec on a shared GV at the exact same time.
and readonly-ness is not complete (e.g. for GvIO).  but i think it's close
enough to ask if this approach is worth pursuing.  futher extesions could
included readonly/shared @ISA, $VERSION, etc., and perhaps a pragma to
enable the sharing as an alternative to using SvREADONLY_on() in .xs

Index: sv.c
===================================================================
RCS file: /usr/local/cvs_repository/perl-current-mirror/sv.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 sv.c
--- sv.c	2001/01/30 05:48:57	1.1.1.12
+++ sv.c	2001/01/31 05:38:59
@@ -7691,6 +7691,30 @@
 char *PL_watch_pvx;
 #endif
 
+#define GvCV_shareable(gv) \
+    (GvCV(gv) && CvXSUB(GvCV(gv)) && SvREADONLY(GvCV(gv)))
+
+#define GV_shareable(gv) \
+    GvGP(gv) && \
+    GvCV_shareable(gv)
+
+static SV *gv_share(pTHX_ SV *sstr)
+{
+    SV *dstr = sstr; /* he_dup() will SvREFCNT_inc() */
+    GV *gv = (GV*)dstr;
+    SV *sv = &PL_sv_no; /* just need SvREADONLY-ness */
+
+    /* write attempts will die with
+     * "Modification of a read-only value attempted"
+     */
+    GvSV(gv) = sv;
+    GvAV(gv) = (AV*)sv;
+    GvHV(gv) = (HV*)sv;
+    /* GvIO, GvFORM */
+
+    return dstr;
+}
+
 SV *
 Perl_sv_dup(pTHX_ SV *sstr)
 {
@@ -7823,6 +7847,16 @@
 	LvTYPE(dstr)	= LvTYPE(sstr);
 	break;
     case SVt_PVGV:
+      if (GV_shareable((GV*)sstr)) {
+          SV *share;
+          if ((share = gv_share(aTHX_ sstr))) {
+              del_SV(dstr);
+              dstr = share;
+              PerlIO_printf(Perl_debug_log, "sharing %s::%s\n",
+                            HvNAME(GvSTASH(dstr)), GvNAME(dstr));
+          }
+          return dstr;
+      }
 	SvANY(dstr)	= new_XPVGV();
 	SvCUR(dstr)	= SvCUR(sstr);
 	SvLEN(dstr)	= SvLEN(sstr);



Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About