Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: On timely destruction?

by Abigail-II (Bishop)
on Aug 28, 2002 at 13:14 UTC ( [id://193439]=note: print w/replies, xml ) Need Help??


in reply to On timely destruction?

Inside Out Objects, in combination with a class method that checks how many instances of an object there are:
package Test; my %attr; sub new {bless [] => shift} sub init {$attr {+shift} = undef} sub attr { my $self = shift; $attr {$self} = shift if @_; $attr {$self} } sub DESTROY { delete $attr {+shift} } sub HowMany {scalar keys %attr}
If you don't do timely destruction, HowMany will return the wrong value. This will be a disaster for programs that limit the number of instances that are allowed to be around.

However, it's not just the semantics you should worry about. Performance might depend on its as well. More than once I've written code where in the DESTROY method a file is closed (and hence, a lock on it is released). If the DESTROY no longer is timely, the semantics won't change - the program would still act correctly.

But the performance would no longer be acceptable, as other programs don't get their locks fast enough.

You can install block-exit handlers, including in your caller's block, so you don't have to play DESTROY games to get lexical exit actions.
That's nice of newly written perl6 programs. But what about perl5 programs running in a perl6 environment? Or just a perl5 module used from a perl6 program? Will they have timely DESTROY?

Allocation failure (for example running out of filehandles) will trigger a GC sweep and retry of the failing operation, so your program won't run out of things for lack of timely cleanup.
Could you elaborate on that? If program1 (not necessarely written in Perl) has an allocation failure because program2 (written in Perl) hasn't done a GC sweep yet, how's that going to trigger a GC sweep in program2?

I'm more concerned about the overal impact on the system a perl6 program is going to run on then the impact on the program itself.

Java's unpredictable GC is already giving lots of people a headache when dealing with long running Java programs. It would be a pity if Perl goes that way too.

Abigail

Replies are listed 'Best First'.
Re: Re: On timely destruction?
by Elian (Parson) on Aug 28, 2002 at 22:42 UTC
    If you don't do timely destruction, HowMany will return the wrong value.
    Well, no, not really. We'll return the right value, which is the number of not-dead objects. That the number is surprising to the programmer is arguably rather sub-optimal but not flat-out wrong. (Yes, I know I'm arguing twiddly bits here)

    The class will have the option of forcing a sweep for dead objects if it so chooses, so there would be a fallback. Yes, this is definitely sub-optimal, and is just a variant on the weak-ref problem. (i.e. a hack of sorts to get around implementation issues)

    However, it's not just the semantics you should worry about. Performance might depend on its as well. More than once I've written code where in the DESTROY method a file is closed (and hence, a lock on it is released). If the DESTROY no longer is timely, the semantics won't change - the program would still act correctly.

    But the performance would no longer be acceptable, as other programs don't get their locks fast enough.

    I'm not sure that's much of a problem. The delay in destruction should be on the order of milliseconds under most circumstances. If that's an unacceptable delay, then odds are something more explicit than relying on automatic destruction is in order.
    You can install block-exit handlers, including in your caller's block, so you don't have to play DESTROY games to get lexical exit actions.
    That's nice of newly written perl6 programs. But what about perl5 programs running in a perl6 environment? Or just a perl5 module used from a perl6 program? Will they have timely DESTROY?
    Perl 5 programs won't have as timely a DESTROY as they do running on the perl 5 engine. Optionally forcing DESTROY checks at block boundaries will be doable, and I suppose we can optionally force it at statement boundaries, though that will be slow.
    Allocation failure (for example running out of filehandles) will trigger a GC sweep and retry of the failing operation, so your program won't run out of things for lack of timely cleanup.
    Could you elaborate on that? If program1 (not necessarely written in Perl) has an allocation failure because program2 (written in Perl) hasn't done a GC sweep yet, how's that going to trigger a GC sweep in program2?
    This only applies within a running parrot program of course--we're not in a position to affect the behaviour of other programs. It's only when there's a potentially recoverable resource allocation within a program that we can do this. Locks, for example, can be tried in non-blocking mode and, if that fails, a GC sweep can be done and the lock retried in blocking mode to wait on other programs that might have it allocated. File open failures due to a lack of filehandles can similarly be tried, a GC run tried, then retried and only then throwing an exception if there are still no filehandles.
    Java's unpredictable GC is already giving lots of people a headache when dealing with long running Java programs. It would be a pity if Perl goes that way too.
    Could you elaborate on this? There are always tradeoffs when making choices, and cleaner/faster internals and no worries about circular garbage is the tradeoff for guaranteed destruction timing. If there are more serious ramifications, it'd be good to know so we can take steps to ameliorate them.
      If you don't do timely destruction, HowMany will return the wrong value.
      Well, no, not really. We'll return the right value, which is the number of not-dead objects. That the number is surprising to the programmer is arguably rather sub-optimal but not flat-out wrong. (Yes, I know I'm arguing twiddly bits here)
      I wouldn't call that twiddling of bits. You're redefining English. You ask for cases where the proposed implementation breaks a program. I give you an example of something that isn't at all contrived, and you dismiss it as "it's not broken, it just does something surprising". I'm glad the attitude of p5p isn't this way, any bug report could be dismissed this way.

      Why did you ask the question anyway?

      The class will have the option of forcing a sweep for dead objects if it so chooses, so there would be a fallback. Yes, this is definitely sub-optimal, and is just a variant on the weak-ref problem. (i.e. a hack of sorts to get around implementation issues)
      I don't like any implementation issues surfacing in the language. But it's certainly worse than the circular references problem you have with refcounting. Then when and whether or not your DESTROY method is called is predictable. It's properly defined when it's called, as soon as the last reference to it disappears. With the proposed implementation, when DESTROY is being called becomes unpredictable.
      #!/usr/bin/perl use strict; use warnings 'all'; package Foo; sub new { my ($class, $ref) = @_; bless [$ref] => $class; } sub DESTROY { my $self = shift; print $self -> [0] [-1], "\n"; } package main; my $ref = []; foreach my $c (qw /one two three four/) { push @$ref => $c; my $obj = Foo -> new ($ref); } print "Exit\n"; __END__ one two three four Exit
      But what will this do if DESTROY is being called at random times? What can, and what can't you do? Will DESTROY be like unsafe signal handlers?
      However, it's not just the semantics you should worry about. Performance might depend on its as well. More than once I've written code where in the DESTROY method a file is closed (and hence, a lock on it is released). If the DESTROY no longer is timely, the semantics won't change - the program would still act correctly.

      But the performance would no longer be acceptable, as other programs don't get their locks fast enough.

      I'm not sure that's much of a problem. The delay in destruction should be on the order of milliseconds under most circumstances. If that's an unacceptable delay, then odds are something more explicit than relying on automatic destruction is in order.
      Do you have anything to back up the "I think", "most circumstances" and "odds are"? If 5 out of 100 planes have a bomb on board, then odds are that you arrive safely, under most circumstances there's no bomb on board. But you won't see a huge rush in plane tickets.
      Perl 5 programs won't have as timely a DESTROY as they do running on the perl 5 engine. Optionally forcing DESTROY checks at block boundaries will be doable, and I suppose we can optionally force it at statement boundaries, though that will be slow.
      Ah "slow", the magic word that can stop anything. Refcounting is also slow, but that didn't stop Perl from being useful for 14 years. *Anything* is slow, for some value of slow. But the common behaviour apparently wasn't slow enough for people to not use OOP. In fact, it was remarkably succesful. Now, if perl6 will be so much slower than perl5 it has to let go of useful features just to keep up, I think we can do without perl6.
      Allocation failure (for example running out of filehandles) will trigger a GC sweep and retry of the failing operation, so your program won't run out of things for lack of timely cleanup.
      Could you elaborate on that? If program1 (not necessarely written in Perl) has an allocation failure because program2 (written in Perl) hasn't done a GC sweep yet, how's that going to trigger a GC sweep in program2?
      This only applies within a running parrot program of course--we're not in a position to affect the behaviour of other programs. It's only when there's a potentially recoverable resource allocation within a program that we can do this. Locks, for example, can be tried in non-blocking mode and, if that fails, a GC sweep can be done and the lock retried in blocking mode to wait on other programs that might have it allocated. File open failures due to a lack of filehandles can similarly be tried, a GC run tried, then retried and only then throwing an exception if there are still no filehandles.
      I understand all of that. But I've been using UNIX for almost 20 years, and I know that running just one task on a machine is an exceptional case. Programs have to compete for resources. Nice programs let resources go as soon as possible, and don't use more than necessary. Nice languages allow for nice programs to be written. C is a nice language. Perl is nice, although it gobbles up a lot of memory. Java isn't a nice language. And it looks like Perl6 is going to be further away from C, and closer to Java.
      Java's unpredictable GC is already giving lots of people a headache when dealing with long running Java programs. It would be a pity if Perl goes that way too.
      Could you elaborate on this? There are always tradeoffs when making choices, and cleaner/faster internals and no worries about circular garbage is the tradeoff for guaranteed destruction timing. If there are more serious ramifications, it'd be good to know so we can take steps to ameliorate them.
      Well, if you find my ramifications about unpredictability not enough, there isn't much left to discuss, is there?

      Abigail, who only seems more reasons not to use perl6.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://193439]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2024-03-28 11:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found