6

(I'm using String as an example, but it could be replaced for Object > MB's of memory)

do this quite a lot:

private static String mTempString = "";

private static void SomeMethod()
{
    mTempString = "Whatever Result";
}

Now my question is, if I was to write it like so:

private static void SomeMethod()
{
    String mTempString = "Whatever Result";
}

and use it in a loop (that is executing hundreds of times a second as an example) would Java know how to manage the memory as example one? Would be memory be of the same efficiently. (Sorry I can't test this myself at the moment)

Which is more memory efficient (disregarding the fact that they are small variables)

--edit--- Found an excellent article here that explains it http://www.cs.berkeley.edu/~jrs/4/lec/08

Oliver Dixon
  • 7,012
  • 5
  • 61
  • 95
  • in second example, variable has local scope. In first example, variable has global scope. Therefore, in second example, the variable can not be accessed out of the function. Which can be done in the former. So, it depends on your needs. – Bill May 27 '13 at 02:33
  • 1
    It's a question of memory, will the variable be recreated? – Oliver Dixon May 27 '13 at 02:38
  • for the former, NO, since it is static and has global scope. For the later, it depends on the compiler, if it is going to keep using the same memory location or a new memory location. IMHO, there should be no performance hit using the second option. – Bill May 27 '13 at 02:42
  • 1
    @Bill - The method can have multiple concurrent callers. With reflection and JNI, these may exist without knowledge of the compiler during compilation of the class. Unless the compiler optimizes out the local variable entirely, I think it's likely there's a separate copy on the activation frame of each call. – Andy Thomas May 27 '13 at 02:48
  • @AndyThomas-Cramer Yes, exactly. But, if the variable has local scope, it should not be made global. AFAIK, the second scenario should not have any performance hit. – Bill May 27 '13 at 02:49
  • 1
    It's more efficient to use a local variable vs using an instance or static variable, in addition to all the other reasons for using the narrowest scope you can. (Keep in mind that your "LO" variable itself is not large -- it's just a pointer.) However, if you keep reallocating (via `new`) a large array or some such, vs reusing a "shared" copy, that reallocation will be somewhat of a performance drag (though how much is hard to say). – Hot Licks May 27 '13 at 03:13

6 Answers6

9

Keep the scope of your variables as narrow as possible.

This is important for several reasons:

  1. Readability. If you use that variable in three different places with four different values (go figure), you're going to have a hard time discerning what purpose that variable is supposed to serve.

  2. Bugs. You reduce the amount of errors that could crop up in your application if you keep a single variable to a single, well-specified scope. Suppose you had that String, and you expected it to be some value in two methods, but it was something completely different.

  3. Intent of purpose. I mentioned this a bit in the readability section, but if you have a static variable that keeps getting redefined, its intended purpose has become unclear. Typically, static methods and variables can be used independent of the state of the object, so if the state of the object affects the value of the static variable, the intent has become confusing.

I wouldn't worry much about memory efficiency at this point (unless you had gobs of strings, but then I'd say you have two things to worry about).*

