8

In response to Aaronaught's response to the question at:

Can't I just use all static methods?

Isn't less memory used for a static method? I am under the impression that each object instance carries around its own executable version of a non-static member function.

Regardless of how much overhead is involved in calling a static method, regardless of poor OO design, and possible headaches down the road, doesn't it use less memory at runtime?

Here is an example:

I make a vector of zero-initialized objects. Each object contains one piece of data (a triangle consisting of nine double's). Each object is populated in sequence from data read from a .stl file. Only one static method is needed. Proper OO design dictates that a method dealing with the the data directly should be distributed to each object. Here is the standard OO solution:

foreach(obj in vec) {
  obj.readFromFile(fileName);
}

Each obj carries readFromFile's compiled code alongside the data!

Memory is more of a concern than performance in this case, and there is a LOT of data on a constrained system.

Solutions:

  1. Namespace method (great for C++ but not possible in Java)
  2. One static method in obj's class. Executable code is kept in one place at runtime. There is a small overhead to call the method.
  3. A parent class from which obj is derived, which contains the private method readFromFile. Call with super.callPrivateMethod() which calls readFromFile. Messy, and still some memory overhead in each object.
  4. Implement readFromFile outside obj's scope, so in vec's class or in the calling class. This, in my opinion, breaks data encapsulation.

I realize for large amounts of data one explicit object for each triangle is not the best approach. This is only an example.

  • 7
    In what language are you thinking that the code is duplicated for each instance? This doesn't happen in Java, C#, C++. – joshp Jan 3 '16 at 4:22
  • 2
    Well, it might happen with some dynamic language in its infancy, or as a side effect of abused reflection. But in general, no, a Byte isn't going to be much larger than the byte it contains. – Matthew Mark Miller Jan 3 '16 at 6:37
  • 1
    The only language I know of where you could get this memory-wasting behavior is Javascript, but even then you'd have to completely fail at prototypal OO to do it. What you're supposed to do in JS is put (both static and non-static) methods on the prototype object, so that all objects inheriting from that prototype will share that one function without any duplication. – Ixrec Jan 3 '16 at 13:27
  • 2
    Have you considered writing a small program that creates thousands of such objects and doing the measurements yourself? – Bryan Oakley Jan 3 '16 at 13:51
  • 1
    Ins't the answer to every OO related question: Dependency Injection? If you're bothered about the memory overhead you could just design a "saver" object of which you make one instance, that can be injected.... – Pieter B Jan 3 '16 at 14:28
18

Methods are not stored on a per-instance basis, even with virtual methods. They're stored in a single memory location, and they only "know" which object they belong to because the this pointer is passed when you call them.

The only extra memory required in C++ is if you're using virtual methods, which require a single extra pointer per instance to point at the virtual method table (in Java of course you always have a base class with virtual methods, Object, so it's unavoidable).

If it worked the way you described, OO languages would not be very popular! Feel free to add as many methods as you need to your objects. It won't affect their memory usage.

  • There is also a per-virtual-method overhead for each class. And Java is virtual by default... – Deduplicator Jan 3 '16 at 5:58
  • 1
    @Deduplicator: That is right, but you can also argue that there is an overhead for having functions/methods in the first place. Each function takes up memory and a virtual function takes a really tiny bit more (around 4 bytes). – Bart van Ingen Schenau Jan 3 '16 at 9:51
  • @BartvanIngenSchenau Or 8 bytes, and for each derived class again. Though both estimates are very much underestimating the cost in Java... – Deduplicator Jan 3 '16 at 10:54
  • 3
    @Deduplicator Still, that cost is per class (and per derived class), not per instance. – Craig Jan 3 '16 at 20:59
7

Regardless of how much overhead is involved in calling a static method, regardless of poor OO design, and possible headaches down the road, doesn't it use less memory at runtime?

This is rather complicated, but I would say "mostly no".

2

A method should be "static" (many languages use the term "class method" which is much better) if it doesn't refer to an instance of the class. It should be an instance method if it refers to an instance of the class.

Making a design decision based on the vague possibility of some memory savings instead of the proper use of class methods and instance methods is a very, very, very bad idea.

  • 2
    Good advice, but doesn't actually answer the question. – JacquesB Jan 4 '16 at 11:41
  • 1
    With the strong assumption that this is an XY question, it does. – gnasher729 Jan 4 '16 at 16:26
1

In principle, there's only one copy of the code, whether it's static member functions or not:

  • In C++ you can easily verify this by looking at the assembler list of the generated code.
  • I'm not Java expert, but from the JNI specification you can deduce it's the same logic: you can fetch a single reference to a function and call it many times for different objects (passing it a class reference as argument, as well as the object reference if it's not a static method).

Using a static or a non-static function will hence not change the memory footprint.

There is in reality a very very small difference, both in the code generated as well as in the memory consumed on the stack during the execution time of the function:

  • A call to the non-static function requires to pass a reference/pointer to the object on which the function/method is applied. This requires usually an additional push and a pop instructions in the calling sequence.
  • A call to a static function doesn't require this overhead.

But this is truly negligible: we are speaking of one or two machine instructions more or less compared to the full code. So it's definitively not something to worry about.

The stack consumption difference at run-time is limited to the time of the execution of the function, to the size of a pointer. This is also negligible, unless you are thinking of a a function called recursively a huge number of times (several millions of time).

So in conclusion, I fully share gnasher729 opinion: premature optimization is the root of all evil. If the function is independent of the object make it static and that should be the only criteria.

  • I believe the C++ compiler might avoid passing the reference to this, if it is not used in the function. In Java probably JIT could do this. – Oliv Mar 16 '16 at 6:10
0

It is easy to focus on things like optimizing memory usage or reducing lines of code but when you start having to maintain programs that people use/break and other programmers add functionality to...and possibly introduce bugs...not that your original program could possibly have bugs that made it past testing you will see that focusing on readability/maintainablility of the code may be more important. I could make a high speed bit array to track a series of data points but unless I wrapped that bit array in an object with understandable accessors the next programmer to touch that code will probably not use it, replace it or do some hideous witchcraft to it.

Not the answer you're looking for? Browse other questions tagged or ask your own question.