Object creation optimization

user184994

I am currently watching a video regarding android code optimization (https://www.youtube.com/watch?v=w9taB0yUwjs)

In this video, he is optimizing the following code:

List<Contact> contacts = new ArrayList<Contact>();

if (cursor.moveToFirst()) {
    do {
        Contact contact = new Contact(...);
        contacts.add(contact);
    while(cursor.moveToNext());
}

He suggests that the following would free up memory.

List<Contact> contacts = new ArrayList<Contact>();

if (cursor.moveToFirst()) {
    do {
        contacts.add(new Contact(...));
    while(cursor.moveToNext());
}

I do not quite understand why this would free up memory. My (limited) understanding is that the contact variable would just be an object reference stored on the stack. Would creating the objects anonymously actually produce a significant reduction in memory usage? From reading this answer it seems an object reference takes up a mere 4 - 8 bytes.

Am I missing something here?

awksp

This might be oversimplified, but it'll give you the basic idea.

Here's a test class comparing a method with an extra reference and an equivalent method with an inlined call:

public class Test {
    static List<String> list = new ArrayList<>();

    public static void extraReference() {
        String s = new String();
        list.add(s);
    }

    public static void noReference() {
        list.add(new String());
    }
}

Here's the bytecode for the methods, in the same order they were declared:

public static void extraReference();
    Code:
       0: new           #2                  // class java/lang/String
       3: dup           
       4: invokespecial #3                  // Method java/lang/String."<init>":()V
       7: astore_0      
       8: getstatic     #4                  // Field list:Ljava/util/List;
      11: aload_0       
      12: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      17: pop           
      18: return        

  public static void noReference();
    Code:
       0: getstatic     #4                  // Field list:Ljava/util/List;
       3: new           #2                  // class java/lang/String
       6: dup           
       7: invokespecial #3                  // Method java/lang/String."<init>":()V
      10: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      15: pop           
      16: return 

If you look carefully, the only difference is an extra reference store/load instruction in the bytecode.

Now, if this code were executed as-is, you might notice a difference after a lot of calls -- such as in a loop. Extra CPU cycles might be burned, and you have to use a place on the stack to store the reference (which shouldn't bother the GC at all since the GC deals only with the heap, and items on the stack are freed automatically, from this answer). But I wouldn't call the cost significant.

However, there's the magical entity known as the JIT compiler present on virtually every JVM (and the Dalvik VM that Android uses, if memory serves). The JIT compiler has the ability to inline the extra reference, so the code with the extra reference essentially becomes exactly the same as the code without the extra reference. This should be an relatively easy optimization for the JIT compiler to execute, especially for more modern VMs.

So in the end, if there is a difference at all you can safely ignore it due to the JITC. You should pick the code style that is more readable to you, in this case.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related