"Original Sin" (Would Java be Better Off Without Primitives?)
Gilad Bracha reopens an old debate about language design, specifically can a language be OO and enforce a primitive type system? In his Room 101 blog post he makes the assertion: "I’ve often said that Java’s original sin was not being a pure object oriented language - a language where everything is an object." The main issue addressed in the post is not on the value of being a pure object oriented language; rather, it addresses the question of whether it would be possible for Java to be as efficient as it is without primitive types. The answer is yes."
Gilad begins his argument with a simple example of how typing create problems. The Java char type was initially represented with 16 bits (in accordance with the Unicode standard at the time) but when the standard changed, "people dealing with unicode in Java have to deal with encoding code points themselves." Turning to the issue of performance, he provides several examples of how to get objects without impairing efficiency. One example
So how would we go about getting rid of primitive types without incurring a significant performance penalty?
Java has a mandatory static type system; it is compiled into a statically typed assembly language (Java byte codes, aka JVML). It supports final classes. I do not favor any of these features, but we will take them as a given. The only changes we will propose are those necessary to eradicate primitive types.
Assume that the we have a final class Int representing 32 bit integers. The compiler can translate occurrences of this type into type int. Hence, we can generate the same code for scalars as Java does today with no penalty whatsoever.
More interesting examples follow, including: methods whose names are operators, forcing Ints to behave as values, the == operato, instance locking, and array covariance.
All in all - Java could have been purely object oriented with no significant performance hit. But it wasn’t, isn’t and likely won’t. Sic Transit Gloria Mundi.
The responses to this post are mostly in agreement with Gilad's points.
Some selected responses:
- Daniel Speiwak - Sounds a lot like Scala, actually. As a point of interest, Odersky and friends have recently come up with an interesting solution to the covariant arrays + unboxed primitives issue: generic type specialization.
- abies -- I'm afraid it is not that simple. While I agree that it is possible to have quite efficient encoding of primitive types as objects there is always a cost. Smalltalk is a good example here - most implementations are having small/large integer distinction in implementation, with small integers being disguised inside a non-rounded pointers. This suddenly means that you have quite different performance for integers crossing certain barrier - and bit worse performance for every integer out there. I, for one, enjoy the fact that java has possibilities to be as fast as C++/Fortran for math crunching code.
- Osvaldo Doederlein -- The discussion about OO vs primitive types should really start with this challenge: name at least one pure OOPL that doesn't exhibit any sigificant performance penalty over languages with primitive scalars/arrays. And don't fool me with high-level application benchmarks; I want that top performance in math/array microbenchmarks, or real-world low-level algorithms like data compression, video encoding, network stacks, etc.
The discussion also includes some technical examples that serve mostly to illustrate the divide between the two sides.
Perhaps the most interesting aspects of this specific instance of the "Great OO Debate" are the issues that are not raised. Some examples:
- The efficiency versus OO purity was the core point of the language wars between Smalltalk and C++ in the 80's and early 90's (well before Java existed) and was a totally irrelevant argument because it ignored the reason that OO languages were created. The purest OO languages at that time were Smalltalk and Self, and both explicitly sought to emulate the example of Simula (not Simula I) by creating a language that supported domain experts to express their problems and solutions easily and directly. It was well understood that this would impair machine efficiency and performance and that was OK!
- This author has seen Smalltalk programs that outperformed C++ programs in embedded, millisecond time-budget, switching applications and real-time graphics display systems (in jet fighters). Programming tricks were employed (e.g. pre-compiling methods and the fact that Smalltalk objects can directly interact with hardware and are not dependent on operating systems) to gain performance. The real payoff was the fact that overall development time was reduced to 1/3 the time to write the equivalent C++ programs.
- Java was never really intended to be an OO language. If Sun had not been thwarted in its efforts to license Smalltalk (a purely business mistake on ParcPlace's part), Java would never have existed. Oak would have continued along the evolutionary path leading to "smart toasters" instead of becoming the foundation for Java. And the express purpose of Java was to blend the best features of Smalltalk and C++, not to be a pure OO language.
- Code and language "features" is the absolutely wrong place to debate the value of OO purity. Objects are a metaphorical tool that allows the developer to best understand the problem domain and which leads to radically different, simpler, and more efficient designs and architectures. Having a language that is pure OO, "everything is an object," merely means you can directly express you designs without worrying about how those designs are implemented and executed at the machine level.
It would be really interesting to see the pure OO / efficiency debate based on why languages are the way they are and if objects really do provide a way to create designs where absolute machine execution efficiency is not an issue.
Martin Thompson Jul 27, 2014