jynx has asked for the wisdom of the Perl Monks concerning the following question:


i'm still new to OO in general, but i've always held certain beliefs about certain internals when doing it. Methinks it's time to get some clarity.

When an object gets instantiated, does the entire object get bootstrapped into memory? Or just the data? Or maybe some subset of the two?

It doesn't make sense that when you load an object all of the methods that are coded to go with the object get loaded for every instance of the object, but this has been my long-standing belief since that's what seemed to be the case in C++ and Java (where an object is a collection of data and methods).

If this were the case than if i have 1000 objects instantiated on a system, there are 1000 duplicate 'new' methods running around somewhere (ok, almost but not quite duplicate). There would also be 1000 copies of every other method described for the object. Obviously this seems ineffecient and bulky, not to mention a couple other problems. i want a 1000 different data structures, but not the baggage.

First of all please tell me i'm wrong.
Second, what does get kept in memory? How does some of this fit together?
Please feel free to refer me to a written source, i'm just looking for clarification.

jynx

Replies are listed 'Best First'.
Re: OO Baggage
by extremely (Priest) on Jan 16, 2001 at 03:43 UTC
    In short, an object is nothing more than a structure of data that has a "name". The compiler uses that name to find a set of subroutines, methods, that are assured of working with that structure. So, no, the methods aren't bootstrapped into memory once for each object, they are just subroutines that perl knows work well with a data structure.

    Honestly, all the jargon makes it a lot more mysterious than it really is but you need the jargon to talk about the subtleties of it all.

    Class
    a data structure blueprint and a set of subroutines that know how to work on that structure.
    Method
    a subroutine that knows how to work on a particular data structure.
    Object
    a chunk of real data that follows a blueprint and has a field in it that knows what Class it belongs to.
    Instantiate
    to use the blueprint in a Class to create a new, filled-out data structure.
    Call
    look up a subroutine by it's method name in the Class that the object belongs to.
    Inherit
    borrow general purpose routines from a "parent" that work on parts of your structure.

    HTH. There is a lot more to it but that is a sorta ok mapping to the world you are likely to have been working in. Others, help me out if I've "translated" that in some evil way that will only hurt him later, please.

    --
    $you = new YOU;
    honk() if $you->love(perl)

Re: OO Baggage
by MeowChow (Vicar) on Jan 16, 2001 at 03:50 UTC
    Great question, I used to wonder the same thing until I learned how C++ was implemented using vtables and whatnot. Basically, code only needs to be in memory once, and objects are just pointers to data structures that the interpreter/compiler knows how to deal with. Having a bunch of objects is basically the same thing as having a bunch of structures; the effective difference being that the the order of the function/method name and it's first parameter is swapped. Consider how in perl, the following two are almost identical:
    $obj->meth(@args); and meth($obj, @args);
    The relevent difference is that perl can work some magic knowing what $obj is blessed as, such as finding it's "meth" method in superclasses.

    So basically, don't worry about memory overhead: it's not an issue. Code performance is the more serious problem, because of the added indirection in OO architectures and added abstraction inherent in OO designs.

Re: OO Baggage
by Rudif (Hermit) on Jan 16, 2001 at 04:19 UTC
    "i have 1000 objects instantiated on a system ..."

    You get one copy of the class (package) code and 1000 copies of the object's data.

    Rudif
Re: OO Baggage
by lzcd (Pilgrim) on Jan 16, 2001 at 03:43 UTC
    Err... I'm no expert here but I think you'll find most OO implimentations (including C++,Java) tend to just keep a copy of the current objects instance 'stack' in memory (instead of the the entire code base as well).

    The only exception to this rule tends be be in the unavoidable areas such as serialization etc.

    I'm not saying that it doesn't tend to chew up memory but in these days of relatively cheap memory, I suspect most people have put a larger priority on running speed than memory usage.

    Not that I've ever done it in Perl, but you may wish to investigate techniques such as pooling and proxies if memory usage is a concern.

    Update: Forgot to mention that there must be at least one copy of the class/code for each different object type/class/thingie/doodad.... er see below. :)
