Java was not famous with its performance (decades ago of course), however i give you a few tips to help you overcome this unfortunate fate.

Suppose that you have an innocent-looking bit of code such as this:

// default constructors
public class cls_default {
    public static void main(String args[]) {
    cls_default x = new cls_default();
    }
}

When new is called, to create an instance of the cls_defaultclass, there are no calls to constructors, right? Actually, there are two constructor calls, as illustrated by the output of   javap –crun on this class:

Method cls_default()
0 aload_0
1 invokespecial #4 < Method java.lang.Object() >
4 return
Method void main(java.lang.String[])
0 new #1 <Class cls_default>
3 dup
4 invokespecial #3 <Method cls_default()>
7 astore_1
8 return

The invoke special calls are Java Virtual Machine byte codes used to call constructors. The Java language has the notion of a default constructor, a constructor automatically generated by a compiler if no constructor is defined in a class. A generated constructor invokes the constructor of the class’s superclass. For example, the declaration above that reads:

public class cls_default

actually means:

public class cls_default extends java.lang.Object

In other words, Object is the superclass of any class you define that does not otherwise have a superclass specified, and its constructor will be invoked by a generated constructor in your class. So a constructor is generated that invokes the constructor in java.lang.Object. java.lang.Objectis a special case, in that it has no constructor declared, and no superclass. The generated constructor for java.lang.Object simply has an empty body.Constructor calls matter because of method call overhead

We can generalize the idea in the previous section. Suppose that you have a class hierarchy:

class A {…}
class B extends A {…}
class C extends B {…}
[/source]
If you create a new instance of class C, then a chain of constructors are called, clear back to the one in java.lang.Object. This is the way it’s supposed to work, but at some point the expense can mount up. This example illustrates the importance of method inlining, and tools that help in such inlining.
When an instance of a class is created using new, initialization of the class’s instance variables (variables unique to each instance) must be done. By contrast, class variables (those declared static, and shared across instances) need only be initialized once, conceptually at program invocation time. The difference between these types of initialization is quite important, as this example illustrates:

public class cls_init1 {
    static class Data {
        private int month;
        private String name;
        Data(int i, String s) {
            month = i;
            name = s;
        }
}
Data months[] = {
    new Data(1, "January"),
    new Data(2, "February"),
    new Data(3, "March"),
    new Data(4, "April"),
    new Data(5, "May"),
    new Data(6, "June")
};
public static void main(String args[]) {
    final int N = 250000;
    cls_init1 x;
    Timer t = new Timer();
    for(int i = 1; i &lt;= N; i++)
    x = new cls_init1();
    t.print("data declared non-static");
    }
}

This example takes 4627 units of time to run. However, if we look closely at this class, there is a potential inefficiency. The month number/name data found in months[]is an instance variable of the class, that is, a copy of the data is found in every instance of the class. Structuring the data in this way doesn’t make sense, in that the number/name data never changes, and is the same across all class instances. So we can change the program slightly, to turn the number/name data into a class variable, with a single copy across all instances:

public class cls_init2 {
    static class Data {
        private int month;
        private String name;
        Data(int i, String s) {
            month = i;
            name = s;
        }
    }
static Data months[] = {
    new Data(1, "January"),
    new Data(2, "February"),
    new Data(3, "March"),
    new Data(4, "April"),
    new Data(5, "May"),
    new Data(6, "June")
};

public static void main(String args[]) {
    final int N = 250000;
    cls_init2 x;
    Timer t = new Timer();
    for(int i = 1; i &lt;= N; i++)
        x = new cls_init2();
    t.print("data declared static");
    }
}

This program requires 421 units of time to run, a saving of 10-1 over the first approach. Moreover, it saves a lot of space per class instance as well. As a general rule, it’s worth “factoring out” methods that do not operate on unique data in a class instance, and variables that are not unique to an instance, and making both methods and variables static, that is, shared across all instances.

WHAT ABOUT RECYCLING CLASS INSTANCES

Suppose that you are implementing some type of a linked list structure, and that nodes of the structure have the form:

class Node {
    Object data; // data
    Node link; // link to next node in the list
}

and you are worried about the costs of allocating and garbage collecting large numbers of these nodes. One alternative to new and garbage collection is to keep a free list of nodes, and check the list before you call new to allocate a node. For example, you might have a class variable freelist used for this purpose. When you free up a node referenced by a variable noderef, you could say:

noderef.link = freelist;
freelist = noderef;

that is, add the freed node to the head of the free list. When you want to allocate a node, you check freelist, and if it’s not null, you can obtain a node by saying:

noderef = freelist;
freelist = noderef.link;

For this scheme to work, you need to update freelist in a thread-safe manner, by using synchronized methods or statements. You need to be careful with this technique, as it tends to work against the whole idea of constructors, and against a cleanly defined approach to initializing objects. This approach makes most sense when you have some type of an internal utility class, and you want to manage large numbers of instances of this class.

Reklamlar

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s