2

I'm learning Java and starting on my first lesson/project. In this project, the tutor's pixel moves across the screen and a steady clip and completes it's journey across the screen in a matter of a few seconds. Mine takes several minutes, moving only 1 pixel every 5 seconds. I would have thought a MacBook Pro would handle Java graphics better than that. To see if it was my code or the unit, I rebuilt the project from scratch while booted in Windows, the performance was noticeably improved. There, the cursor moves 1-2 pixels a second; still not as good as the instructors, but better than OSX handles it. I'm wondering if this is normal or expected? Does OSX just have a crappy time with handling Java graphics? I've linked my code if it helps to answer this question, as well as a video of the slow moving pixel and abysmal frame rate in OSX. Fraps shows I'm getting an average 650 fps in Windows, the code output on the OSX side shows it is more around 40-60 depending on whether or not I have other video processes going. In the video it is around 45, but that is because the screen capture slows it down from the average 60 fps.

example of framerate in OSX: https://www.youtube.com/watch?v=PQ0-L4slgP4

Code for Screen class: http://pastebin.com/3ETKsY8r

Code for Game class: http://pastebin.com/NDreVB60

I'm using Eclipse Juno under 10.7.5 on the Apple side, and Windows 7 on the Bootcamp side. The MacBook has 4GB of memory and a 2.53 Ghz Intel Core 2 Duo.

Vin Breau
  • 269
  • 3
  • 17
  • 4
    maybe your code is the problem, you iterate over your large pixel array 3 times in your render loop, you only need to access 2 values in it each time, (also `running` should be volatile) – ratchet freak Dec 13 '12 at 17:34
  • That's possibly true, but my code is identical to the instructors in every way and his runs very fast. It has been suggested by others that I remove the pixels param entirely. – Vin Breau Dec 13 '12 at 17:49
  • which JVM are you using? Sun or OpenJDK? – fo_x86 Dec 13 '12 at 17:59
  • 1
    To see @ratchetfreak's point, note the secular improvement when going from `createBufferStrategy(3)` to `2` and then to `1`; see also this [alternative](http://stackoverflow.com/a/2068517/230513). – trashgod Dec 13 '12 at 18:01
  • 1
    a note, just because the instructors write some code this way or that way doesn't mean it's the best way. If anything usually it's not, instead being the easiest to understand code. – Jimmt Dec 13 '12 at 18:17
  • Changing the `createBufferStrategy` to 1 made it run as fast is it did in Windows. So I agree that is the cause of the sluggishness. To answer @fo_x86: java version "1.7.0_10" Java(TM) SE Runtime Environment (build 1.7.0_10-b18) Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode) – Vin Breau Dec 13 '12 at 18:33

1 Answers1

1

I ran your code sample on my MacBookPro and the result was way better than the one in the video you had posted.

Now, I am not super expert on Java 2D Graphics, but an observation is that since you need to redrawing the whole canvas over and over with every iteration so that the pixel moves, logic involved in the rendering process should be fast. Also, since the pixel is moving diagonally, the greater area to the right is of no use for your example, hence I would recommend making the JFrame a square, which makes for a less area to re-draw.

Finally, I made some changes to the code of the class Screen that could make things faster for you.

package com.oblivion.rain.graphics;

public class Screen {
    // Height was removed since there is no use for it
    private int width;
    public int[] pixels;

    int time = 0;
    int counter = 0;

    // We need this in order to avoid the iteration in the clear method.
    int previousPixel = 0;

    public Screen(int width, int height) {
        this.width = width;
        pixels = new int[width * height]; // 50,400
    }

    public void clear() {
        // In case the frame is a rectangle, the previousPixel
        // could hold a value that is greater than the array size
        // resulting in ArrayOutOfBoundsException
        if (previousPixel < pixels.length) {
            pixels[previousPixel] = 0;
        }
    }

    public void render() {
        counter++;

        if (counter % 100 == 0) {
            time++;
        }

        // Calculate the previousPixel index for use in the clear method
        previousPixel = time + (time * width);


        // Make sure we didn't exceed the array length, then set the 
        // array data at the calculated index
        if (previousPixel < pixels.length) {
            pixels[previousPixel] = 0xff00ff;
        }
    }
}
Waleed Almadanat
  • 1,027
  • 10
  • 24
  • Thanks for taking the time to do this. However, your script only ran at about 1 pixel per every 2 seconds movement. It's my MacBook. I rebuilt the code from scratch while booted to Windows and had noticeably improved performance. I also found that the screen FPS in Mac 10.7 dropped by half by simply playing a YouTube video at the same time. I continued with the project and found other animations to run faster, but with random jerking. This behavior was worse, again, when a YouTube video was played simultaneously. I just have to accept that this unit doesn't run Java well. – Vin Breau Dec 17 '12 at 19:01