summaryrefslogtreecommitdiff
path: root/dump.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2013-03-11 11:42:32 +0000
committerNicholas Clark <nick@ccl4.org>2013-05-29 10:52:50 +0200
commit9faf471aadb0009c0def1e2e9ab174082632af3b (patch)
tree83cb48c21bb39e29bcc82690c0f5b8caefa47d8d /dump.c
parent99f57afc36ebadbe790958225afc2a70c73dd64a (diff)
downloadperl-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.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/dump.c b/dump.c
index 70ac48778a..93094a4ebc 100644
--- a/dump.c
+++ b/dump.c
@@ -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));