*: First rule of optimization: Don't do it.
Second rule of optimization (experts only!): Don't do it yet.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • I'm using String as an example, but it could be replaced for Object > MB's of memory – Oliver Dixon May 27 '13 at 02:50
  • If an instance of your custom object is using *mega* bytes of memory, you now have [three things](http://en.wikipedia.org/wiki/God_object) to worry about. – Makoto May 27 '13 at 02:51
  • There's formally defined specifications [here](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html), but you don't want to concern yourself with that until you *have* to concern yourself with it. – Makoto May 27 '13 at 03:06
  • Hm. You moved the goal posts of this question. Also, your question is a bit wonky in and of itself - static variables are different than fields or local variables with respect to their lifetime and allocation. I'm going to roll back the edit you made, but you're welcome to *add it in* - just don't let it replace the entire question (which most answers here are based on). – Makoto May 27 '13 at 03:17
  • So what is the answer to the question? Does the compiler recreate locally scoped variables? – Oliver Dixon May 27 '13 at 03:41
  • 1
    @Olly Considering your example uses the (immutable) `String`, new objects will always need to be created and thrown away each loop regardless, so your desire to micro-optimize would be for naught anyhow. – arkon Nov 22 '14 at 09:34
3

In general, prefer to limit the scope of variables as much as possible. This makes code easier to understand, debug and refactor.

In this case, the memory required for these variables in both cases is very small. Each variable is a reference to an object, not the object itself. The reference may take as little as four bytes when used as a local variable.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • 1
    But the Object is not a variable -- just the reference is. The reference is a small number of bytes, regardless of the size of the object. – Andy Thomas May 27 '13 at 03:02
  • So when the local method creates local variables over and over they are just references, then wouldn't different values come out for different arguments? – Oliver Dixon May 27 '13 at 03:42
  • Can you clarify the question? Does "different arguments" refer to method arguments, or something else? Does "different values" refer to method return values, or something else? – Andy Thomas May 27 '13 at 04:22
1

The scope of local variables should always be the smallest possible.

unless you need the variable outside of the scope it is better to declare the variable inside the scope. There is no performance difference in this case but it is recommended for best coding practice to declare the variable in the smallest possible scope. See this similar and popular SO question

A different scenario would be a use of immutable type instead of string. Where there will be a slight performance difference (very negligible). There declaring at top would be a very little bit better as you do not need to initializing the variable at each loop. But in string as it is creating new object each time so this is not an issue in your case.

Community
  • 1
  • 1
stinepike
  • 54,068
  • 14
  • 92
  • 112
  • 1
    "smallest possible" would include **ALL** places where it is needed. So by definition you couldn't use it outside of the "smallest possible scope" – Craig May 27 '13 at 02:47
1

Jvm should be able to determine that this is a constant and optimize it if necessary so you dont need to worry about either style.

In case of arithmetic expressions JVM can perform constant folding optimization.

If you are just interested in strings, constant strings are stored inside a string pool.

As you may know strings are immutable in java.

Therefore if you have constant strings in java, they will only be stored once and all references will point to that string object.

e.g.

    String s = "a" + "bc";

    String t = "ab" + "c";

    System.out.println(s == t);

returns true because t and s point to the same string object.

Furthermore java classes have constant pools where all constants like these are moved to.

Essentially JVM is quite clever and I do not think that either of these toy examples are better than each other at least in terms of efficiency. Although as other answers mention, there are software design considerations that you probably should take into account.

Osama Javed
  • 1,432
  • 1
  • 16
  • 21
1

I conduced my own test on this to see if the compiler was actually creating a "new" object with each iteration. Here are the results from the following code:

private static long mStartedTime;

public static void main(String args[])
{
    long TotalTime = 0;
    int NumberOfLoops = 7;

    for(int i = 0; i < NumberOfLoops; i++)
    {
        mStartedTime = System.currentTimeMillis();

        for(float Index = 0; Index < 10000000; Index++)
        {
            test1("wewgwgwegwegwegsd veweewfefw fwefwef wfwefdwvdw wefwe wevwev etbe tbebetbetb evberve");
        }

        System.out.println("Program took: " + String.valueOf(System.currentTimeMillis() - mStartedTime) + " to complete.");
        TotalTime += System.currentTimeMillis() - mStartedTime;
    }

    System.out.println("Average time taken: " + String.valueOf(TotalTime / NumberOfLoops));
}


public static void test1(String THisIsText)
{
    String Test = THisIsText;
    Test = Test.substring(1);
}

private static String mTempString;
public static void test2(String THisIsText)
{
    mTempString = THisIsText;
    mTempString = mTempString.substring(1);
}

They came out with different results, seems putting varibles in the local scope causes a performance loss:

I can only guess that the local method variables are deleted and this takes time hence why test1 takes longer? (Can anyone confirm this)

(After many tests)

Local-scope average: Average time taken: 1183

Class-scoped reusable variable: Average time taken: 1043

Oliver Dixon
  • 7,012
  • 5
  • 61
  • 95
  • 3
    Strings are a special case. Literal string objects can be placed in a string pool by the compiler. Multiple reference variables can reference the same object. – Andy Thomas May 27 '13 at 04:21
  • 1
    @OllyDixon: Amazing how many people answered anything but what you asked. At the end, you answer your own question. I have the same question reusing a bitmap. So, following your results here, I will declare it globally. – Luis A. Florit Oct 05 '13 at 02:35
0

If mTempString is a temporary variable needed only in someMethod() then it must be declared as a local variable inside the method and never as a static member of your class. The reason is that you want to make sure that nobody else messes with your temporary variable.

If you declare it in the class, then your code is more error prone, because you can't be sure who could modify the variable.

In your example the temporary variable is declared as a static field. This makes the code not thread safe. If two different threads would call the same method almost at the same then the second method call would change the value of the temporary variable affecting the thread that invoked the first call.

nakosspy
  • 3,904
  • 1
  • 26
  • 31