Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static method is slow

I'm programming a simple game in java. I've made a collision test with 30 FPS, where I had to get the size of the window. Because I haven't had access to the GUI instance, I thought I'd make a shared instance, because this is pretty standard in Objective-C, where I come from.

class GUI extends JFrame {
    private static GUI _sharedInstance;

    public static GUI sharedInstance() {
        if (_sharedInstance == null) {
            _sharedInstance = new GUI();
        }
        return _sharedInstance;
    }
}

But for some reason, it was really slow. Then I replaced the shared instance with public static final instances for the size, and it works fast now, even with 60 FPS or higher.

Can anyone explain me why this happens?

EDIT

So instead of calling GUI.sharedInstance().getWidth(), I'm just calling GUI.windowSize.width. I have used the public static final Dimension windowSize instead.

EDIT

Here's the collision detection. So, instead of calling int width = GUI.kWindowWidth;, I was calling int width = GUI.sharedInstance().getWidth(); before.

// Appears on other side
if (kAppearsOnOtherSide) {
    int width = GUI.kWindowWidth;
    int height = GUI.kWindowHeight;

    // Slow
    // int width = GUI.sharedInstance().getWidth();
    // int width = GUI.sharedInstance().getHeight();

    Point p = this.getSnakeHead().getLocation();
    int headX = p.x;
    int headY = p.y;

    if (headX >= width) {
        this.getSnakeHead().setLocation(new Point(headX - width, headY));
    } else if (headX < 0) {
        this.getSnakeHead().setLocation(new Point(headX + width, headY));
    } else if (headY >= height) {
        this.getSnakeHead().setLocation(new Point(headX, headY - height));
    } else if (headY < 0) {
        this.getSnakeHead().setLocation(new Point(headX, headY + height));
    }
}
like image 534
IluTov Avatar asked Nov 22 '12 22:11

IluTov


1 Answers

I know that this might not be the real answer to the question, but there could be a problem with a race condition. I assume that you are trying to use the lazy/singleton pattern, because the construction of the GUI class is quite expensive and you need only one instance.

Now, what happens? If a thread runs into the if statement body, it creates a new GUI instance. Just before the next assignment, it gets paused by the scheduler. Now another thread pops in, sees that _sharedInstance is still null and creates another GUI instance (and so on...).

Lets assume that there are only two threads. The first thread runs to the end and the second one is continued, now you have two instances of the GUI class. Nobody says that the unassigned GUI instance gets destroyed or garbage collected. That could explain tha 50 % performance loss compared to using finally and assigning the GUI instance directly to _sharedInstance.

See e.g. the Java examples at http://en.wikipedia.org/wiki/Singleton_pattern Double checked locking, inner classes or an enum are the ways you can use.

like image 59
user3001 Avatar answered Oct 12 '22 11:10

user3001