JDK-5095398 : Graphics performance degrades unacceptably when XPS laptop unplugged (Win XP)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 5.0
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2004-09-01
  • Updated: 2008-03-11
I noticed that some Swing applications I was using (e.g., JEdit) became unusably slow whenever my laptop (Dell XPS) was unplugged.  I know that either/both the CPU and the graphics chip are probably scaled back on performance (and thus power consumption) when the laptop is unplugged, but not to the extent I was seeing in these Swing applications.

I ran some tests (both 2D and native) to see what the problem was.

It turns out the main bottleneck is text performance.  This is seen through runs of J2DBench2 (where the drawString performance while unplugged was .55% (that's half of one percent, or 200x slower) the performance while plugged in), SwingMark (where the overall score was about 20x slower, and every test suffered similarly), and some micro benchmarks that I wrote.

The main graphics operation in text rendering is Locking/Unlocking the destination surface; since we do not currently accelerate text operations, we render the text by locking the back buffer, copying the glyph pixels one-by-one, and unlocking the back buffer.  So it seems reasonable that the core problem is the Lock/Unlock performance while unplugged.

I wrote a native test (DDrawLockTest) to trace the root cause.  My first attempts didn't find the problem; I was getting nearly the same performance for unplugged Lock/Unlock operations as I did while plugged in (occasional blips, but nothing on the order of what I saw with Java2D).  Then I created the offscreen ddraw surface to be d3d-capable, which matches our approach in Java2D (the back buffer must be d3d-capable in order for us to be able to draw lines and textures to it).  This finally showed the same results as I was seeing with Java2D; worse, in fact, because my native test hammered exclusively on Lock/Unlock.

The performance I saw with DDrawLockTest was something like:
	7 ms for 500 Lock/Unlock operations for the offscreen surface
	18 ms for 500 Lock/Unlock operations for the onscreen primary surface
while plugged in, but:
	2600 ms for the offscreen
	6100 ms for the onscreen primary
when unplugged.

Ignoring the onscreen primary surface performance (we actually don't do this
in Java2D by default; locking the screen tends to cause flickering), we can see that the offscreen performance for this simple Lock/Unlock operation suffers by a factor of about 370x.

I do not know if this is a widepread problem for Windows laptops , or whether it is specific to the XPS configuration (ATI 9700M), but this degree of performance loss for one of our core rendering approaches (using ddraw for the back buffer, locking that back buffer for common operations such as text) makes it unacceptable when the problem does occur.

We should figure out how widespread the problem is and what it would take to fix the problem in general.

WORK AROUND Just to narrow this down, disabling the use of Direct3D eliminates the problem on pre-5.0u8 releases (-Dsun.java2d.d3d=false or by setting an env. variable J2D_D3D=false).

EVALUATION I've verified on my notebook with ATI board that the problem is not reproducible on 5.0u8 (not yet released) and mustang (Java 6) builds (http://mustang.dev.java.net).

EVALUATION Another possible workaround we could implement is to listen to WM_POWERBROADCAST (PBT_APMPOWERSTATUSCHANGE) message and disable the use of DirectDraw/Direct3D if we're running on batteries. The tricky part is enabling the use of DirectDraw back once we run on power again, given our somewhat messy state of Win32 pipelines.

EVALUATION Note that in Mustang (Java 6) and 5.0u8 we've stopped using Direct3D for rendering to offscreen surfaces by default in non-fullscreen mode because of some other issues. So if this problem is only caused by our use of D3D, it will be addressed soon for 5.0 - in update 8, and in mustang it should already be fixed.

EVALUATION The key here is that it is our use of D3D that causes the horrendous slowdown. Or, rather, our specification that the buffer needs to be d3d-enabled; actual d3d operations are not that much slower. But the Lock/Unlock of a d3d-enabled surface is far worse than the equivalent operation on a non-d3d-enabled surface. Interestingly, the performance of Lock/Unlock when plugged in is significantly worse (2000 ms vs. 500 ms) than the same operation on a non-D3D surface. Whatever the driver or hardware is doing to support d3d capability on this surface is imposing a pretty serious penalty for our simple 2D operations on that surface. I believe the real fix here is in the upcoming rewrite of our DirectX rendering pipeline; we need to move to a system where all possible rendering operations occur through DirectX, instead of the model we currently have where many operations (such as text) go through a software rendering approach. By sending everything down the same pipe, we will stop getting hit by such bottlenecks as this bug as well as other mixed-rendering problems wuch as context switching between ddraw and d3d and GDI as well as the inability to truly pipelin graphics calls since there are so many operations that flush the pipeline currently. So this bug may eventually be closed as a duplicate of some other bug (such as 5091095, which is an RFE for supporting hw-accelerated glyph caching through Direct3D). But in the meantime we will leave it on the list to track this specific slowdown issue. ###@###.### 2004-09-01

WORK AROUND Use -Dsun.java2d.ddoffscreen=false when unplugged Also, play with the PowerPlay settings for the ATI chip. Users can access this through the Advanced button on the Settings tab of the Display Control Panel. Disabling PowerPlay makes unplugged performance equivalent to plugged-in performance (at the cost of higher battery power consumption, presumably). ###@###.### 2004-09-01