views:

601

answers:

2

Considering internal memory usage

input = web_service.FullCompanyListChunksGet(x, ChunkSize);
ReadXML(input);

should take the same memory as

ReadXML(web_service.FullCompanyListChunksGet(x, ChunkSize));

Doesn't it? Do both samples pass just the reference to the ReadXML Method?

Please help me understanding the difference. Thanks

+5  A: 

I'd expect the JITted code to be pretty much the same. In the bytecode there's an extra store/load for the first form, but I'd be very surprised to see that make a real difference. The advantage of the first form is that it can make debugging easier - but it makes the code more verbose at the same time.

EDIT: I originally wrote that the two create the same bytecode, but that's not true:

public class Test {
  static void separate() {
    String x = "hello";
    String y = x.toString();
    foo(y);
  }

  static void combined() {
    String x = "hello";
    foo(x.toString());
  }

  static void foo(String x) {
  }
}

Compiles to (just the separate and combined methods):

static void combined();
  Code:
   0:   ldc #2; //String hello
   2:   astore_0
   3:   aload_0
   4:   invokevirtual #3; //Method java/lang/String.toString:()Ljava/lang/String;
   7:   invokestatic #4; //Method foo:(Ljava/lang/String;)V
   10:  return

static void separate();
  Code:
   0:   ldc #2; //String hello
   2:   astore_0
   3:   aload_0
   4:   invokevirtual #3; //Method java/lang/String.toString:()Ljava/lang/String;
   7:   astore_1
   8:   aload_1
   9:   invokestatic #4; //Method foo:(Ljava/lang/String;)V
Jon Skeet
Verbose, true, but probably more readable as well.
shambleh
@shambleh: Sometimes - sometimes not. I certainly wouldn't want to *always* create a local variable for *every* intermediate value. Sometimes the name of the variable can help though, as well as the debugging bit.
Jon Skeet
Does 7: astore_1 8: aload_1 mean that a temporarily copy is created?
Henrik P. Hessel
Well, it does in the bytecode, but I'd expect the same JITted code. If it takes any more memory *at all* (which I doubt) it'll only be 4 or 8 bytes - enough for the reference. It's not creating a copy of the *string*.
Jon Skeet
+1  A: 

In your first example

input = web_service.FullCompanyListChunksGet(x, ChunkSize);
ReadXML(input);

the variable input remains in scope until the end of the block that contains this code. It's not eligible for GC until the exit of that block. In this example

ReadXML(web_service.FullCompanyListChunksGet(x, ChunkSize));

the variable goes out of scope at the function return, so is eligible for garbage collection earlier.

Steve B.
that's something which is important to me..thanks
Henrik P. Hessel
Is the JIT not allowed to notice that the variable won't be used any more, and (when not running under a debugger) ignore it as a root earlier?
Jon Skeet
@Jon: I think it is, but if it really, really matters (!?!) that a data structure is garbage collected earlier, not assigning it (or nulling it afterwards) means that you don't have to depend on the JIT's behaviour on a particular platform.
Stephen C
@rAyt: in my experience it is very unusual for something like this to make much difference in practice. I'd only resort to micro-managing references in stack frames if I had HARD evidence that it was causing problems. If you don't have evidence then this is probably a premature optimization and a waste of your time.
Stephen C