Swing Performance OS X 10.6 vs. Windows 7

Hello there Java Gurus! ;D

This is my first post to this forum, I have about 6 months of experience of Java in general, and about 1 month of Java GUI programming (Swing), so consider me as a Java newbie. :wink:

I started to develop a simple 2D shooter game with Java swing as a hobby project. I am using Java 1.6.0_65 with Mac OS X 10.6.8, Macbook Pro 2.4 GHz Intel Core 2 Duo (Spring 2010 model), the display card is NVIDIA GeForce 320M.

In my paint method, I draw about 30-50 rectangles with Swing drawRect() method, sizes of 32 * 32 pixels, few are of 7 * 7 pixels of size, the smaller ones are filled with fillRect. I call the paintComponent() method 50 times/sec from a timer callback.

To get some kind of idea of how fast/slow the painting is, I added some measurement code:



      public void paintComponent(Graphics g) 
      {
          long startTime = System.nanoTime();
 
          //
          // call the drawing methods here
          //

    	  // for debugging paint speed
    	  long endTime = System.nanoTime();
    	  if (paintDurationBufferIdx < DURATION_BUFFER_LEN)
    		  paintDurationBuffer[paintDurationBufferIdx++] = (int)(endTime - startTime) / 1000;
    	  else
    	  {
    		  long avg = 0;
    		  for (int ii = 0; ii < DURATION_BUFFER_LEN; ii++)
    			  avg += paintDurationBuffer[ii];
    		   avg /= DURATION_BUFFER_LEN;
    		  
    		  System.out.println("Paint avg. duration: " + avg + " us");
    		  
    		  paintDurationBufferIdx = 0;
    	  }  


Average execution time per single paintComponent() seems to be about 3000 usec.

I also run same code in couple for Windows 7 PCs (Sony Vaio laptop, AMD dual core 2.x GHz and HP laptop, Intel quad core, 2.x GHz, don’t remember all details now). In Windows machines, average execution time was only about 100 us, that is about 30 x faster!

What can explain such a big difference? Can System.nanoTime() work with different resolutions between Windows 7 & OS X, or is painting really that slow in OS X?

On the other hand, I also measured average execution time of the non-GUI related part of my game engine (moving of objects, collision detections etc.), and it was between 50 - 100 us on both system, so maybe System.nanoTime() is reliable, and painting really is that slow in OS X?

Hi

Don’t use Swing if you want to obtain consistent performance across platforms, rather use OpenGL (JogAmp or … whatever).

I am getting paint durations between 1400 - 1800 us on OS X 10.6 with this simple test app:


// 
// Simple application to test Java Swing performance on Mac OS X vs. Windows
//

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class SwingSpeedTest_GUI {
   
	private static class SwingSpeedTestGUI extends JPanel
	{	   	  
		private TimerCallBack actionTimer = null;
		private Timer timer = null;
	  
		// for debugging paint speed
		private static final int DURATION_BUFFER_LEN = 1500; // 30 sec
		private int   paintDurationBufferIdx;
		private int[] paintDurationBuffer;
	  	  
		// constructor
		SwingSpeedTestGUI(int timerTick_ms)
      {		  		    
			actionTimer = new TimerCallBack(this);
			timer = new Timer(timerTick_ms, actionTimer);
		  
			paintDurationBuffer = new int[DURATION_BUFFER_LEN];
			paintDurationBufferIdx = 0;
		}
	  
		void start()          { timer.start(); } // start paint timer	  	  	  
		public void rePaint() { repaint();     } // repaint
	   
		// paint method
		public void paintComponent(Graphics g) 
		{
			long startTime = System.nanoTime();
    	  
			super.paintComponent(g);
			  
			int cornerX = 10;
			int cornerY = 10;
			int x = cornerX;
			int y = cornerY;
		  
			// draw bigger squares
			for (int i = 0; i < 40; i++, x += 60)
			{	  
				Color cSaved = g.getColor();
				g.setColor(Color.RED);			  
				g.drawRect(x, y, 34, 34);
				g.setColor(cSaved);
			  
				if (x > 750) { x = cornerX - 60; y += 60; } 
			}

			// draw smaller, filled squares
			x = cornerX + 800;
			y = cornerY;
		  
			for (int i = 0; i < 20; i++, x -= 25, y += 25)
			{	  
				Color cSaved = g.getColor();
				g.setColor(Color.RED);			  
				g.drawRect(x, y, 7, 7);
				g.fillRect(x,y , 7, 7);
				g.setColor(cSaved);
			}
		      	  
			// for debugging paint speed
			long endTime = System.nanoTime();
			if (paintDurationBufferIdx < DURATION_BUFFER_LEN)
				paintDurationBuffer[paintDurationBufferIdx++] = (int)(endTime - startTime) / 1000;
			else
			{
				long avg = 0;
				for (int ii = 0; ii < DURATION_BUFFER_LEN; ii++)
					avg += paintDurationBuffer[ii];
				avg /= DURATION_BUFFER_LEN;
				System.out.println("Paint avg. duration: " + avg + " us");
				paintDurationBufferIdx = 0;
			}  
		}
      
		private static class TimerCallBack implements ActionListener 
		{   
			private SwingSpeedTestGUI gui = null;
   	        	  
			// constructor
			TimerCallBack(SwingSpeedTestGUI gui)
			{
				this.gui = gui;
			}
   	   
			// timer callback method
			public void actionPerformed(ActionEvent evt) 
			{
				gui.rePaint();
			}   	   	
		}
	}
   
	public static void main(String[] args) 
	{
		JPanel container = new JPanel();
		container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS)); 
		SwingSpeedTestGUI gui = new SwingSpeedTestGUI(20);
		container.add(gui);
	   
		JFrame window = new JFrame("SwingSpeedTestGUI");
		window.setContentPane(container);
		window.setSize(900, 700);
		window.setLocation(0, 0);
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		window.setVisible(true);
	   
		gui.start();
	}
}

Of course it runs different, the OS processes commands differently, and unless you’re also running Windows 7 on the same computer, your hardware will also process the code differently, resulting in different frame rates. You can’t expect the same performance on both operating systems, it just won’t happen unless I’m missing something major here.

I am running Windows 7 on Sony and HP laptops, and the HW should be quite equal in terms of raw CPU power.

Anyway, 30* faster performance on Windows 7 PCs just amazes me!!! :o

Just another reason to switch from OSX to either Windows or a slim *nix distro :wink: