Java 7 features

R

Roedy Green

I thought "No Operator Overloading" was an argument for favoring Java
over C++.

the problem is not operator overloading, when the overloaded operators
follow the usual rules of math. The problem comes with totally
unrelated functions are assigned operators, e.g. C++ reusing the shift
operators for i/o, or Java reusing + for contatenation.
 
T

Twisted

I am wondering if parallel logic in the chip is the secret of the
speed of the nested if. Perhaps it can do several lookaheads.

Could be. Branch prediction is clobbered by jump tables. I wonder if
dynamic method dispatch uses a binary tree approach instead of vtable
approach to take advantage of branch prediction in any of these VMs or
in Jet?

As for examining the assembly produced by Jet, why not simply
disassemble the object code it outputs?
 
J

Jacques-Olivier Haenni

Hello,

Guillermo said:
If we had closures (and unnamed functions a la Smalltalk), we could
use HashMaps instead of switch statements.

At my opinion, that's the very interesting thing in closures. You can
then add new functionalities such as the 'switch-on-map' mentionned in
some previous post, or an (enhanced) 'for each' loop, or some thread
management functionalities only by modifying the API, without any other
change to the JVM ! (The API is easier to modify than the JVM, whether
it be by one of us or even by Sun.)

Ok, this could be done already now in a large extent with anonymous
classes, but the amount of boilerplate code to write make such solutions
quite heavy to use.

JO.
 
T

Twisted

Ok, this could be done already now in a large extent with anonymous
classes, but the amount of boilerplate code to write make such solutions
quite heavy to use.

In a way, heavy use of closures for basic flow control and such is
"quite heavy to use" anyway, in terms of CPU and memory use. Have you
ever noticed that Smalltalk is v...e...e...e...e...r...r...r...y
s...l...o...o...o...w...w ?

CPUs themselves probably need a redesign to cope with the sort of code
in question. Procedural code with branching conditionals is what they
natively execute. In cases where closure-based constructs can be
compiled down to such a thing on a JIT basis you're golden, but
otherwise...
 
R

Roedy Green

As for examining the assembly produced by Jet, why not simply
disassemble the object code it outputs?

"simply"? Without symbol tables it is quite a bit of work to find the
code of interest, especially when it looks nothing like what you would
have written yourself.

I have a query into Jet about how to get the undocumented assembler
listing working again.

If that fails, my curiosity may press hard enough to solve this
mystery the hard way.
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Twisted schreef:
Are you out of your cotton-picking MIND?!
No.

I don't want to have to
declare every method as "throws RuntimeException" just because just
about everything might throw NPE and any of several other assorted
bounds, arithmetic, etc. exceptions. And if you want Error declared
too, just forgeddaboudit.

Well, once all exceptions are checked, the throws X statement would be
superfluous anyway, so no argument.
You'd have to massively redesign the language to make this have any
beneficial effect,

