next up previous print clean
Next: Future Up: Discussion Previous: Jest's advantages

... and disadvantages

Java is slower than C. When interpreted, Java is about 10 times slower. When compiled by a just-in-time compiler, Java is about 2 times slower. Experts predict that standard Java will soon be nearly as fast as C or C++, but probably never as fast as Fortran. Java's run time resolution of all methods that are not declared final and its array bound checks for indexing operations are probably the two features that hurt Jest's performance most. However, we have not yet investigated Jest's performance systematically.

Nevertheless, we intend to use Jest for large scale problems. To improve Jest's performance, we implement computationally intensive routines in C and link them with Jest objects. Java's native method mechanism easily facilitates the linking of C and Java routines. A Java program that invokes a C routine remains platform-independent if the method invocation is programmed to default to the Java version, when a native version is unavailable.

Typically, a Jest programmer prototypes and tests his program in an all-Java version. If the performance is insufficient, the programmer can profile the application and decide which part of the code to replace by a native method. We expect that straightforward numerical code, such as a convolution kernel, might need to be translated from Java to C, while algorithmically complex code, such as a solver, will not.

Alternatively, Jacob and Karrenbach 1997 report a performance comparable to Fortran when they combine Jest, a specialized compiler (JavaParty), and parallel computers in the optimization of a a large-scale geophysical inversion problem. Unfortunately, to yield that performance, their compiler required a non-standard class modifier regarding the distribution of parallelized objects.

Besides better performance, I wish Java contained a primitive type for complex numbers and the ability to overload the array index operator []. For the same reasons that Java offers float and double primitive types, it should include a complex-number primitive type[*]: (1) a complex-number primitive is important in many applications, (2) a class implementation incurs unacceptable inefficiencies, and (3) only a primitive type offers the concise and intuitive arithmetic operators, such as `+'. Alternatively, a complex number can be simply represented by two floats. However, the lack of a single complex-number type and its associated methods is error-prone, tedious, and not object-oriented.

For example, the methods below compute one root of the quadratic equation a x2 + b x + c = 0. The concise first method does not exist in Java, since it uses a complex primitive type. The second method computes the same root but uses a user-defined complex class: It unfortunately obfuscates the simple, original mathematical operation.

Desired method:  

  static Complex root(Complex a, Complex b, Complex c) {
    return  (b - Complex.sqrt(b*b - 4*a*c)) / (2*a) ;

Available method:

  static Complex root(Complex a, Complex b, Complex c) {
    Complex b2      = Complex.multiply(b,b);
    Complex ac4     = Complex.multiply(4,Complex.multiply(a,c)); 
    Complex discrim = Complex.sqrt(Complex.subtract(b2,ac4)); 
    return Complex.divide(Complex.subtract(discrim,b)),
                          Complex.multiply(2,a))); }

Without a primitive type for complex numbers, we must choose between an encapsulating complex-number class or an error-prone representation by a pair of floats. We partially side-stepped this difficulty by implementing a class for an array of complex numbers. Such an array justifies the class overhead, which was prohibitive for a single complex number, and simultaneously hides the representation of a complex number as a pair of floats. However, using individual complex numbers remains inefficient or tedious unless Java adds a complex-number primitive type.

I wish the [] indexing operator could be overloaded in Java. Again, a multi-dimensional array is a fundamental structure in science and engineering applications. Internally the array might be stored as a Java array, a Java vector, or a huge out-of-core data file. Independent of the internal structure, applications need to index the array elements with a general indexing operation. Only the [] indexing operator offers the conciseness that matches the operation's simplicity. Since Java generally does not permit overloading operators[*], only classes with an internal Java array representation can offer the desired [] indexing operator.

For example, the program fragments [*] approximate the second derivative of a one-dimensional array. The first formulation with its natural index expressions is only available if the array is implemented as a native Java array. If the array is a user-defined array (e.g., an out-of-core, a complex number array) or a Java vector, Java's inability to overload the index operator leads to the verbose formulation of the second program fragment.

Desired method:  

  float x[] = new float[10];   // only native Java arrays
  float y[] = new float[10];
  ...
  y[i] =  (-x[i+1] + 2*x[i] - x[i-1]) / 4.0;

Available method:

  Myarray x = new Myarray(10); // using Java's Vector 
  Myarray y = new Myarray(10); // or complex array class
  ...
  y.setElement(i,(- x.ElementAt(i+1) 
                  + x.ElementAt(i  ) 
                  - x.ElementAt(i-1)) / 4.0);

In our applications, we could not forego the conciseness and simplicity of the array index expression and consequently had to pierce the encapsulation of our array-like vector classes to ensure access by index for operators. Therefore, the array-like Rsf vector and its operators are more closely linked than I wish. Additionally, our classes offer function calls to access individual array elements. However, I find such calls unintuitive, especially when the arguments include index and element values (f.setDatum(3,3.f)). I was not able to devise a general solution based on enumerations. In summary, I do not know how to write application classes with concise, but general, indexing operators for array-type data implemented by structures other than the original Java array.

I believe Java's future in science and engineering will be greatly enhanced if those two shortcomings - a primitive complex-number type and overloading the index operator - were redressed. Java designers should not underestimate the importance of science and engineering as sources of innovation and education.


next up previous print clean
Next: Future Up: Discussion Previous: Jest's advantages
Stanford Exploration Project
3/8/1999