delete object

G

George Mpouras

I have create a class witht some properties and methods
I create a new object and do some stuff
At the end I call a custom method called $obj->Close();
the Close is like this

sub Close
{
my $self = shift;
my $class = ref $self || $self;
$class = __PACKAGE__ if $class eq '';
ref $self || die
......
$self = {};
undef $self;
}

Unfortunately after calling the Close the
use Data::Dumper; print Dumper($obj);
at my main program is still full of data . What I have to do inside the
module , so when I call the Close the $obj to be empty ?
 
W

Willem

George Mpouras wrote:
) I have create a class witht some properties and methods
) I create a new object and do some stuff
) At the end I call a custom method called $obj->Close();
) the Close is like this
)
) sub Close
) {
) my $self = shift;
) my $class = ref $self || $self;
) $class = __PACKAGE__ if $class eq '';
) ref $self || die
) .....
) $self = {};
) undef $self;
) }
)
) Unfortunately after calling the Close the
) use Data::Dumper; print Dumper($obj);
) at my main program is still full of data . What I have to do inside the
) module , so when I call the Close the $obj to be empty ?

This should work:

%$self = ();

But *why* do you want the $obj to be empty? There is no need to do that.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
T

Tim McDaniel

I have create a class witht some properties and methods
I create a new object and do some stuff
At the end I call a custom method called $obj->Close();
the Close is like this

sub Close
{
my $self = shift;
my $class = ref $self || $self;
$class = __PACKAGE__ if $class eq '';
ref $self || die
.....
$self = {};
undef $self;
}

Almost everybody finds it helpful to indent their code inside {...}.
Unfortunately after calling the Close the
use Data::Dumper; print Dumper($obj);
at my main program is still full of data . What I have to do inside
the module , so when I call the Close the $obj to be empty ?

I want to echo Willem's comment that
%$self = ();
should work.

The reason why:

{...} in a value context produces a reference to a hash table. When
you assign references like "$b = Frog->new()", $b points to the hash
table in memory. If you later do "$c = $b", $c and $b point to the
same area. If you later do "$b = {}", then $b points to a different
(empty) hash table, but $c still points to the old one.

But for a different thing: if you manipulate what $b or $c point to,
then using $b and $c see the effect.
$c = $b;
$b->{'trireme'} = 3;
then
$c->{'trireme'}
evaluates to 3 also.

That is why
$self = {};
undef $self;
do nothing to $obj. They make $self point to a new empty hash table,
or make it undef, which does not change $obj.

That is why
%$self = ();
should work. That does not change $self. It changes what $self
points to. Since $obj points to the same thing, it also see the
changes.

I also wonder a little bit why you worry about this. When Perl sees
that an object has no more references to it, then it knows that it is
impossible for that object to ever be used again, and it cleans up the
space when it thinks it's convenient. That is usually good enough.
Certainly the other way, making the programmer clean up old objects,
has been demonstrated again and again to be a lot of trouble and hard
to do correctly in all cases. In almost all cases, you just want Perl
to do the cleanup reliably for you ... unless there is some other
reason.
 
T

Tim McDaniel

Instead, write a DESTROY method (if you need one)

To expand on that: my understanding is that a DESTROY method is very
rarely needed -- for example, if there's an external connection that
must be closed cleanly. If all you are worried about is internal
storage, like the contents of a hash table, then I don't know of a
reason to have a DESTROY method: I think it will be called only when
there are no more references to the object, so as long as $obj still
has a reference to the object, it won't get called.
and then just

undef $obj;

when you want to destroy it.

Note that that's in the caller, getting rid of the more persistent
reference to the data.
Most of the time you don't need to: you can just let it go out of
scope.

That's a short form of what I wrote.
 
R

Rainer Weikusat

Ben Morrow said:
Quoth (e-mail address removed):

You also need DESTROY when the object has internal circular references,
since they won't be collected until the cycle is explicitly broken.

Provided that 'an object' has the only reference to some self-referential
structure, the DESTROY method can be used to 'break the circle' so
that the affected objects are destroyed, too. But that's rare enough
to be considerde coincedence.
Nowadays you can often avoid this by using weakrefs, though it's not
always easy to pick the right ref to weaken. (This is a consequence of
Perl using reference counts rather than a proper garbage collector.)

As a consequence of the Perl using proper garbage collection, instead
of something designed in an academic ivory tower in order to design
academic ivory tower problems which rarely occur in practice, it is
usable for for something other than academic ivory navel-gazing, since
this usually involves dealing with all kinds of 'external objects'
beyond the reach of the garbage ivory academics collector and this
'dealing with' requires programmer control over both initialization
and finalization, even if this 'external object' is something as
mundane as a file (fans of 'proper garbage collection' usually
maintain that it is much properer when it solely deals with memory
while all other resources are to be managed with explicit code). There
also other, nice side effects, eg, the memory requirements of Perl
compared 'something proper' (such as Java) are really frugal because
memory can be reused as soon as it became unused, not as soon as there
really is no other choice. This is, of course, not really feature
because it doesn't help Oracle selling high-end minicomputers ...
and so on.

Is there any kind of Kool-Aid on this planet you didn't drink?
[just wondering ...]
 
G

George Mpouras

This should work:

%$self = ();

But *why* do you want the $obj to be empty? There is no need to do that.

it works partially . $obj is still a blessed object;
There is a need for this. What I am doing at the main script is complex and
objects are looking at each other status.
What I decide to do is


sub Close {
....
%{$self} = ();
return {};
}


and at the calling script
$obj = $obj->Close;
 
G

George Mpouras

Ο "Ben Morrow" έγÏαψε στο μήνυμα


What on *Earth* are you doing here? Do you know aht any of this is
supposed to do?


Let me think, log(x**7)**(1/2) - 3 maybe ?
 
G

George Mpouras

That is why
$self = {};
undef $self;
do nothing to $obj. They make $self point to a new empty hash table,
or make it undef, which does not change $obj.

That is why
%$self = ();
should work. That does not change $self. It changes what $self
points to. Since $obj points to the same thing, it also see the
changes.


Very explanatory, thanks Tim.
 
T

Tim McDaniel

This should work:

%$self = ();

But *why* do you want the $obj to be empty? There is no need to do that.

it works partially . $obj is still a blessed object;
There is a need for this. What I am doing at the main script is complex and
objects are looking at each other status.
What I decide to do is

sub Close {
...
%{$self} = ();
return {};
}

and at the calling script
$obj = $obj->Close;

By "looking at each other's status", do you mean that other objects
have references to the same object? If not, and if you're willing to
change the caller, maybe you should be able to do
undef $obj;
and forget about doing anything else.
 
G

George Mpouras

Ï "Tim McDaniel" Ýãñáøå óôï ìÞíõìá
This should work:

%$self = ();

But *why* do you want the $obj to be empty? There is no need to do that.

it works partially . $obj is still a blessed object;
There is a need for this. What I am doing at the main script is complex and
objects are looking at each other status.
What I decide to do is

sub Close {
...
%{$self} = ();
return {};
}

and at the calling script
$obj = $obj->Close;

By "looking at each other's status", do you mean that other objects
have references to the same object? If not, and if you're willing to
change the caller, maybe you should be able to do
undef $obj;
and forget about doing anything else.


There are no cross references , only simple read properties between objects.
Yes undef $obj is enough after all. but I would like also to free some
memory !
 
T

Tim McDaniel

Yes undef $obj is enough after all. but I would like also to free
some memory !

I think that you did not understand the previous messages on garbage
collection. After you remove the last reference to some data, Perl
will free that memory automatically at some time. Also, unless there
is MUCH MUCH memory in an object, you should not bother to free it
yourself.
 
G

George Mpouras

I understand about garbage collector, theory is good but practice is
different.
try this command to check memory usage by perl
watch "ps -e -orss=,args= | sort -b -k1,1n | pr -TW$COLUMNS | grep -i perl"

my @array;
push @array, $_ foreach 1 .. 20_000_000;

# if do nothing 816136 perl mem.pl
#undef @array; # with this 553996 perl mem.pl
#@array = (); # with this 816140 perl mem.pl

print "press any key to continue"; getc;
 
G

George Mpouras

Perl will free it *immediately*, including calling ->DESTROY if it is
defined.

while your program is running it will not free a bit
 
R

Rainer Weikusat

Ben Morrow said:
It's not at all rare: for instance, XML::Twig has circular refs, and a
->dispose method to break them.

I'm writing about using Perl for real-world problems, specifically,
the real-world problems I used it for during the last 15 years or so,
and there, circular references where a rare occurence. For obvious
reasons, I can't comment on what people designed which
self-referential datastructures for what reasons when implenting 1
bazillion of 'generally useful' (aka 'generally useless') code
libraries available for download from server a.b.c.d.
When implementing large systems, Perl's refcounting causes problems in
practice.

Problems which occur in 'large systems' are more often than not
problems occuring because of 'the large system' which should usually
rather be structured into independent components interacting with each
other. Also, the interesting question is 'what precisely is a large
system'? Eg, it is a safe assumption that a monolithic OS kernel is
necessarily a larger 'integrated system' than most sensibly designed
applications. Yet, reference counting is (and - AFAIK - has always
been) the memory management strategy of choice for kernels (BTW, the
'large system' is another classic ivory-tower fad -- if people think
they need to implement 'large systems' then they have to find a way to
solve the problems related to that. And that they *believe* to need
something in order to solve some problem they encountered [or believe
they will encounter] doesn't turn that something into a categorical
imperative).

But this is more or less an aside: I two useful properties of
referencing: It is deterministic and it can be used for all kinds of
resources, not just memory. The first one is a conditio sine qua non
for the more complicated problems I have to deal with because of the
necessity to conform to 'some kind of protocol' wrt dealing with
'external entities' such as database servers. And the second makes my
(or anyone's) life much easier because there's generally no need to
worry about explicit resource management -- an object dies as soon as
it isn't used anymore and code tearing down whatever needs to be torn
down, insofar not already included in Perl, will run automatically
whenever this happens. A third one would be that it is possible to
have live Perl objects which are temporarily not reachable from
within the program, eg, send a pointer to some object through a kernel
IPC channel to another part of the program, for instance, some
top-level event loop, and ensure that it isn't deallocated by
increasing its reference count. This can also be very convenient.
Internally, they cause *huge* problems: a large number of bugs
in perl turn out to be caused by a refcount which got too high or too
low somewhere.

100% of all bugs in the perl implementation come from buggy code which
happens to be part of it. That's not exactly surprising ...
 
R

Randal L. Schwartz

Ben> When implementing large systems, Perl's refcounting causes problems in
Ben> practice. Internally, they cause *huge* problems: a large number of bugs
Ben> in perl turn out to be caused by a refcount which got too high or too
Ben> low somewhere.

This is FUD. The only time you need to worry about refcounts is when
you write circular-reference data structures. And when you're doing
that, you know you are doing that.

Just keep your data as a DAG, not a willy-nilly criss-cross, and it'll
be easier to test *and* maintain.
 
X

Xho Jingleheimerschmidt

When implementing large systems, Perl's refcounting causes problems in
practice.

While I don't doubt that that is true, I've run into more problems with
Java's garbage collector than I have with Perl's, and I've used Perl far
far more.
Internally, they cause *huge* problems: a large number of bugs
in perl turn out to be caused by a refcount which got too high or too
low somewhere.

Well, I'm sure mistakes can be made in the implementation of any technique.

Xho
 
I

Ivan Shmakov

George Mpouras said:
I understand about garbage collector, theory is good but practice is
different.
try this command to check memory usage by perl
watch "ps -e -orss=,args= | sort -b -k1,1n | pr -TW$COLUMNS | grep -i perl"

Indeed, Perl doesn't seem to free all the space immediately.

#!/usr/bin/perl

# 1652 perl ...
BEGIN { getc; }
my @array = (1 .. (1 << 22));
# 331360 perl ...
# huh? 80 bytes per an integer?
getc;
print $#array, "\n"; # prints: 4194303
undef @array;
# 298640 perl ...
getc;

[...]
 
R

Rainer Weikusat

George Mpouras said:
I understand about garbage collector, theory is good but practice is
different.
try this command to check memory usage by perl
watch "ps -e -orss=,args= | sort -b -k1,1n | pr -TW$COLUMNS | grep -i perl"

In the given context, this is a nonsense-test: The resident segment
size is the amount of physical memory the kernel has presently
allocated to this process. This number is going to be smaller than or
equal the amount of virtual memory allocated to this process (code +
stack + statically allocated data + 'dynamically allocated memory',
VSZ). The latter may change if the process choses to 'shrink' the
used portion of its virtual address space, eg, by munmapping some
area/ file which was mmapped before or by lowering the 'break' (=>
brk(2), sbrk(2)). Usually, this doesn't happen because userspace
memory allocators will keep 'free' virtual memory they have already
allocated in order to reuse it for future userspace memory allocation
requests (there's no good reason for doing otherwise because, except
on pathologically configured systems ["I wanted to kill the swap
because it was there!!"], the kernel will redistribute physical memory
among itself and other processes as it sees fit/ as the need arises).

In addition to this, perl will also usually keep memory that was
already allocated for some variable attached to that variable in case
it might again be needed in future, cf

----------
use Devel::peek;

@a = 0 .. 1000000;
@a = ();
Dump(\@a);

$s = join('', 0 .. 100000);
$s = '';
Dump(\$s);
----------
 
R

Rainer Weikusat

Ben Morrow said:
Quoth Xho Jingleheimerschmidt said:
On 04/25/2012 02:02 PM, Ben Morrow wrote:
[...]
Well, I'm sure mistakes can be made in the implementation of any technique.

I'm not just talking about mistakes: if that was the only issue, they'd
have been found and fixed. The problem is that perl's internal data
structures consists of a rather complicated graph of objects (well,
structs), with necessary cross-references all over the place, and with
enormously varying lifetimes. The perl core is, in fact, a good example
of a system where Randal's suggestion to just keep your data in a DAG is
not practical.

Naively counting lines of code, perl 5.10.1 figures as 574,000 and the
core of Linux 2.6.36.4 (without architecture specific code and device
drivers) has 2,132,318 which is about 3.72 times the size of the
former (and the count is biased in favor of perl because it didn't
cherry-pick anything there). So, how come that something which causes
so 'huge problems' in a relatively small 'system' that some people
consider it unworkable apparently works for a much larger system which
is additionally forced to 'survive' in a signficantly less friendly
environment? Could this perhaps be an instance of some (few) people
confusing "we can't do it" with "it can't be done" (or, not entirely
unlikely "they surely won't be able to do it" with "it is impossible"?)
For example, a bug which was fixed in 5.14 but before that will segfault
perl, probably back as far as 5.000:

perl -MDevel::peek -e'my $x = sub { 1 };
delete $main::{__ANON__};
Dump $x;
'

This segfaults because the sub holds a pointer to its glob, in this case
*__ANON__; but this pointer isn't refcounted, because (at least in the
named sub case) the glob also holds a pointer to the sub, so there would
be a cycle.

Nope. This isn't refcounted because this would be pointless in case of
a named sub since the glob already holds a refcounted pointer to the
sub. For obvious reasons, a mechanism designed based on the assumption
that there will always an 1:1 mapping between different kinds of
objects can't just be 'extended' to the 1:n case without changes. Why
does an anonymous sub have to have a pointer to a glob with a name in
the symbol table to begin with? Minus "this happened to be the fastest
way to tack it onto the existing code" of course? If this is a magic
glob, why is it possible to delete from Perl code? Or why isn't this
simply documented as 'the glob .... is used internally by perl and
Perl code must not delete it'? Lastly, which actually useful
functionally is provided by this example that is supposed to justify
dumping other useful functionality?
 
P

Peter J. Holzer

Perl will free it *immediately*, including calling ->DESTROY if it is
defined.

while your program is running it will not free a bit

That's not true.

Perl will call free() immediately (in most cases - there are some cases
where it keeps the memory because it expects to need it again soon).

But what free does with the memory depends on the implementation of the
malloc library. In the case of the GNU library the rules are (somewhat
simplified):

* Small objects (up to 128 kB) objects are allocated from the "heap" -
a contiguous memory area just after the data segment. The heap can
grow (if there is not enough unused memory in it) or shrink (if there
is unused memory at the end), but it is always contiguous. If there
are 3 MB of unused memory in the middle of it, that memory can not be
returned to the OS. (But that memory is of course available for
future malloc calls and the heap will only grow again after you've
filled it up).

* Larger objects are allocated individually via mmap. Because they have
been individually requested from the OS, they can be (and are)
individually returned to the OS.

Most memory allocations that perl makes (SVs, strings, pads, ...) are
small - they come from the heap and when they are freed they go back to
the heap - they will be reused when perl needs more memory again, but
the perl process won't shrink (unless you just happened to free enough
memory at the end of the heap). But long strings and large arrays and
hashes (only the array or hash itself, not its elements) come directly
from the OS and will be returned to it immediately. So if those are
freed the process does shrink.

Other malloc implementations may differ.

But the important point is that this is a function of the underlying
malloc library, not the perl interpreter, and as a Perl programmer you
have no control over that. The perl interpreter just calls free, whether
you just let the object go out of scope or you called undef. The malloc
library then decides what to do with the chunk of memory you just
returned to it. The code you posted earlies almost certainly makes no
difference, the result is just the same as if you just removed the last
reference to the object.

hp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,019
Latest member
RoxannaSta

Latest Threads

Top