Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (497)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Mysterious Graphics2D-related slow-down  (Read 1741 times)
0 Members and 1 Guest are viewing this topic.
Offline sixtyten

Junior Member


Projects: 1



« Posted 2013-01-25 19:59:11 »

Hey,

A puzzling bug (at least to me)  Huh - previously my game was running at 60 FPS no problem, but one day when I ran it again, the framerate was down to 3-4 FPS. I found that I could restore the full framerate by removing some graphics2D.drawString() calls.

But then the next day, it seemed to be back down to 3-4 FPS (I had made some minor code changes in the interim). When I removed all but 1 of the drawString calls, the framerate went back to 60FPS again. But the amount of text I'm now able to draw without a very drastic slowdown is far less that what I could draw originally...

Perhaps the drawStrings are not the issue and there is some other drawing operation that I am compensating for by removing them. I'm clutching at straws here... Has anyone experienced anything similar who could give me some suggestions what might be going on? Is there some limit to Graphics2D calls that might be causing the slow-down?

Thanks.  Cheesy

Edit: Latest news - as far as I can tell it's a fairly generalised slow-down from the old to the new version. Profiling identical code in the 2 versions gives a performance drop of 10-20x. This is not some big complicated game, just a single class that I'm coding for the 4K compo. My latest guess is that it's something memory-related, but I am trying some more advanced profiling to see what might be going on...
Offline ClickerMonkey

JGO Coder


Medals: 20


Game Engineer


« Reply #1 - Posted 2013-01-25 21:12:12 »

What rendering hints are you setting on your Graphics object if any? You could be telling it to draw text in a very detailed manor opposed to the quickest algorithm.

Offline sixtyten

Junior Member


Projects: 1



« Reply #2 - Posted 2013-01-25 21:50:47 »

What rendering hints are you setting on your Graphics object if any? You could be telling it to draw text in a very detailed manor opposed to the quickest algorithm.

Antialiasing hints were on, but turning them off has no effect on the slow-down. It seems to depend on the number of Graphics2D drawing calls (drawString, drawRect, etc.).
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Cero
« Reply #3 - Posted 2013-01-25 22:06:37 »

Edit: Now it is slowing down even with no drawString calls, so that alone is not the culprit. But adding or removing other Graphics2D calls still seems to massively affect the framerate. Some further background info: Most of the other graphics are done by drawing directly into a BufferedImage (as a DataBufferInt), which is then drawn to the screen using appletGraphics.drawImage.

You really need to get your shit together and find out what it is exactly, using a profiler or sysouts of system.nanotime

Offline sixtyten

Junior Member


Projects: 1



« Reply #4 - Posted 2013-01-25 22:57:34 »

Edit: Now it is slowing down even with no drawString calls, so that alone is not the culprit. But adding or removing other Graphics2D calls still seems to massively affect the framerate. Some further background info: Most of the other graphics are done by drawing directly into a BufferedImage (as a DataBufferInt), which is then drawn to the screen using appletGraphics.drawImage.

You really need to get your shit together and find out what it is exactly, using a profiler or sysouts of system.nanotime

Well I System.nanoTime'd the hell out of everything, and all the numbers add up to 100ms+ which of course means god-awful framerate. But this is all stuff that has been running smoothly up until recently. I just installed a Java update, I wonder if that affected it. I have older versions of the code backed up so I will try compiling them again to see how they run.
Offline sixtyten

Junior Member


Projects: 1



« Reply #5 - Posted 2013-01-25 23:24:15 »

Hmmm... so I went back and compiled an old version. Ran smoothly no problems.

Timing a section of code in the old version that does "plotting" gives 3-6 ms. In the newer version, it gives 60-120 ms. OK, fine.

So then I copied the exact code (from the first System.nanoTime to the second) from the old to the new version. And the timings are still exactly as before. So the conclusion is that doing exactly the same thing is 20x times slower in one version than the other...

The code that I copied is a loop that transfers data from a world-map array to the screen array (a 512x512 int array). There are various things done in the loop (which take 60-120ms in the new version). If I remove all that and just set all screen values to 0, the time taken is now 8ms - which is still slower than the old version which is doing everything else in the loop as well.

Any ideas?
Offline sixtyten

Junior Member


Projects: 1



« Reply #6 - Posted 2013-01-25 23:39:31 »

This is the code snippet I was talking about:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
            // XXX: DEBUG - Profile screen plotting
           long plotT1 = System.nanoTime();

            // Draw everything to the screen
           for (py=0; py < worldSize; py++) {
               for (px=0; px < worldSize; px++) {

                  // Screen coordinates
                 i = (py << worldSizePow) + px;
                 
                  // Plot pixel
                 pixels[i] = 0;
               }
            }

            // XXX: DEBUG - Stop pixel plotting timer
           long plotT2 = System.nanoTime();


