Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4354142
Votes 0
Synopsis Floating point performance problem
Category java:classes_lang
Reported Against 2.0_beta
Release Fixed
State 11-Closed, Not Reproducible, request for enhancement
Priority: 4-Low
Related Bugs 4461243
Submit Date 18-JUL-2000
Description




java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

There seems to be a problem with the floating point code generation in Hotspot
on  customer . The following code demonstrates the timing differences between
various versions of the same algorithm.

public class MathTest {

	public MathTest () {
		go(new OriginalCalculation());
		go(new StrictOriginalCalculation());
		go(new NativeOriginalCalculation());
		go(new HackedCalculation());
		go(new NativeHackedCalculation());
		go(new NoDivisionHackedCalculation());
		go(new StrangeDivisionHackedCalculation());
	}
	

	public void go(Calculation c) {
		long ctime = System.currentTimeMillis();
		for (int y=0; y < 533; y++) {
			for (int x=0; x < 800; x++) {
				c.calculation(x, y);
			}
		}
		System.out.println(c.getClass().getName() + " " +
(System.currentTimeMillis() - ctime));
	}



	/**
	 *  Main method
	 */
	public static void main(String [] args) {
		MathTest t = new MathTest();
	}
	
	interface Calculation {
		void calculation(double x, double y);
	}
	
	/* All timings are from a Pentium 3 550Mhz and are in mSec */
	
	/**
	 * Performance: BAD (~1730)
	 * This is the original calculation that doesnt perform well.
	 */
	class OriginalCalculation implements Calculation {
		public void calculation(double x, double y) {
			double radius = Math.sqrt(x * x + y * y);
			double theta  = Math.acos( x / radius);
		}
	}

	/**
	 * Performance: BAD (~1760)
	 * Original calculation with strict floating point switched on
	 */
	class StrictOriginalCalculation implements Calculation {
		public strictfp void calculation(double x, double y) {
			double radius = Math.sqrt(x * x + y * y);
			double theta  = Math.acos( x / radius);
		}
	}
	
	/**
	 * Performance: GOOD (~420)
	 * instead of calling Math routines call a native method which simply
calls
	 * 'C' math library function and returns
	 */
	class NativeOriginalCalculation implements Calculation {
		public void calculation(double x, double y) {
			double radius = MyMath.sqrt(x * x + y * y);
			double theta  = MyMath.acos( x / radius);
		}
	}

	/**
	 * Performance: BAD (~1740)
	 * Split calculation into pieces
	 */
	class HackedCalculation implements Calculation {
		public void calculation(double x, double y) {
			double x2 = x * x;
			double y2 = y * y;
			double radius = Math.sqrt(x2 + y2);
			double ah = x / radius;
			double angle = Math.acos(ah);
		}
	}

	/**
	 * Performance: GOOD (~440)
	 * Isolate to see if calling math lib is the problem
	 */
	class NativeHackedCalculation implements Calculation {
		public void calculation(double x, double y) {
			double x2 = x * x;
			double y2 = y * y;
			double radius = MyMath.sqrt(x2 + y2);
			double ah =  x / radius;
			double angle = MyMath.acos(ah);
		}
	}

	/**
	 * Performance: GOOD (~400)
	 * Ok. So what gives. I am still using the Math library but if i get
rid of the
	 * division everything speeds up...
	 */
	class NoDivisionHackedCalculation implements Calculation {
		public void calculation(double x, double y) {
			double x2 = x * x;
			double y2 = y * y;
			double radius = Math.sqrt(x2 + y2);
			double ah = x; // COMMENTED OUT. / radius;
			double angle = Math.acos(ah);
		}
	}

	class StrangeDivisionHackedCalculation implements Calculation {
		public void calculation(double x, double y) {
			double x2 = x * x;
			double y2 = y * y;
			double radius = Math.sqrt(x2 + y2);
			double ah = x2 / radius;
			double angle = Math.acos(ah);
		}
	}
	

}
(Review ID: 105926) 
======================================================================
Work Around




Use native methods
======================================================================
Evaluation
The test program demonstrates that java.lang.Math.acos is very slow in
comparison to calling a native version in libm. The test program however
has two mistakes in it which caused it to give misleading results. The
class NoDivisionHackedCalculation simply uses the value of the x parameter
(after assigning to ah) to pass to acos. This value is almost always out
of range (acceptable range -1.0 .. 1.0) so acos runs very quickly making it
look like divide was the culprit. Similarly class StrangeDivisionHackedCalculation does the divide but it divides x^2 by the
radius which also is almost always greater than 1.0 and so acos again runs
fast for the invalid values.  So the final result of the investigation is
that java acos is slow but the test program has errors which make it look
like divide is slow.


  xxxxx@xxxxx   2000-07-19

Changing category:subcategory to java:classes_lang to investigate reported speed problem in acos.

  xxxxx@xxxxx   2001-08-09

To investigate this issue, I wrote an acos microbenchmark that called acos 4 different ways

 * java.lang.Math.acos
 * java.lang.StrictMath.acos
 * Java port of fdlibm acos
 * jni call to underlying C libm acos

On both Solaris SPARC and Windows, the jni call was *slower* than Math.acos by about 20% under both 1.3.1 and 1.4 (both client and server compilers).  Closing as not reproducible

  xxxxx@xxxxx   2002-04-19
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang