Generics are cool

T

Tim Tyler

Lee Fesperman said:
Tim said:
Lee Fesperman said:
Tim Tyler wrote:
IMO, autoboxing sucks.

AFAICS, it's only good if your point of comparison is the previous version
of Java.

Take a slightly less myopic perspective - and surely the best thing is
never to have had primitive types in the first place.

I'd view that as a myopic perspective. Java wouldn't be appropriate for
certain high-performance applications if that were true. [...]

That appears to be the idea that having no primitive types necessarily
involves a performance hit.
True.

Performance may have been one of the reasons why primitive types were
included in Java in the first place - but I think these days the idea
that having everything be an object involves a performance hit is
regarded as a fallacy.

Do you have evidence of significant high performance applications
written in such a language?

Since such languages include Python, C#, Ruby, Scheme, Dylan, ML,
and Smalltalk I'd say yes.
 
C

Chris Uppal

Tim said:
Exactly: in the supplied [but snipped :-(] example, Java 5 behaves
differently from all previous versions of Java - in a manner that is
not backwards-compatible with them.

Can you exhibit code that compiles under /both/ 1.4 and 1.5 and has different
behaviour ? Or, even more interesting if you can find an example, code that
compiles under 1.4 but has different behaviour when run under 1.4 and 1.5 ?

As far as I can see Sun have been pretty careful only to use the cache for
Integers that are "created" via paths that did not exist in 1.4. E.g.
Integer.valueOf(int) uses the cache, and so does auto-boxing, but the
Integer(int) constructor does not, and neither does Integer.valueOf(String).

Perhaps /too/ careful -- though I'm certainly impressed by the care they've
taken, the end result is that the various versions of Integer.valueOf() are no
longer consistent between themselves, nor do they follow the pattern of cache
usage previous set by, say, Boolean.

-- chris
 
C

Chris Uppal

Tim said:
Since such languages include Python, C#, Ruby, Scheme, Dylan, ML,
and Smalltalk I'd say yes.

I'm not sure that I'd lump Python and Ruby in with Scheme, Dylan, ML, and
Smalltalk as being suitable for high-performance applications. Python and Ruby
are (in their standard, interpreted, implementations) considerably slower than
the compiled languages.

Yes, there are applications where throughput is important, and which have been
successfully been implemented in Python and Ruby (Zope comes to mind, and the
new Ruby web framework, the name of which escapes me, seems to be generating
quite a bit of attention too), but such cases depend on the application being
limited by factors such as IO rather than by raw processing power.

(Such applications become more common as machines get faster of course. Indeed
there's an argument to be made that compilation, as an implementation
technology, is an unnecessary complication for many purposes. For instance the
Smalltalk implementation that I prefer to use is unique, among the commercial
implementation, in that it is implemented as a bytecode interpreter (albeit, an
impressively fast interpreter) rather than by JITing -- that looses it a factor
of maybe 2 or 3 compared with the compiled Smalltalks, and maybe 5 or 6
compared with compiled /and optimised/ C, but that makes no noticable
difference for most of my applications.)

BTW, I wouldn't lump C# in with Scheme, etc, here. At least, as far as my
limited understanding of C# implementation goes, I think that it uses
/auto-boxing/ rather than /unboxed/ ints, so the implementation technology is
more like Java's (with consequent compromises in the semantics) than like
Scheme/Smalltalk/ML/et al.

-- chris
 
B

Bent C Dalager

Exactly: in the supplied [but snipped :-(] example, Java 5 behaves
differently from all previous versions of Java - in a manner that is
not backwards-compatible with them.

I see. The difference you referred to was more the presence of
autoboxing than the caching of Integers? If this is the case, I don't
see why the difference is particularly relevant. Noone is going to be
burned by it because code that requires autoboxing wouldn't compile at
all in 1.4 anyway. Well, except if you're writing code using the 5.0
compiler and want the code to be backwards compatible I suppose, but
then your build process should include building for target 1.4 etc.,
which would have you catch it anyway.

Cheers
Bent D
 
B

Bent C Dalager

i just wrote a little test program that loops through and performs a
single addition to an integer 10 million times.

using a primitive integer, the loop takes on average just about 100
milliseconds.

rewriting the program to represent the integer as an Integer object, then
leaving the rest of the loop as it is for the autoboxing/unboxing, the
loop now takes on average about 2000 milliseconds. thats 20x slower!

It would be interesting to know what percentage of your autoboxed
Integer objects got cleaned up by the GC before program exit. If a
majority were, the figure may be accurate, but if you had enough
memory available for most of them to remain unreclaimed, boxing might
be somewhat more expensive than this in a long-running app.

Cheers
Bent D
 
C

Chris Uppal

Dale said:
If Java primitives
were objects just like the current objects that would be a nightmare
performance and understanding wise. The real issue here is value
semantics vs. reference semantics.

I don't want to sound hostile, but this is completely wrong.

Take a look at a typical Smalltalk implementation. (BTW, this post isn't
intended as a plug for Smalltalk -- though readers are welcome to take it that
way if they wish -- but as an experience report from someone who has used a
language with the features under discussion.)

The typical /implementation/ strategy is the old "unboxed representation" trick
(encoding smallish int values in what otherwise would be a pointer to an
object's physical representation -- /NOT/, please note, auto-boxing, which
would indeed be a performance problem). This does cause a small slowdown
relative to the use of "raw" primitive types, which -- in the case of
Smalltalk -- is exacerbated by the dynamic nature of its type system making it
harder (but not impossible) for the JIT to optimise arithmetic operations, but
the slowdown is fairly small (I don't have figures for modern implementations,
but I'd guess 10-20% for raw arithmetic) and would easily be accommodated for
/most/ purposes.

For integer values that need more than about 30 bits the system must switch to
a boxed representation. That indeed causes a noticeable slowdown (mainly
because of all the object allocations), but on the other hand there is no
problem with integer overflow (I still can't understand why Java -- supposedly
so safe -- allows /silent/ integer wraparound by default).

That's the implementation side. Now for the semantics. To be honest I don't
really understand what you think the problem would be. In Smalltalk integers
are objects, and that causes no problems that I can see. It's not obvious to
me what value "value semantics" would be supposed to add. Integers are either
BigIntegers (boxed) or SmallIntegers (unboxed), both are subclasses of Integer.
Integer and Float are subclasses of Number. Normal class-based polymorphism is
used extensively and in complete accordance with how all the other objects
work. No need for "widening conversions", overloaded arithmetic operators (0.1
+ 22) and all the other junk that Java has to add to its semantics in order to
hack around the problems caused by primitive types. It all works very well.

BTW, I'm not saying that it would be appropriate for a language like Java not
to have primitive types at all. The nature of the language (specifically its
type system) means that they could be included as an expert-friendly feature
available for use by people who knew what they were doing when (say) adding two
integers together, or comparing two floats. But what I /do/ think is that
machine primitives should never have been the /default/ representation of
numbers.

-- chris
 
D

Dale King

Chris said:
Dale King wrote:



I don't want to sound hostile, but this is completely wrong.

If it is wrong, then you did not show that it was wrong. I said that if
Java primitives were just like normal java objects that would be bad.
You go on to describe a system where they could be treated in a way that
is *NOT* like normal Java objects.
Take a look at a typical Smalltalk implementation. (BTW, this post isn't
intended as a plug for Smalltalk -- though readers are welcome to take it that
way if they wish -- but as an experience report from someone who has used a
language with the features under discussion.)

The typical /implementation/ strategy is the old "unboxed representation" trick
(encoding smallish int values in what otherwise would be a pointer to an
object's physical representation -- /NOT/, please note, auto-boxing, which
would indeed be a performance problem). This does cause a small slowdown
relative to the use of "raw" primitive types, which -- in the case of
Smalltalk -- is exacerbated by the dynamic nature of its type system making it
harder (but not impossible) for the JIT to optimise arithmetic operations, but
the slowdown is fairly small (I don't have figures for modern implementations,
but I'd guess 10-20% for raw arithmetic) and would easily be accommodated for
/most/ purposes.

IMO 10-20% slowdown pretty much falls in the "nightmare" category.
For integer values that need more than about 30 bits the system must switch to
a boxed representation. That indeed causes a noticeable slowdown (mainly
because of all the object allocations), but on the other hand there is no
problem with integer overflow (I still can't understand why Java -- supposedly
so safe -- allows /silent/ integer wraparound by default).

Once again you agree that it would have performance problems.
That's the implementation side. Now for the semantics. To be honest I don't
really understand what you think the problem would be. In Smalltalk integers
are objects, and that causes no problems that I can see. It's not obvious to
me what value "value semantics" would be supposed to add. Integers are either
BigIntegers (boxed) or SmallIntegers (unboxed), both are subclasses of Integer.
Integer and Float are subclasses of Number. Normal class-based polymorphism is
used extensively and in complete accordance with how all the other objects
work. No need for "widening conversions", overloaded arithmetic operators (0.1
+ 22) and all the other junk that Java has to add to its semantics in order to
hack around the problems caused by primitive types. It all works very well.

Another way of saying value vs. reference semantics is copy vs.
reference semantics or aliasing.

Consider these:

Object o1 = new Object();
Object o2 = o1;

int i1 = 5;
int i2 = i1;

There are vastly different semantics for these two. o1 and o2 both refer
to the same object, but i1 and i2 are copies of the same value. O1 is an
alias for o2.

There are all sorts of combinations of semantics in various languages,
but all I am saying is that it would be a pretty major shift in
semantics for Java to have numeric values be "objects". The only
semantics that Java has for objects (reference semantics) would not
necessarily be the best for numerical values.
BTW, I'm not saying that it would be appropriate for a language like Java not
to have primitive types at all. The nature of the language (specifically its
type system) means that they could be included as an expert-friendly feature
available for use by people who knew what they were doing when (say) adding two
integers together, or comparing two floats. But what I /do/ think is that
machine primitives should never have been the /default/ representation of
numbers.

And I was saying that the nature of the language means that it would not
be appropriate. It would take a major change to the language, not only
in technical ways but in basic understanding of the semantics of the
language. I'm not saying that Java could not have been created with more
object-like primitives, but it would be different than what the objects
are right now.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top