Old version takes 0.6ms, new version takes 8ms - same code.
Offline philfrei
« Reply #7 - Posted 2013-01-25 23:57:12 »

I'm curious, if you substitute an int[] for BufferedImage pixels, what does that do to the timing between the two versions?

What versions of Java are you referring to?

I don't know a lot about graphics, but there are a number of different ways to place data into a BufferedImage, and the internals of this are a bit mysterious to me: sometimes areas beyond, in the graphics accelerator process(?) are engaged. There are other folks that know more about this and will be able to help.

I think it is possible to build the array, then place the entire data array into the BufferedImage in one command, rather than 512^2 writes. This might be a good work-around.

I did this as follows:

1  
2  
3  
4  
5  
    int[] pixelData = raster.getDataElements(0, 0, width, height, pixelData);

    // two loops to place data into pixelData

    raster.setDataElements(0, 0, width, height, pixelData);


Maybe that will work faster for you. "raster" is the raster you get from your BufferedImage.

HTH!

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline sixtyten

Junior Member


Projects: 1



« Reply #8 - Posted 2013-01-27 21:04:28 »

I'm curious, if you substitute an int[] for BufferedImage pixels, what does that do to the timing between the two versions?

Using an int array seems to run at the same speed.

Quote
What versions of Java are you referring to?

It was an upgrade to my Java plug-in in Firefox (to SE 7 U11 10.11.2.21). I don't think that should affect compilation from the Java libs though. Plus it's clear the slow-down is specific to the newer version of the code and not the old, so the issue is not with any of the Java platform per se.

Quote
I don't know a lot about graphics, but there are a number of different ways to place data into a BufferedImage, and the internals of this are a bit mysterious to me: sometimes areas beyond, in the graphics accelerator process(?) are engaged. There are other folks that know more about this and will be able to help.

I think it is possible to build the array, then place the entire data array into the BufferedImage in one command, rather than 512^2 writes. This might be a good work-around.

I did this as follows:

1  
2  
3  
4  
5  
    int[] pixelData = raster.getDataElements(0, 0, width, height, pixelData);

    // two loops to place data into pixelData

    raster.setDataElements(0, 0, width, height, pixelData);


Maybe that will work faster for you. "raster" is the raster you get from your BufferedImage.

HTH!

The problem is not the screen copying itself I think, it seems to be more of a general slow-down to all processes (blegh). I thought it might be some memory paging evil slowing everything down, so I reduced the size of one large array (a 4096x4096 double array) to 512x512, but that had no effect.

I'll look into how to do some more informative profiling (I'm using Eclipse). But any suggestions/ideas are very welcome.

Cheers!
Offline StumpyStrust
« Reply #9 - Posted 2013-01-27 21:36:48 »

In your new version or you setting and global flags to use opengl? They can cause all sorts of crap to happen.
Also, the performance of java2D is almost directly related to the number of Graphics.drawStuff calls as long as you are not decelerating images.

I had massive changes in performance when using java2D and trying something on one computer then another or changing small things. Will recommend switching to something more reliable.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sixtyten

Junior Member


Projects: 1



« Reply #10 - Posted 2013-01-27 23:46:35 »

In your new version or you setting and global flags to use opengl? They can cause all sorts of crap to happen.
Also, the performance of java2D is almost directly related to the number of Graphics.drawStuff calls as long as you are not decelerating images.

I had massive changes in performance when using java2D and trying something on one computer then another or changing small things. Will recommend switching to something more reliable.

This for the 4K compo, so I'm pretty much bound to using Java2D.

Okaaaayyyy, so it makes less and less sense over time. I tried commenting out the majority of the drawing code and that worked to bring the framerate back to 60 FPS. So then bit by bit I commented the code back in, to find the faulty section. But all I can conclude after that is that the length of the code is what is causing the slow-down... as ridiculous as that sounds.

For example the version with this code runs at 60FPS:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
            // If player trying to settle, show potential town location
           playerCanSettle = false;
           
            // XXX: DEBUG - Time settlement radius drawing
           long drawSettleT1 = System.nanoTime();

            playerSettling = false;
           
            if (playerSettling) {

               // Unsettle-able = Red, Settle-able = White
              //px = playerCanSettle ? 0xFFFFFF : 0xFF0000;

            }
           
            // XXX: DEBUG - Time settlement radius drawing
           long drawSettleT2 = System.nanoTime();


