Java 1.5 Generics & Unboxing performance

  • Thread starter brian.vanheesch
  • Start date
B

brian.vanheesch

What are the benchmarks of using generics instead of just continuing
with casting?

I understand the clean-code & compile time data-type checking that
Generics provides. I need to understand the performance benefits
versus code rewriting costs.

If there is minimual performance gain (or performance loss), then it
makes no sense to have my team juniors scan through Java classes &
convert them to Generics.

Same question for unboxing: is

Integer bigEye = 15;

faster/slower than

Integer bigEye = new Integer(15);

(or is the compiler just doing that translation for us now?)
 
T

Timbo

What are the benchmarks of using generics instead of just continuing
with casting?
None. The bytecode that is generated is exactly the same.
I understand the clean-code & compile time data-type checking that
Generics provides. I need to understand the performance benefits
versus code rewriting costs.

If there is minimual performance gain (or performance loss), then it
makes no sense to have my team juniors scan through Java classes &
convert them to Generics.
Perhaps not (although I like type-safety so I did change a lot of
the code that I was doing when I first upgraded my compiler), but
they are worth using in the future IMO. Others will disagree...
just a matter of opinion.
Same question for unboxing: is

Integer bigEye = 15;

faster/slower than

Integer bigEye = new Integer(15);

(or is the compiler just doing that translation for us now?)
According to Sun, there is a slight performance overhead. From
this paage:
http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html

"The performance of the resulting list is likely to be poor, as it
boxes or unboxes on every get or set operation. It is plenty fast
enough for occasional use, but it would be folly to use it in a
performance critical inner loop."
 
O

Oliver Wong

What are the benchmarks of using generics instead of just continuing
with casting?

I understand the clean-code & compile time data-type checking that
Generics provides. I need to understand the performance benefits
versus code rewriting costs.

If there is minimual performance gain (or performance loss), then it
makes no sense to have my team juniors scan through Java classes &
convert them to Generics.

Doing so might allow you to discover bugs by giving you compile errors
that might have only shown up at runtime.
Same question for unboxing: is

Integer bigEye = 15;

faster/slower than

Integer bigEye = new Integer(15);

(or is the compiler just doing that translation for us now?)

I believe "Integer.valueOf(15)" is better than both of the above, as the
VM may cache common used Integer objects.

- Oliver
 
R

Ranganath Kini

Java's Generics feature uses type-erasure technique and hence when you
compile a generic enabled code, all the type information is lost in the
compiled code and the code ultimately works with the classic
java.lang.Object in place of the generic type.

This type-erasure technique according to Sun, is used to provide for
backwards compatibility to allow non-generic code to work with generic
code.

One possible advantage I see between traditional non-generic and
generic code is that, in the non-generic code, the compiler had to add
extra code to check the casting and type conversion operations that you
use. With generics code, these code checks need not be added when
emitting the final bytecodes and hence may marginally improve
performance. But I have no proof to support this point.

If you want to know if its worth retrofitting your old non-generic code
with the generics feature, I wud say its really not worth doing so, for
two reasons:

1. There is no difference or marginal difference btwn generics and
non-generic code at the byte code level.

2. Sun does not expect customers and developer to redesign their code
due to generics. The idea behind implementing Generics feature using
the type-erasure technique obviously is to support classic non-generic
code with the same honesty. If u were to do the redesign, ure
effectively defeating the backward compatibility issue and only
expending more effort to re-invent the wheel (sort-of).

Although if ure a class library developer, i.e. u design and develop
class libraries containing reusable code, u cud consider adding
Generics support to enable your customers to take advantage of the
language feature.

In my personal opinion, Generics feature is just a syntax luxury, tats
all. It pampers developers by having the compiler do all the dirty
(casting/conversion) work in a safe manner. (tat sounds so much like
Microsoft solutions right? ;-) )

Anyways, here is a link of a comparitive test btwn generic vs.
non-generic code which may throw more light on the issue:

http://www.oreillynet.com/pub/wlg/8126?wlg=yes

Hope it helps!
 
R

Roedy Green

What are the benchmarks of using generics instead of just continuing
with casting?

It gives you no benefit or penalty. It generates the exact same
run-time code. Generics are purely a compile time check.
 
C

Chris Uppal

I understand the clean-code & compile time data-type checking that
Generics provides. I need to understand the performance benefits
versus code rewriting costs.

There are none. No losses either.

Same question for unboxing: is

Integer bigEye = 15;

faster/slower than

Integer bigEye = new Integer(15);

To a first approximation they are the same. If you /really/ care about the
performance of such a trivial operation[*], then the first is likely to be a
fraction faster since the compiler will emit code to utilise the new, and
marginally faster, Integer.valueOf(int) method.

([*] and if you do care then you /definitely/ shouldn't be using the "wrapper"
classes at all, with or without autoboxing.)

-- chris
 
C

Chris Uppal

Timbo said:
According to Sun, there is a slight performance overhead. From
this paage:
http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html

"The performance of the resulting list is likely to be poor, as it
boxes or unboxes on every get or set operation. It is plenty fast
enough for occasional use, but it would be folly to use it in a
performance critical inner loop."

That's talking about the performance of using the wrapper classes at all.
Whether you create your wrapper instances explicitly yourself, or the compiler
does it automatically for you makes little or no difference (depending on which
API you use). The warning from Sun is valid, since you might not realise that
autoboxing was translated into use of the wrapper classes. But in this case
the OP is comparing autoboxing with explict use of wrappers.

-- chris
 
T

Tony Morris

Same question for unboxing: is
Integer bigEye = 15;

faster/slower than

Integer bigEye = new Integer(15);

