Profiling JPARSEC
Table of Contents

Profiling JPARSEC

My next main milestone is to release a new version of the ephemerides server, and since I'm now working on this full time my intenction is to re-design it almost completely with better charts. To achieve this the first step is to finish the implementation of sky and planetary rendering, improving performance and image quality, reducing memory footprint, and eliminating all bugs. This is the task I did in the last month. Visual quality is now much better since I use some star textures to produce very realistic images. Besides the textures of the Milky Way I also use now the textures of deep sky objects in the same way as Stellarium. To improve performance I have used the profiling tool JVisualVM already included in the Java 6 SDK. JVisualVM is a great tool to see which methods are consuming the CPU power, allowing to put more care in those parts of the code. These are the main steps and fixes in the profiling process.

  • Analysis of the code before using JVisualVM: Besides eliminating innecesary operations I set the Projection.INVALID_POSITION value to null, resulting in much lower memory consumption and better performance. I was unable to see more things to improve without using a profiling tool.
  • Profiling 1: I found an important fraction of the CPU time in LocationElement.getApproximateAngularDistance (due to the use of Math.acos, which is slow), Ephem.getApparentElevation, and RenderPlanet.fromPlanetEquatorToFromOtherDirection. The solution I applied was a great improvement in FastMath class with the implementation of new functions (acos, hypot), the implementation of getApproximateAngularDistance in Projection class with better performance, and some reduction in the number of operations in Projection. For the new functions of FastMath I used the library by Bill Rossi (also called FastMath), integrated in Apache Commons Math. In Ephem.getApparentElevation I implemented the possibility of reducing the number of iterations.
  • Profiling 2: In the second iteration with JVisualVM I found that the Java method Graphics.fillOval and some methods in DataSet were very slow. As a solution I used BufferedImage.setRGB when the size of the oval is 1 or 2 pixels. A great performance improvement was noticeable in planetary rendering. The methods in DataSet class were also revised.
  • Test of performance without profiling: JVisualVM showed no signs of problems, but when I enabled and disabled the visualization of each kind of objects I noticed that RenderSky.drawSky had a problem when drawing the star labels (very slow). The problem was an ArrayList getting too big. Another slowdown was noticeable in the drawAxes method using a GeneralPath object. Despite of using the same object when drawing the Milky Way or the limits of constelations, the one that draws the coordinate grid was the only one too slow. It seems the problem is related to both the number of pixels modified (that depends on the stroke) and the number of times the path line crosses or cuts itself. I reimplemented the method calling Graphics.drawLine, which was about 50% faster, but still apparently too slow. I implemented it again using the Graphics.drawPolyLine to draw all lines at once from an array. In a little test I found this should be 3 times faster (unless the number of lines is really big), but when applying this to the RenderSky.drawAxes method I saw no improvement at all. Another performance improvement was possible when drawing labels without superimposing one on top of another.
  • Profiling 3: The only method consuming a relevant fraction of the CPU time was Graphics.drawLine. It is apparently not possible to fix. DrawPolyLine is not a solution either. I was also worried by the possible slowdown due to the use of a Graphics interface with some overload in the methods and an important number of casts. I did a test without all this and found, to my surprise, a performance improvement of only 5%, which is extremely slow compared to the gain I obtain, the possibility of rendering everything in Android.
  • Final touches: The Milky Way drawing process had some bugs, but these problems were not the cause of the bad filling of the Milky Way by the GeneralPath.fill method of Java. To solve this I applied the Queue-Linear Flood Fill algorithm by J. Dunlap, firstly implemented in Java by Owen Kaluza. It is not as fast as the Java method, but at least it works very well. A lot of other details and bugs were fixed in RenderSky and SkyChart classes.


With all these improvementes the performance is around 50% better in wide fields of view and almost 100% faster in fields of view below 50 degrees, using Java 6. This is very important for the Android port, which is clearly much faster now. Memory consumption is similar, but the memory peak is lower in Android. I have eliminated the possibility of using several threads since there's no improvement at all. Another nice thing is that after all this the performance in Java 7 is around 80% faster compared to Java 6, which is impressive since before the profiling the performance in Java 7 was 5-10% better only. With Java 7 it is possible to drag the sky with stars up to magnitude 7 at 30 fps and full screen mode in my Core i5 PC, which is impressive and only comparable in performance to that of KStars, which is now clearly below in visual quality.

blog/profiling_jparsec.txt · created: 2012/10/08 16:00 (Last modified 2016/05/17 12:51) by Tom├ís Alonso Albi
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki