On Fri, Oct 06, 2006 at 02:23:41PM -0700, Jerry Hedden wrote:

> It's not the use of overload.pm that is still the issue.
> It's just that generating the Class=TYPE(0xADDR) string
> takes so much time.  Your patch puts stringification of
> overloaded and non-overloaded objects nearly on a par.
> However, both still pale in comparison to getting a TID:


Well, if stringification of references really needs to be as fast as possible
:-)

==== //depot/perl/sv.c#1302 - /home/nick/p4perl/perl/sv.c ====
--- /tmp/tmp.55500.0    Fri Oct  6 23:52:22 2006
+++ /home/nick/p4perl/perl/sv.c Fri Oct  6 23:42:10 2006
@@ -2743,17 +2743,38 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv,
                    return stringify_regexp(sv, mg, lp);
                } else {
                    const char *const typestr = sv_reftype(referent, 0);
+                   const STRLEN typelen = strlen(typestr);
+                   UV addr = PTR2UV(referent);
+                   char buffer[sizeof(UV) * 2 + 4];
+                   char *p = buffer + sizeof(buffer);
+                   const char *const buffer_end = p;
 
                    tsv = sv_newmortal();
                    if (SvOBJECT(referent)) {
-                       const char *const name = HvNAME_get(SvSTASH(referent));
-                       Perl_sv_setpvf(aTHX_ tsv, "%s=%s(0x%"UVxf")",
-                                      name ? name : "__ANON__" , typestr,
-                                      PTR2UV(referent));
+                       const HEK *const name = HvNAME_HEK(SvSTASH(referent));
+
+                       if (name) {
+                           sv_grow(tsv, HEK_LEN(name) + typelen + 5
+                                   + 2 * sizeof(UV));
+                           sv_setpvn(tsv, HEK_KEY(name), HEK_LEN(name));
+                           sv_catpvs(tsv, "=");
+                       } else {
+                           sv_setpvs(tsv, "__ANON__=");
+                       }
+                       sv_catpvn(tsv, typestr, typelen);
+                   } else {
+                       sv_grow(tsv, typelen + 4 + 2 * sizeof(UV));
+                       sv_setpv(tsv, typestr);
                    }
-                   else
-                       Perl_sv_setpvf(aTHX_ tsv, "%s(0x%"UVxf")", typestr,
-                                      PTR2UV(referent));
+                   *--p = ')';
+                   do {
+                       *--p = PL_hexdigit[addr & 15];
+                   } while (addr >>= 4);
+                   *--p = 'x';
+                   *--p = '0';
+                   *--p = '(';
+
+                   sv_catpvn(tsv, p, buffer_end - p);
                }
                if (lp)
                    *lp = SvCUR(tsv);

>          Rate  thr  obj  tid
>     thr 131/s   --  -2% -63%
>     obj 133/s   2%   -- -62%
>     tid 355/s 171% 166%   --

which gets me

     Rate  tid  thr  obj
tid 472/s   -- -13% -17%
thr 539/s  14%   --  -5%
obj 565/s  20%   5%   --


but I'm not sure if it's really worth making this change to sv_2pv_flags.

[Hmm, thinking about it further as I'm doing all the length calculations
explicitly I don't actually need a mortal SV for a scratch buffer. I could
just malloc() it directly, and use SAVEFREEPV() to free it later]

The moral seems to be that sprintf() derived formatters are slow. (At least
in C. In Perl sprintf, as one op, is faster than functionally equivalent
but more verbose Perl code).

Nicholas Clark

Reply via email to