(or is the compiler just doing that translation for us now?)

The latter is slower (with some assumptions in place).
If you substitute 15 with 1555, things change.
You will almost certainly hear some erroneous over-simplifications on this
topic - I urge you to find things out for yourself to avoid potential
misleading.

Here's some fun:
http://jqa.tmorris.net/GetQAndA.action?qids=7
 
R

Roedy Green

The latter is slower (with some assumptions in place).
If you substitute 15 with 1555, things change.
You will almost certainly hear some erroneous over-simplifications on this
topic - I urge you to find things out for yourself to avoid potential
misleading.

How could that be you wonder. Java is free to do the boxing with any
method it wants. It can inline some prebuilt Integer constants or use
a factory method that does so. You can get away with that because
Integer is immutable.
I presume with new Integer( i ) it may take you literally.
 
T

Tony Morris

Java is free to do the boxing with any
method it wants.

No it is not free.
It is fixed by the language specification that only those with the range
[-128 127] will result in a common Integer instance.
 
R

Roedy Green

Java is free to do the boxing with any
method it wants.

No it is not free.
It is fixed by the language specification that only those with the range
[-128 127] will result in a common Integer instance.

It never occurred they would "box" themselves in that way. I guess
the problem is people puzzled by == behaving strangely or
unpredictably.

They can still use any method to get that result, either direct
inlining or a method that produced one of those prebuilt Integers.

I guess then they constrained new Integer NOT to do that. Too bad
because 99% of the time that is what you want.
..
 
T

Tony Morris

Roedy Green said:
Java is free to do the boxing with any
method it wants.

No it is not free.
It is fixed by the language specification that only those with the range
[-128 127] will result in a common Integer instance.

It never occurred they would "box" themselves in that way. I guess
the problem is people puzzled by == behaving strangely or
unpredictably.

They can still use any method to get that result, either direct
inlining or a method that produced one of those prebuilt Integers.

I guess then they constrained new Integer NOT to do that. Too bad
because 99% of the time that is what you want.
.

My explanation is quite lengthy and prone to criticism from "the other side
of the fence", so I put myself at risk when
a) I attempt it without sound premise.
b) I attempt it on an internet forum such as Usenet, where your target
audience is generally at the bottom end of intellect (and so here I am).
I'll give it a small shot anyway.

The problem is actually the result of the exposing of a constructor, which
implicitly exceeds requirements.
A client has never cared about "newness" of an object, only the contracts
that that object supports.
In the event that the object is mutable (such that an effect of the
invocation of an operation can be observed on some other operation), then
still "newness" has never mattered - merely, identity of the object
(contract implementation identity) such that operation O can be invoked on
'some supporting subject' (A), have an effect observed, while operation O
can also be invoked at some other time and have an effect observed on 'some
other supporting subject' (B), but not A. Since we distinguish A and B, then
this implies that they have identity - whether or not they are new, is never
relevant. This all assumes an OO paradigm (which has an awful contradictory
paradox, which I have omitted).

Since Integer is both immutable (cannot have a side effect observed after
invocation of an operation - or simply, all of its operations a monadic (see
Monads - Haskell)) and it exposes a constructor (exceeding requirements),
Sun have had to concede at some point that they believe will be optimal for
a general set of use cases. This atrocity is quite minor in the greater
scheme of all atrocities that are evident in the language.

ContractualJ prohibits the use of constructors: "All constructors are
declared private, and throw java.lang.UnsupportedOperationException, unless
they are implicit constructors of anonymous classes. Exposing construction
details (as Java constructor semantics implies) is not permitted." [
http://contractualj.com/ ] and attempts to demonstrate the optimal
workarounds (but still far from optimal once you exclude the premise of Java
itself) within the given context (that is, Java).

Although this explanation is far from complete, I am trying to complete a
publication that touches on this topic. The publication is a preliminary to
the release of my language specification (which is even more far from
complete).
 
P

Piotr Kobzda

Tony said:
The latter is slower (with some assumptions in place).
If you substitute 15 with 1555, things change.

According to the language specification things _may_ change, but don't
have to.
You will almost certainly hear some erroneous over-simplifications on this
topic - I urge you to find things out for yourself to avoid potential
misleading.

Agreed. Right place is chapter 5.1.7 Boxing Conversion of JLS3:
http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7

The answer provided there is incorrect.

Better answer than f) is b).

Depending on implementation 777 may be boxed as the same instance each time.
A direct consequence is the following answer:

- true false false|true false

Based on Boolean logic rules, false|true is true. Which gives b).


In fact, the correct answer is:

i) something else _f)_or_b)_


Regards,
piotr
 
T

Thomas Hawtin

Tony said:
Java is free to do the boxing with any
method it wants.

No it is not free.
It is fixed by the language specification that only those with the range
[-128 127] will result in a common Integer instance.

No. Those ints in the range [-128, 127] will certainly always box to the
same instance, but those outside that range may or may not. For longs
even those within the range may not box to the same instance.

Tom Hawtin
 
T

Tony Morris

Piotr Kobzda said:
According to the language specification things _may_ change, but don't
have to.


Agreed. Right place is chapter 5.1.7 Boxing Conversion of JLS3:
http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7

The answer provided there is incorrect.

Better answer than f) is b).

Depending on implementation 777 may be boxed as the same instance each time.
A direct consequence is the following answer:

- true false false|true false

Based on Boolean logic rules, false|true is true. Which gives b).


In fact, the correct answer is:

i) something else _f)_or_b)_


Regards,
piotr

You're right - I created that question while the JSR was in discussion, and
I became aware of the error later, but forgot about it.
I will correct it, thanks.
 

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,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top