Indeed, that’s why it is never going to happen. But I cannot follow
your argument which I snipped away, to be honest. I do not think it is
valid.
Once again: if you want to see how it can be done, have a look at Eiffel
error handling. It looks a bit minimalistic at first, but it is as
simple as it can get.
(http://docs.eiffel.com/eiffelstudio/general/guided_tour/language/tutorial-09.html)

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGi6Rme+7xMGD3itQRAqJuAJ9ffoUtfOx+FWHPju0OJTdzHcwLFACfXVRB
N3OSMFTpw2xLKeZ+e1gMnf4=
=TjT1
-----END PGP SIGNATURE-----
 
S

Stefan Ram

Roedy Green said:
I am wondering if parallel logic in the chip is the secret of the
speed of the nested if. Perhaps it can do several lookaheads.

I have found a bug in my benchmark. The random numbers
generated were often negative and thus prefered one branch.

Now, I have changed

final int random =( randomizer / 65536 )% 10;

to

final int random =(( randomizer / 65536 )& 0x7fffffff )% 10;

everywhere.

After this, the if-sequence is not faster then the switch
anymore, but both take the same time. This confirmes the text
quoted before, which claims that the switch was implemented by
if-sequences.

For the special case of a dense array of values to be
converted into other values, one might also use a look-up
table. I have tried this, and it is indeed much faster than
the switch.
 
R

Roedy Green

The -genasm+ switch in Jet seems to be discontinued so I can't easily
figure out what sort of code it is generating for both.

A talked with the Jet people about this anomaly. They said the
Pentiums have such damaged lookahead logic they do very badly on jump
tables. However, that does not explain why AMD was slow too.

Unfortunately GenAsm in Jet, an undocumented feature to view generated
asm code, has been discontinued. To solve this I will have to find a
cheap decent disassembler. In the old 16-bit days I used one I liked
a lot called Sourcer, but his is no longer. I have compiled a list of
candidates at
http://mindprod.com/jgloss/disassembler.html
 
J

Joshua Cranmer

Operator overloading is complex in C++ becasue you can overload =, +=,
-=, etc. and not make them equivalent.

You can also overload the ',' operator, as well as the '||' operator,
etc. (every operator, in fact, except the '.','::', and the '?:'
operators).
In Java, operator overloading should only be used for: +, -, * and /,
and their meaning should therefore let programmers write a += b and
automatically replace that by a = a + b (which would get then translated
to a = a.operator_plus( b );) No harm done.

What if I have a Matrix class that overloads the '*' operator and I want
to do the simplest scalar multiplication: 5 * m? (This is where C++
operator overloading gets really complicated.)
 
B

Bjorn Borud

[Joshua Cranmer <[email protected]>]
|
| What if I have a Matrix class that overloads the '*' operator and I want
| to do the simplest scalar multiplication: 5 * m? (This is where C++
| operator overloading gets really complicated.)

indeed, which is why "don't do that then" is the right answer :).

-Bjørn
 
S

Stefan Ram

Bjorn Borud said:
| What if I have a Matrix class that overloads the '*' operator and I want
| to do the simplest scalar multiplication: 5 * m? (This is where C++
| operator overloading gets really complicated.)
indeed, which is why "don't do that then" is the right answer (...)

That is one advantage of associating operators with pairs and
not single operands.

If "*" is associated with the left operand of type »int«,
you can not overload it in C++ IIRC.

In a fictional language, however, classes might also have pairs
as their designation. In this language, the operator »*« would
be associated with the class »( int, Matrix )«. This class is
not inbuilt and, therefore, an overload is possible.
 
R

Roedy Green

final int random =(( randomizer / 65536 )& 0x7fffffff )% 10;

I look more carefully at the code, I see another problem.

Your code to calculate randoms overwhelms the cost of the code to do
the swtich.

I rewrote the code. Here is my new result with Jet.

[E:\com\mindprod\example]TestSwitch
Calculate time for IF/time for SWITCH. >1 means IF is slower
Trial | ratio | average
0 1.00 1.00
1 1.01 1.00
2 0.97 0.99
3 0.99 0.99
4 1.01 1.00
5 1.00 1.00
6 1.04 1.00
7 1.01 1.00
8 1.00 1.00
9 0.99 1.00
10 0.99 1.00

In other words IF is just as fast as switch WHY??

package com.mindprod.example;

import static java.lang.System.nanoTime;
import static java.lang.System.out;
import java.util.Random;

/**
* Compares relative speed of nested if vs switch
*
* @author Roedy Green, Canadian Mind Products, based on a program by
Stefan
* Ram.
* @version 1.0, 2007-07-04 Created with IntelliJ IDEA.
*/
public class TestSwitch {

// ------------------------------ FIELDS
------------------------------
// one million iterations per trial
final static long ITERATIONS_PER_TRIAL = 1000000L;

// --------------------------- main() method
---------------------------

public static void main( final java.lang.String[] args ) throws
java.lang.Throwable
{

out.println(
"Calculate time for IF/time for SWITCH. >1 means IF
is slower" );
out.println( " Trial | ratio | average" );
final Random wheel = new Random();

// accumulate total machine cycles for switch
long accumSwitchTotal = 0;

// accumulate total machine cycles for if
long accumIfTotal = 0;

// force code to do something rather than be optimised out of
existence
long forcer = 0;

// do forever
for ( long trial = 0; ; trial++ )
{
// accumulate machine cycles for switch for this trial
long accumSwitchTrial = 0;

// accumulate machine cycles for if for this trial
long accumIfTrial = 0;

for ( long i = 0; i < ITERATIONS_PER_TRIAL; ++i )
{
final int random = wheel.nextInt( 10 );
long start = nanoTime();
final int rif;
{
if ( random == 0 )
{
rif = 20418437;
}
else if ( random == 1 )
{
rif = 94704581;
}
else if ( random == 2 )
{
rif = 45898144;
}
else if ( random == 3 )
{
rif = 49094059;
}
else if ( random == 4 )
{
rif = 77416885;
}
else if ( random == 5 )
{
rif = 91322469;
}
else if ( random == 6 )
{
rif = 40218964;
}
else if ( random == 7 )
{
rif = 93641667;
}
else if ( random == 8 )
{
rif = 29822916;
}
else
{
rif = 625909;
}
}
accumSwitchTrial += nanoTime() - start;
forcer += rif;
start = nanoTime();
final int rswitch;
switch ( random )
{
case 0:
rswitch = 16336774;
break;
case 1:
rswitch = 62881795;
break;
case 2:
rswitch = 27998504;
break;
case 3:
rswitch = 9612956;
break;
case 4:
rswitch = 25592297;
break;
case 5:
rswitch = 77114095;
break;
case 6:
rswitch = 23554325;
break;
case 7:
rswitch = 55380051;
break;
case 8:
rswitch = 47971513;
break;
default:
rswitch = 41100793;
}
accumIfTrial += nanoTime() - start;
forcer += rswitch;
}// end for iterations
double ratio = (double) accumIfTrial / (double)
accumSwitchTrial;
accumIfTotal += accumIfTrial;
accumSwitchTotal += accumSwitchTrial;
double averageRatio =
(double) accumIfTotal / (double) accumSwitchTotal;

out.printf( "%6d %6.02f %6.02f\n", trial, ratio,
averageRatio );
}
}
}
 
O

Oliver Wong

Roedy Green said:
[E:\com\mindprod\example]TestSwitch
Calculate time for IF/time for SWITCH. >1 means IF is slower
Trial | ratio | average
0 1.00 1.00
1 1.01 1.00
2 0.97 0.99
3 0.99 0.99
4 1.01 1.00
5 1.00 1.00
6 1.04 1.00
7 1.01 1.00
8 1.00 1.00
9 0.99 1.00
10 0.99 1.00

In other words IF is just as fast as switch WHY??

To clarify, when I said that switch-statements behave like a bunch of
if-statements, I meant at the semantic/behaviour level, not at the
performance level.

However, these experiments just seem to reinforce the dogma: "Don't
optimize without profiling; your intuitions about performance are probably
wrong."

- Oliver
 
O

Oliver Wong

Stefan Ram said:
That is one advantage of associating operators with pairs and
not single operands.

If "*" is associated with the left operand of type »int«,
you can not overload it in C++ IIRC.

In a fictional language, however, classes might also have pairs
as their designation. In this language, the operator »*« would
be associated with the class »( int, Matrix )«. This class is
not inbuilt and, therefore, an overload is possible.

I definitely see the appeal of specifying the behaviour of binary
operators within class-pairs, rather than within a specific (but perhaps
arbitrary?) class. Maybe operators should not simply be thought of as
syntactic sugar for a method invocation on an object, but rather as first
class citizens of a language in their own right?

- Oliver
 
S

Stefan Ram

Oliver Wong said:
I definitely see the appeal of specifying the behaviour of binary
operators within class-pairs, rather than within a specific (but perhaps
arbitrary?) class. Maybe operators should not simply be thought of as
syntactic sugar for a method invocation on an object, but rather as first
class citizens of a language in their own right?

In my fictional language, they can still be method
invocations, namely, on objects of the type »( int, Matrix )«,
similar to:

new IntMatrixPair( 5, m ).product()

»Java was actually designed to have tuples from the start,
but they never quite got in.«

http://gbracha.blogspot.com/2007/02/tuples.html
 
R

Roedy Green

To clarify, when I said that switch-statements behave like a bunch of
if-statements, I meant at the semantic/behaviour level, not at the
performance level.

You said " Yes, I think that's an accurate mental model of how the
switch statement works"

That sounded to me a description of how they behave under the hood. I
was puzzled when I read that which you meant.

We need a pair of adjectives:

1. one for a model describes the end result but is not necessarily
anything like how it is implemented.

2. one for a model that roughly describes what goes on at the machine
code level.
 
C

Chris Smith

Here's my (very conservative) view:

Joshua Cranmer said:
Recently, I was looking around online and came across this (partial) list
of new Java 7 features. What I want to know is what support/disapproval
people have of these options:

@ Closures

I have no opinion, because I haven't actually read through Neil's
proposal (I'm assuming Neil's proposal is what would happen here). I'm
skeptical, and there is a certain bar of "does it add anything?" that
would need to be cleared here.
@ Strings in switch statements
@ Operator overloading for BigDecimal

Of course, on both counts.

If operator overloading were being considered in a more general way,
there might be dispute between the two options. In the absence of
something more general, the only way to oppose it for BigDecimal is to
have never tried any non-trivial use of BigDecimal as it stands. This
is no different from operator overloading for String.
@ Language-level XML support

Bleh. I'd like to see this idea hidden under mounds and mounds of dirt,
and the ground poisoned so that no one will go near it again. I'm
wondering when the proposal will come to add JSON syntax to the
language, and then YML, and then INI file format, and then...

Addiction to XML signifies the worst possible side of Java, and brings
out the ugliest in its developers. It's quite the tricky little devil,
too, as it has ensnared any number of people who otherwise think clearer
than that.
@ Reified generics

YES!!!!!!!
YES!!!!
Oh, and YES!!!!!

(In other words, this feature means "fix the broken generics we wrote
the first time around.")
@ Superpackages

Not sure what they are.
@ Removing checked exceptions

This would be a serious, serious mistake. Improving checked exceptions
to fix their limitations is one thing. Removing them is the wrong
direction.
 
T

Twisted

Indeed, that's why it is never going to happen. But I cannot follow
your argument which I snipped away, to be honest. I do not think it is
valid.

You can't snip the whole argument and handwave "I do not think it is
valid" and expect to be believed. Either respond in detail and marshal
some evidence to support your POV, or forget about it. If you have a
detailed proposal for how to make all the RuntimeExceptions checked
without driving Java programmers mad (or everyone just spalling
"throws RuntimeException" on every method), then by all means spell it
out. But pointing us to some Web site regarding some other programming
language entirely is a cop-out. We want to discuss these ideas here in
the newsgroup, not go off someplace else and read a monologue on the
subject where we can't reply with our own thoughts, and which isn't
even based on Java.

P.S. whether it is doable with RuntimeException or not, I think it's
frankly impossible with Error. Those can literally pop up anywhere.
Any "new" can throw OOME, for instance, and therefore any method call
might, since it might have a "new" in it directly or by way of further
calls. Making those checked really would just force everyone to put an
explicit "throws Error" on every method. Right now, basically, a
"throws RuntimeException, Error" is implied on every method
declaration, and I think that's just fine...
 
O

Oliver Wong

Hendrik Maryns said:
[...]

Well, once all exceptions are checked, the throws X statement would be
superfluous anyway, so no argument.

To me, a checked exception is one you have to either handle or
explicitly throw, and an unchecked exception is one which you do not need
to handle nor explicitly throw. The terms are only meaningful in contrast
to each other. I can't see a difference between a language which has only
"unchecked exceptions" (and thus you never need to declare a throw), and a
language which has only "checked exceptions" (and thus you never need to
declare a throw).

It may be more productive to focus the debate on:
1) Should there be a duality of checked vs unchecked exceptions, or
should there only be one type of exception?
and 2) If the latter, should this "only one type" of exception have
enforced throw declaration, or forbid any type of throw declaration
whatsoever, (or perhaps allow the throw declarations, but make them
optional, as a form of documentation, and have no effect on behaviour of
the program)?

FWIW, I think Sun got this part of the language design right and that
there is value in having two different types of exceptions.

- Oliver
 
W

Wojtek

Oliver Wong wrote :
FWIW, I think Sun got this part of the language design right and that
there is value in having two different types of exceptions.

Indeed there is.

If I have the following:

public class Foo
{
public static final int BAR = (new FooBar("foobar")).getIndex();
public static final int BAR_2 = (new FooBar("foobar2").getIndex();
}

If the constructor for FooBar("") is defined as throwing a checked
exception, how do you handle it?

OTOH, if it throws an unchecked exception, then this is valid code, and
some other part of the JVM will catch it.


Note: This type of construct should ONLY ever fail during the coding
process, where the developer can fix it. I use it to to make sure that
the passed parameter is uniquely named.

Note2: There are other constructs to attach the new FooBar to the class
Foo, but they are not relevant to this discussion...
 

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,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top