--- /dev/null
+use strictures;
+use Devel::Dwarn;
+
+use Devel::MAT::Dumpfile;
+
+my ($sv_counts, $svmap, $seentypes, $refholders );
+
+sub ha { sprintf '0x%x', $_[0] }
+
+for my $dmp (qw(dump_200356 dump_300033)) {
+ my $d = Devel::MAT::Dumpfile->load($dmp);
+
+ Ddie [ $d->sv_at( 0x3d1e370 )->values ];
+
+ for my $sv ($d->heap) {
+ next unless $sv->type eq 'SCALAR' and ! grep { defined $sv->$_ } qw(qq_pv pv pvlen iv uv nv ourstash);
+ $sv_counts->{join "\0", map { (defined $sv->$_) ? $sv->$_ : 'UNDEF' } (qw(qq_pv pv pvlen iv uv nv ourstash))}{$dmp}++;
+ $svmap->{$dmp}{ha $sv->addr} = { sv => $sv };
+ }
+
+ for my $sv ($d->heap) {
+ for ( values %{ {$sv->outrefs_strong} } ) {
+ if (my $slot = $svmap->{$dmp}{ha $_->addr}) {
+ push @{$slot->{refs}}, $sv;
+ $slot->{reftypes}{$sv->type}++;
+ }
+ }
+ }
+
+
+
+ for my $addr ( keys %{$svmap->{$dmp}}) {
+ my $slot = $svmap->{$dmp}{$addr};
+ delete $svmap->{$dmp}{$addr} if $slot->{sv}->refcnt != scalar @{ $slot->{refs} || [] };
+
+ my $refsummary = join ":", map { $_ => $slot->{reftypes}{$_} } sort keys %{$slot->{reftypes}};
+
+ if ($refsummary eq 'HASH:1') {
+ $seentypes->{$dmp}{$refsummary}++;
+
+ $refholders->{$dmp}{$slot->{refs}[0]->desc_addr}++;
+ }
+ else {
+ delete $svmap->{$dmp}{$addr};
+ }
+ }
+
+# for my $reflist (values %{$refmap->{$dmp}}) {
+# next unless $reflist;
+# my $cnts;
+# $cnts->{$_->type}++ for @$reflist;
+# Ddie $cnts;
+# }
+
+# local $Data::Dumper::Maxdepth = 3;
+# Ddie $refmap;
+}
+
+for (keys %$sv_counts) {
+ my ($l, $r) = values %{$sv_counts->{$_}};
+ delete $sv_counts->{$_} if ( ($l||0) == ($r||0) );
+}
+
+Dwarn [$sv_counts, $seentypes, $refholders ];
+
# check that "phantom-chaining" works - we never lose track of the original $schema
# and have access to the entire tree without leaking anything
-{
+while (1) {
my $phantom;
for (
- sub { DBICTest->init_schema( sqlite_use_file => 0 ) },
- sub { shift->source('Artist') },
- sub { shift->resultset },
- sub { shift->result_source },
- sub { shift->schema },
- sub { shift->resultset('Artist') },
- sub { shift->find_or_create({ name => 'detachable' }) },
- sub { shift->result_source },
- sub { shift->schema },
- sub { shift->clone },
- sub { shift->resultset('CD') },
- sub { shift->next },
- sub { shift->artist },
- sub { shift->search_related('cds') },
- sub { shift->next },
- sub { shift->search_related('artist') },
- sub { shift->result_source },
- sub { shift->resultset },
- sub { shift->create({ name => 'detached' }) },
- sub { shift->update({ name => 'reattached' }) },
- sub { shift->discard_changes },
- sub { shift->delete },
- sub { shift->insert },
+ sub { DBICTest->init_schema( sqlite_use_file => 0, no_deploy => 1 ) },
+# sub { shift->source('Artist') },
+# sub { shift->resultset },
+# sub { shift->result_source },
+# sub { shift->schema },
+# sub { shift->resultset('Artist') },
+# sub { shift->find_or_create({ name => 'detachable' }) },
+# sub { shift->result_source },
+# sub { shift->schema },
+# sub { shift->clone },
+# sub { shift->resultset('CD') },
+# sub { shift->next },
+# sub { shift->artist },
+# sub { shift->search_related('cds') },
+# sub { shift->next },
+# sub { shift->search_related('artist') },
+# sub { shift->result_source },
+# sub { shift->resultset },
+# sub { shift->create({ name => 'detached' }) },
+# sub { shift->update({ name => 'reattached' }) },
+# sub { shift->discard_changes },
+# sub { shift->delete },
+# sub { shift->insert },
) {
$phantom = populate_weakregistry ( $weak_registry, scalar $_->($phantom) );
}
- ok( $phantom->in_storage, 'Properly deleted/reinserted' );
- is( $phantom->name, 'reattached', 'Still correct name' );
+# ok( $phantom->in_storage, 'Properly deleted/reinserted' );
+# is( $phantom->name, 'reattached', 'Still correct name' );
}
# Naturally we have some exceptions
SKIP_SCALAR_REFS => ( $] > 5.017 ) ? 1 : 0,
};
+use Devel::MAT::Dumper -max_string => -1;
+
use base 'Exporter';
our @EXPORT_OK = qw(populate_weakregistry assert_empty_weakregistry hrefaddr visit_refs);
;
}
+warn "\nPID $$\n";
+
+my ($cycle_cnt, $max, $dumpnext) = (0, 0);
sub populate_weakregistry {
my ($weak_registry, $target, $note) = @_;
for my $reg (values %reg_of_regs) {
(defined $reg->{$_}{weakref}) or delete $reg->{$_}
for keys %$reg;
+
+ $max = scalar keys %$reg if $max < scalar keys %$reg;
}
# FIXME/INVESTIGATE - something fishy is going on with refs to plain
$weak_registry->{$refaddr}{slot_names}{$note} = 1;
}
+ $max = 0 if $cycle_cnt == 8000;
+ $dumpnext = 1 unless ( ++$cycle_cnt % 100_000 );
+ unless (++$cycle_cnt % 10_000) {
+ if (-f "/proc/$$/stat") {
+ my $proc_stat = do { local (@ARGV, $/) = "/proc/$$/stat"; <> };
+ my ($vsz) = map { $_ / 1024 }
+ (split (/\s+/, $proc_stat))[-22]; # go backwards because the %s of the pr
+
+ printf STDERR "#\n# VSIZE:%dKiB\n", $vsz
+
+ }
+ }
+
+# if ($dumpnext and ( (scalar keys %$weak_registry) == $max )) {
+# undef $dumpnext;
+# Devel::MAT::Dumper::dump( "/tmp/dump_$cycle_cnt" );
+# exit if $cycle_cnt >= 900_000;
+# }
+
$target;
}