diff options
author | Nicholas Clark <nick@ccl4.org> | 2013-03-11 11:42:32 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2013-05-29 10:52:50 +0200 |
commit | 9faf471aadb0009c0def1e2e9ab174082632af3b (patch) | |
tree | 83cb48c21bb39e29bcc82690c0f5b8caefa47d8d /dump.c | |
parent | 99f57afc36ebadbe790958225afc2a70c73dd64a (diff) | |
download | perl-9faf471aadb0009c0def1e2e9ab174082632af3b.tar.gz |
Cache HvFILL() for larger hashes, and update on insertion/deletion.
This avoids HvFILL() being O(n) for large n on large hashes, but also avoids
storing the value of HvFILL() in smaller hashes (ie a memory overhead on
every single object built using a hash.)
Diffstat (limited to 'dump.c')
-rw-r--r-- | dump.c | 25 |
1 files changed, 24 insertions, 1 deletions
@@ -1803,7 +1803,30 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo } PerlIO_putc(file, '\n'); Perl_dump_indent(aTHX_ level, file, " KEYS = %"IVdf"\n", (IV)HvUSEDKEYS(sv)); - Perl_dump_indent(aTHX_ level, file, " FILL = %"IVdf"\n", (IV)HvFILL(sv)); + { + STRLEN count = 0; + HE **ents = HvARRAY(sv); + + if (ents) { + HE *const *const last = ents + HvMAX(sv); + count = last + 1 - ents; + + do { + if (!*ents) + --count; + } while (++ents <= last); + } + + if (SvOOK(sv)) { + struct xpvhv_aux *const aux = HvAUX(sv); + Perl_dump_indent(aTHX_ level, file, " FILL = %"UVuf + " (cached = %"UVuf")\n", + (UV)count, (UV)aux->xhv_fill_lazy); + } else { + Perl_dump_indent(aTHX_ level, file, " FILL = %"UVuf"\n", + (UV)count); + } + } Perl_dump_indent(aTHX_ level, file, " MAX = %"IVdf"\n", (IV)HvMAX(sv)); if (SvOOK(sv)) { Perl_dump_indent(aTHX_ level, file, " RITER = %"IVdf"\n", (IV)HvRITER_get(sv)); |