Re: OO Baggage
by Lexicon (Chaplain) on Jan 16, 2001 at 10:14 UTC
    Here's what I remember from my Programming Languages class, although generalized because specifics are foggy and probably also language dependent. We studied Java when we did this: who knows how it applies to Perl (well, I bet someone here does, but whatever).
    // Some Pseudo Code of Class Foo Class Foo { Static int FooCount; float FooVariable; Static int FooInc() {return FooCount++;} float GetFooVar() {return this.FooVariable;} } Foo MyFoo = New Foo(3.14); Foo MyFoo2 = New Foo(6.02);

    We have Class Foo that has some static and normal variables. It also has static and normal methods. We instantiate this class in MyFoo with a New method and FooVariable = 3.14 and MyFoo2 with FooVariable = 6.02.

    The New method also increments a Static Variable FooCounter which keeps track of how many Foo's we have running around in memory space. It does this with the Static Method FooInc(). Finally, there is a method GetFooVar() which returns the FooVariable of a specific Foo.

    Now we have a memory block that contains the Foo Class along with its Static Variable FooCount = 2 and pointers to the Static Method FooInc() and normal Method GetFooVar().

    There are also two memory blocks that contain the data of the Foo (one for MyFoo and another for MyFoo2). These two memory blocks also contain pointers back to the Foo Class as well as a bit more information about the Foo class. Using the class pointer and some memory offset information, they can access the GetFooVar() method. They do not have memory offset info to the FooInc() method though, because that is static and can only be called on the Foo class itself. (Probably it would be Private of course and only callable by Foo itself, but it's still Static.)

    This is how I remember it, but no warantee or anything. It gets far more complex pretty quickly when you start adding things like inheritance or whatever, but I think this answers your question. Basically, one instance of Static information and methods, but each instance of the class will contain some pointer information for the class and each method it might need to call, so there will be a little extra bloat, but it should be trivial (a few bytes) compared to the size of even a single method.

    By all means, please correct any errors oh compiler writing types (I don't take that class till next year).

    -Lexicon

Re: OO Baggage
by coreolyn (Parson) on Jan 16, 2001 at 22:34 UTC

    A monk on a similar quest to my own. After all the reading on Perl OO I could get my hands on, (which went far to understanding the terminology and concepts), I found when I sat down to play, much of the information made the issue far more complex than necessary to learning and utilizing Perl OO code.

    Perl OO cannot be compared to Java as essentially you control the object, not a VM. This is much more fun but frought with hazards. I wish someone had provided the following code about two weeks ago, as Perl OO is much easier to understand and use from a minimalist approach rather than trying to grok all the issues at once.

    Use the following bench to rotate your code changes through Tiny.pm and NotSoTiny.pm. Every keystroke change becomes immesurably more important in OO and by focusing on the effects of each keystroke your basic Perl understanding and your grokking of Perl OO will grow with it.

    In the end the what where and how becomes mute, and it becomes just a variation of coding in Perl.

    package Tiny; # Filename Tiny.pm # The Worlds Smallest Perl Object use strict; sub new { return bless { }, shift; } 1; ------------------------------------------------------- package NotSoTiny; # Filename NotTiny.pm use strict; sub new { return bless { value => 'A value' }, shift; } sub get_value { return shift->{value}; } 1; ------------------------------------------------------ #! /usr/bin/perl -w #Filname: bench use Benchmark qw(timethese); # perl 5.6 has 'cmpthese' # which is very cool, and # much more informative # If you have 5.6 just # s/timethese/cmpthese/g use strict; use lib ('./'); use Tiny; use NotSoTiny; my ( $roll, @roll ); my $loop = 250000; # You will want this var up here to # Adjust itineratations to avoid # warnings ###### Preload Objs ################################### # Benchmark two ways one with pre constructed objs and # another without considering construction costs. my $TinyObjBase = Tiny->new(); my $NotTinyObj = NotSoTiny->new(); ###### SubRoutine Vars ################################# # To be completely fair do the same with the Vars for # the subroutines. my $TinySub; my $NotSoTinySub; ###### End Init ########### system("clear"); my $loops; for $loops ($loop) { timethese $loops, { ##### Subroutine Comparisons TinySubPreVar => sub { $TinySub = Tiny(); }, TinySubNewVar => sub { my $NewTinySub = Tiny(); }, NotSoTinySubPreVar => sub { $NotSoTinySub = NotSoTinySub(); }, NotSoTinySubNewVar => sub { my $NewNotSoTinySub = NotSoTinySub(); }, ##### Object Comparisons TinyObjReused => sub { $TinyObjBase; }, TinyObjNew => sub { my $NewTinyObj = Tiny->new(); }, NotSoTinyObjReused => sub { $TinySub = $NotTinyObj->get_value(); }, NotSoTinyObjNew => sub { my $NotSoTinyObjNew = NotSoTiny->new(); $TinySub = $NotSoTinyObjNew->get_value(); }, }; } sub Tiny { return; } sub NotSoTinySub { return 'A value'; }

    coreolyn