However, including the one (completely unreachable) line in the if statement drops the framerate to 10 FPS:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
            // If player trying to settle, show potential town location
           playerCanSettle = false;
           
            // XXX: DEBUG - Time settlement radius drawing
           long drawSettleT1 = System.nanoTime();

            playerSettling = false;
           
            if (playerSettling) {

               // Unsettle-able = Red, Settle-able = White
              px = playerCanSettle ? 0xFFFFFF : 0xFF0000;

            }
           
            // XXX: DEBUG - Time settlement radius drawing
           long drawSettleT2 = System.nanoTime();


This is well beyond any kind of weirdness I'm used to experiencing. Normally I can confidently rely on the bug coming from some stupidity on my part, but this.....

I feel like perhaps it's some technical aspect of the way the program's being run. Like it's hitting a memory ceiling or stack limit or something else uber-technical. So if any Java gurus have any ideas...
Offline philfrei
« Reply #11 - Posted 2013-01-28 02:29:58 »

Pretty darn weird on the face of it.

On the two versions, is the nanoTime over this code interval about the same? Or is this where the slow down is occurring?

What is the value of 'px' if it is not assigned at that spot? Could the slowdown be related to the value contained in 'px'?

Just tossing some ideas your way. This does seem mysterious.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline SHC
« Reply #12 - Posted 2013-01-28 02:49:50 »

I think it may be the problem in the execution. Just a test. submit the old and new versions of your game here so that we can run them.

Offline ctomni231

JGO Wizard


Medals: 99
Projects: 1
Exp: 7 years


Not a glitch. Just have a lil' pixelexia...


« Reply #13 - Posted 2013-01-28 21:06:56 »

Wait, did you say you were using anti-alias calls along with draw calls in a loop?

If this is being done in a loop in Java2D. That is 100% that cause of such a dramatic frame loss. Anti-aliasing is extremely slow in Java if you call it more than once per update frame. (Actually, it is just really slow in general.)

I did make a 4k game for this competition and tried to use anti-aliasing. One call slowed down my game from 60FPS to around 45FPS. For Applets, it really slows it down depending on the anti-alias call used. It can be very expensive. In order to keep the game running quick on the slowest computers, I had to really fake anti-aliasing by using colors that naturally looked dimmer. It is a lot quicker than depending on that call.

But that is just a very wild guess. If you are experiencing that much of a difference, I'd try removing those calls and seeing if they make a real difference in the frame rate. (Oh, if that was done, also trying to reduce the amount of draw calls can help a ton as well.)


Offline sixtyten

Junior Member


Projects: 1



« Reply #14 - Posted 2013-01-28 21:13:23 »

I think it may be the problem in the execution. Just a test. submit the old and new versions of your game here so that we can run them.

Let's see if this works - slow version:

[applet archive=slowversion.jar class=T width=512 height=512]
Offline sixtyten

Junior Member


Projects: 1



« Reply #15 - Posted 2013-01-28 21:44:28 »

OK, fast version:

[applet archive=fastversion.jar class=T width=512 height=512]

Yes, I know there are different amounts of text drawn/graphic objects. But I would be interested to hear if there's a big difference in speed between the two versions for everyone else, as there is for me.

The simplest solution will probably be for me to trim down the code (which is pretty bloated as I've been trying out lots of different ideas) and reduce the number of drawX calls if possible. But it's a bit troubling that I could hit some invisible performance ceiling at any time.

Does this just get filed under "Java2D sucks"?
Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #16 - Posted 2013-02-02 10:26:15 »

They both started at about 11 to 15FPS and then the fast one suddenly went to 60FPS.  OSX Mountain Lion, Java 7.13.

Maybe the JIT compiler is having difficulty with your slow version.  Or more likely you've used some feature that isn't hardware accelerated and the graphics image is getting copied back and forth between the CPU and GPU multiple times per loop.  I'd switch off all anti-aliasing and see if that helps.  Try commenting out all text writing. Also check that the BufferedImage format is compatible with your display to ensure good copy performance between CPU and GPU.

This used to be a big problem for me back on OSX with Java 1.4 (worked ok on PC), when I bit bashed the raster image interleaved with writing antialiased text.  Basically all text functions were done on the GPU, while the rest needed the buffer on the CPU.  Result: Endless buffer copies throughout the loop.

Time flies like a bird. Fruit flies like a banana.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

BurntPizza (25 views)
2014-09-19 03:14:18

Dwinin (39 views)
2014-09-12 09:08:26

Norakomi (68 views)
2014-09-10 13:57:51

TehJavaDev (93 views)
2014-09-10 06:39:09

Tekkerue (47 views)
2014-09-09 02:24:56

mitcheeb (68 views)
2014-09-08 06:06:29

BurntPizza (51 views)
2014-09-07 01:13:42

Longarmx (38 views)
2014-09-07 01:12:14

Longarmx (44 views)
2014-09-07 01:11:22

Longarmx (40 views)
2014-09-07 01:10:19
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!