Home  Introduction  Complex numbers  Newton's method  Newton's method with complex numbers  Fractals  Optimisations  Performance

Search this site:
Threads Database Profiling Regular expressions Random numbers Compression Exceptions C Equivalents in Java
 Got a question about Java? Java discussion forum

The cost of Java object orientation in mathematical calculations: optimisations

So far, we have used a ComplexNumber class to encapsulate complex numbers in our calculation of a Newton's method fractal. We have also made the class immutable for maintainability.

On this page, we consider two optimisations, both of which trade ease of coding and maintainability for improved performance:

  • making ComplexNumber mutable;
  • doing away with the class altogether, and performing calculations simply with double variables.

Optimisation 1: A mutable version of ComplexNumber

Firstly, then, we consider a mutable version of the ComplexNumber class: i.e. one whose components are not final, and where calling operator methods such as add(), multiply etc actually modifies the object it is called on rather than returning a new object. For example, the add method looks as follows:

public ComplexNumber add(ComplexNumber other) {
  this.real += other.real;
  this.imag += other.imag;
  return this;
}

To make some of the calling code more succinct, we make each method return this so that we can chain methods together, but no new object is actually created: each number object's operator method always returns "itself". Notice that we now have to make a slight modification to the iterate() method:

private void iterate() {
  ComplexNumber x = new ComplexNumber(this.xr, this.xi);
  iter = -1;
  for (int i = 0; i < 100; i++) {
    ComplexNumber num = (new ComplexNumber(x)).multiply(x).addReal(-4d);
    ComplexNumber denom = (new ComplexNumber(x)).multiplyReal(2d);
    ComplexNumber frac = num.divide(denom);
    x = x.subtract(frac);
    // ... as before ...

Essentially, any time that we want to make a calculation based on a particular number but still retain the original value of that number, we need to remember to construct a new copy of that number. It's easy to see how we could introduce bugs by forgetting to do this! We should also note that our immutable class is no longer thread-safe without some extra provision.

On the upside, all operator methods where we don't explicitly create a new ComplexNumber object will now re-use the same object, in principle improving performance. In a moment, we'll see just how much or how little it does improve performance in practice.

Optimisation 2: eliminating ComplexNumber

The second optimisation we consider is to do away with the ComplexNumber class altogether. In effect, we declare local double variables to represent real and imaginary components as we need them, and "inline" the raw calculations (which were encapsulated in methods on ComplexNumber) as required. A possible implementation is as follows:

private void iterate() {
  double xreal = this.xr;
  double ximag = this.xi;
  iter = -1;
  for (int i = 0; i < 100; i++) {
    // calculate (a+bi)/(c+di), where:
    //   a+bi is x**2-4
    //   c+di is 2x
    double a = xreal * xreal - ximag * ximag - 4;
    double c = 2 * xreal;
    double b = c * ximag;
    double d = 2 * ximag;
    double divreal = (a * c + b * d) / (c * c + d * d);
    double divimag = (b * c - a * d) / (c * c + d * d);
    // The result of this division is the adjustment to x
    if (divreal == 0 && divimag == 0) {
      iter = i;
      break;
    }
    xreal -= divreal;
    ximag -= divimag;
  }
  this.xrResult = xreal;
  this.xiResult = ximag;
}

In this case, our expression x2-4 is about as simple as they get. It's easy to see how with more complex expressions, writing out the calculation code "by hand" could quickly become unweildy and prone to bugs.

Nonetheless, there's no denying that from a performance point of view, this method has the advantage of eliminating all object management overhead.

Performance of these optimisations

On the next page, we discuss the performance gain from these optimisations.


Unless otherwise stated, the Java programming articles and tutorials on this site are written by Neil Coffey. Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles, or if you simply have a programming question that you would like to see answered on this site. Most topics will be considered. But in particular, the site aims to provide tutorials and information on topics that aren't well covered elsewhere, or on Java performance information that is poorly described or understood. Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Javamex UK 2010. All rights reserved.