in reply to Space taken by a coderef

Good questions, but I'm not convinced of the practical utility. What's on your mind?
  1. That depends. You can look at the definition of the xpvcv struct in cv.h in the Perl sources for the basic information any subroutine (anonymous or not) has to carry around. Of course, a reference to a subroutine is just a scalar, and takes as much memory as any other reference.
  2. Yes, the number of operations in the function and the pads it uses all eat up a little bit of memory.
  3. Yes, anything that you'd think costs memory probably does. :)
  4. I believe so, based on the existence of some funky closure-like bugs, but I'm not an authority on the subject. I do know that it's reused on subsequent subroutine calls, if possible, to avoid the malloc-free cycle. I would imagine recursion has its own opportunities and challenges for optimizations.

Replies are listed 'Best First'.
Re: Re: Space taken by a coderef
by dragonchild (Archbishop) on Jan 18, 2002 at 22:31 UTC
    I'm not sure there is practical utility. The first thing is that closures provide "hard encapsulation", where the only way to the internals of an object is through the interface. This comes at a small CPU hit, naturally.

    My immediate thought is for flyweight objects that take more than one scalar's worth of info. Instead of using class-level parallel arrays to keep the info, I was thinking that, maybe, closures would be more memory-efficient. (This is over arrays or hashes.)

    Now, yes, I know that optimizing for memory isn't necessarily a good thing, especially this early in the game. But, I just want to keep my options open and see what the comparison is.

    An example of what I'm talking about would be:

    sub new { my $class = shift; return undef if ref $class; my ($first, $second) = @_; my $self = sub { my $var = shift; my ($mode, $newval) = @_; if ($var == 0) { return $mode ? $first = $newval : $first; } elsif ($var == 1) { return $mode ? $second = $newval : $second; } return undef; }; bless $self, $class; return $self; }

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Ahh, I see. In this case, Perl compiles the closure once and only needs one copy of the optree. It only has to attach to the lexical scope once for each unique closure created, so you'll have the cost of a scratchpad that holds $first and $second, as well as the cost of the lexical variables within the closure.

      It wouldn't surprise me if this were slightly more efficient than a hash, but you'd probably need to get up above five or six member variables before it pays off. You'll save a little bit on accessors, though, but that's probably just the cost of the optrees, and you can avoid that if you're clever.

        The cost of the lexicals within the closure (and the operations of assigning to them) can be avoided by using direct access to @_. *shrugs*

        How would I avoid the cost on accessors? What exactly is this optree you're talking about? Can I affect the optree after creating the closure?

        ------
        We are the carpenters and bricklayers of the Information Age.

        Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.