Optimise my ray tracer

H

HomerCritic

There are articles both from Sun and IBM, stating that is NOT favorable
to pool or cache objects. The newer garbage collectors have a
generational mechanism that causes new objects to get reclaimed
quicker.

I've had a fairly complex heavy image processor with many cached image
blocks. Processing would take around 30 minutes and had a lot of
pooling, where I check out buffered images and return them to the pool.
When I took out the pooling and created new ones, the performance
didn't get reduced one bit.

On a side note, the "language shootout" web page measures Java WRONG.
They don't do their tests properly.
Often Java runs actually faster than C, especially for number
crunching.

I've gotten in many arguments in the past where people were not
believing me, but I won on every occasion.
 
L

Lee Fesperman

HomerCritic said:
There are articles both from Sun and IBM, stating that is NOT favorable
to pool or cache objects. The newer garbage collectors have a
generational mechanism that causes new objects to get reclaimed
quicker.

That's not universally true. For instance, if object creation/destruction is expensive.
Database connections are an example.
 
C

Chris Smith

Lee Fesperman said:
That's not universally true. For instance, if object creation
/destruction is expensive. Database connections are an example.

Right. Specifically, it's most true under the following conditions:

1. Memory management effort dominates the object's lifecycle management.
2. The object is small enough to be allocated in the nursery.
3. The object is short-lived enough not to be promoted from the nursery.

So, for example, keeping one 128K buffer may also improve performance
over re-allocating it every time you need it. The real point Sun ought
to be making is not that pooling is bad, but that software developers
are, in general, not very good at predicting what is good or bad for
performance. Because of that, writing an object pool without having
some clear and objective profiling cases in place to measure the
resulting change in performance is not a good idea.

Basically, keep code simple, then optimize with liberal use of objective
data and not intuitive ideas about performance.

(That said, I don't think most people would include database connections
in their general idea of instance pooling. Connection pooling is a
different matter altogether, and in that case it probably is worth
designing for pre-emptively just on the basis that it's widely
recognized as good practice and provided for in the JDBC API.)

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Jon Harrop

HomerCritic said:
On a side note, the "language shootout" web page measures Java WRONG.
They don't do their tests properly.
Often Java runs actually faster than C, especially for number
crunching.

Can you elaborate on this? All of my tests indicate that Java is many times
slower than most other modern languages, even stereotypically slow
languages like SML and OCaml.
 
C

Chris Smith

Jon Harrop said:
Can you elaborate on this? All of my tests indicate that Java is many times
slower than most other modern languages, even stereotypically slow
languages like SML and OCaml.

You're making statements that are far too broad to be useful. Java is
far slower doing what? If you're measuring only startup time (before
'main' even starts) then you'll find Java is literally tens of thousands
of times slower than many other languages. That's why Java is rarely or
never used for interactive applications that run for extremely short
periods of time, such as typical command line utilities.

Most computational tasks tend to run within about 10% to 20% of optimal
time for the hardware platform, and compare about evenly with modern
compiled languages. There are specific tasks for which significant
general performance differences may be measured (floating point
calculations being one, but I can't recall whether Java is typically
faster or slower here, and it may depend on the platform), but this
wouldn't be described as "many times slower".

I strongly suspect that the issue is startup time. If you're measuring
it with your ray tracer, are you measuring externally so as to include
the startup time, or internally once the VM has started? There's no
"right" way to do this; it depends on whether your target audience will
care about startup time, or only how the appo performs once it's
running. However, if you're including startup time, you ought to at
least add a note that this is the reason for the results. The great
majority of applications run for orders of magnitude longer than the
average benchmark, and just saying that Java is slower is very
misleading.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Jon Harrop

Chris said:
You're making statements that are far too broad to be useful. Java is
far slower doing what?

Running my ray tracer.
Most computational tasks tend to run within about 10% to 20% of optimal
time for the hardware platform, and compare about evenly with modern
compiled languages.

If you're trying to say that equivalent programs written in different
languages like C, C++, Java, SML, OCaml and Fortran will be within 20% of
each other's performance then that definitely isn't true. Any programs
which stress allocation/deallocation (e.g. balanced binary trees) are
likely to do significantly worse in garbage collected languages. Any
programs which stress indirected data structures will do significantly
worse in OCaml, particularly when pointers cost 64 bits.
There are specific tasks for which significant
general performance differences may be measured (floating point
calculations being one, but I can't recall whether Java is typically
faster or slower here, and it may depend on the platform), but this
wouldn't be described as "many times slower".

Here are the times for running my ray tracer on x86 (1.2GHz Athlon T-bird)
with n=128, level=6 and ss=4:

Mlton 1.250s mlton ray.sml
IFC 1.361s ifort -O3 -u -static-libcxa -o raytracer raytracer.f90
C++ 1.555s g++-3.4 -O3 -march=athlon-tbird -ffast-math ray.cpp -o ray
ocamlopt 1.932s ocamlopt -inline 100 ray.ml -o ray
SML-NJ 2.085s sml ray.sml
G95 3.351s g95 -O3 -ffast-math ray.f90 -o ray
C 4.125s gcc-3.4 -lm -std=c99 -O3 -march=athlon-tbird
-funroll-all-loops -ffast-math ray.c -o ray
Java 6.492s javac ray.java
GCJ 20.316s gcj-3.4 --main=ray -Wall -O3 -march=athlon-tbird
-funroll-all-loops -ffast-math ray.java -o ray
ocamlc 41.047s ocamlc ray.ml -o ray

as you can see, Java run under Sun's J2SE is over 5x slower than the fastest
implementation (Mlton-compiled SML).
I strongly suspect that the issue is startup time.

I have taken many measurements for different running times (<2s to >20s)
and, assuming Java's startup time to be constant, the startup time is
insignificant.
If you're measuring
it with your ray tracer, are you measuring externally so as to include
the startup time, or internally once the VM has started? There's no
"right" way to do this; it depends on whether your target audience will
care about startup time, or only how the appo performs once it's
running. However, if you're including startup time, you ought to at
least add a note that this is the reason for the results. The great
majority of applications run for orders of magnitude longer than the
average benchmark, and just saying that Java is slower is very
misleading.

Right, well I've accounted for that and I can still only conclude that Java
is very slow.

I've also run the ray tracer on AMD64 with JDK 1.5 and Java is still
significantly slower than other languages, albeit "only" 2.4 times slower.
 
T

Tor Iver Wilhelmsen

Jon Harrop said:
Can you elaborate on this? All of my tests indicate that Java is many times
slower than most other modern languages, even stereotypically slow
languages like SML and OCaml.

Since Java code (unless forced to run interpreted) runs 98% of its
time as run-time optimized native code, how can it be slower than
compile-time optimized C code? Are you perchance taking startup time
into consideration?
 
J

Jon Harrop

Tor said:
Since Java code (unless forced to run interpreted) runs 98% of its
time as run-time optimized native code, how can it be slower than
compile-time optimized C code?

Many possible reasons:

1. Java's optimiser isn't as good.
2. The time spent optimising is longer than the time saved executing.
3. Deficiencies in the language (of which there are many in Java, e.g.
run-time checks due to OO, boxing).
4. Poor implementations of performance critical constructs by the compiler,
e.g. recursion.
Are you perchance taking startup time into consideration?

I have taken startup time into consideration. Java is still consistently
many times slower than most other languages.
 
L

Lasse Reichstein Nielsen

Jon Harrop said:
I have taken startup time into consideration. Java is still consistently
many times slower than most other languages.

Is this using the original code that was posted here? Because it can
be written significantly better.

Just making the Vector class static will reduce its number of fields
by 25%, which should make a significant cut in the initialization time
for each Vector.

/L
 
J

Jon Harrop

Lasse said:
Is this using the original code that was posted here? Because it can
be written significantly better.

Great, tell me how (provided it doesn't get too much longer).
Just making the Vector class static will reduce its number of fields
by 25%, which should make a significant cut in the initialization time
for each Vector.

One my machine, the original took 31s for:

$ javac ray.java
$ java ray 256>image.pgm

With the vector class declared static (what exactly does this do?) it takes
29s, which is not significantly faster.

In contrast, Mlton-compiled SML is much shorter (79 vs 110 LOC) and runs
about 5x as fast, taking only 6s to ray trace exactly the same image.

So we really need much better optimisations if Java is going to perform
anything like as well as the other languages. Am I missing something
simple, like JIT or optimisation flags?
 
T

Tor Iver Wilhelmsen

Jon Harrop said:
With the vector class declared static (what exactly does this do?)

This alone tells us you really do not know Java.

The point is that you really should not take startup time into
consideration when considering how "fast" a language is. It would be
akin to testing whether the Windows "calc" program is faster than
using pencil + paper to add two numbers, and then take Windows startup
time into account. Java is designed to run apps over a period of time,
you don't and draw the wrong conclusion.
 
J

Jon Harrop

Tor said:
This alone tells us you really do not know Java.

Yes, I do not know Java, as I stated in my original post. That's why I'm
here, asking for advice.

I'm not actually getting any useful advice though. So far, lots of people
have said that Java has a startup time, suggested minor performance tweaks
which fail to make the program 5x faster and told me that I don't know
Java.
The point is that you really should not take startup time into
consideration when considering how "fast" a language is.

For the umpteenth time, I have taken startup time into account. I am doing
measurements over an order of magnitude variation in total running time and
startup appears to be insignificant (~0.2s out of 30s total running time).
Java is still vastly slower than everything else. Is this representative of
Java or am I doing something daft?
It would be
akin to testing whether the Windows "calc" program is faster than
using pencil + paper to add two numbers, and then take Windows startup
time into account. Java is designed to run apps over a period of time,
you don't and draw the wrong conclusion.

Yes, I am trying very hard to draw the appropriate conclusion. Currently,
the conclusion is that Java is the second most verbose, slowest to compile
and the slowest to run out of the languages that I have tested (C, C++,
OCaml, SML, Fortran).
 
L

Lasse Reichstein Nielsen

Jon Harrop said:
Great, tell me how (provided it doesn't get too much longer).

I posted a link to a slightly optimized version. I don't know if
I am changing the algorithm too much for comparison (e.g., moving
loop invariant code out of the loop) and doing all the I/O at the
end instead of during the computation.

<URL: http://www.infimum.dk/privat/RayTracing.java >
(I changed the class name too, to a more traditional Java format).

I admit to having performed "optimizations" without profiling first,
so there is no telling which change does what, but it does give
me an ~30% increase in speed for size=100.
With the vector class declared static (what exactly does this do?)

It makes the class more independent of the surrounding class, so each
Vector doesn't have to carry around a reference to a "ray" object that
it never uses.

In a real program, I would put all the nested classes into their own
files.
it takes 29s, which is not significantly faster.

My guess is that a lot of the time comes from I/O (ok, just O, it only
does output :).
In contrast, Mlton-compiled SML is much shorter (79 vs 110 LOC) and runs
about 5x as fast, taking only 6s to ray trace exactly the same image.

Brevity of code is not in itself a quality. Java is often more verbose
than other languages, but I also often find it more readable, because
differet programmers can't invent their own dialect.
So we really need much better optimisations if Java is going to perform
anything like as well as the other languages. Am I missing something
simple, like JIT or optimisation flags?

Can't help you there. I rarely fiddle with flags :)


Btw, is the generated image correct? It looks odd.
/L
 
D

Dale King

Tor said:
Since Java code (unless forced to run interpreted) runs 98% of its
time as run-time optimized native code, how can it be slower than
compile-time optimized C code? Are you perchance taking startup time
into consideration?

You know I've been indoctrinated in the Java is as fast as C as well,
but someone was pointing out benchmarks that show it is twice as slow as
compiling the code with gcj. I've not had time to look into the actual
results (and I haven't found any comparing to 1.5), but it makes me
wonder if maybe we've believed something that isn't true.
 
C

Chris Uppal

Dale said:
You know I've been indoctrinated in the Java is as fast as C as well,
but someone was pointing out benchmarks that show it is twice as slow as
compiling the code with gcj. I've not had time to look into the actual
results (and I haven't found any comparing to 1.5), but it makes me
wonder if maybe we've believed something that isn't true.

Depends on what you're doing -- obviously. There have been various reports of
differences in performance with various JVMs vs. various "other" languages.
The results are varied as well.

I do suspect, though, that applications that show Java to be in the 50%-80% as
fast as C/C++/Fortran are probably under-reported. Java turning out to be as
fast or faster than the old-school languages is news; Java turning out to be
significantly slower is also news; but Java turning out to be slower by an
unimportant margin... <yawn/>

In this particular case, though, I suspect that the results are not
representative -- I did measure the OP's earlier version of the Java code vs.
the C++ code he had on his web page (I had to fix some minor differences), and
found that on my machine the 1.5 server JVM from Sun was getting on for twice
as fast as the C++ code compiled with MS VC6 or VS2003 [*]. He's since offered
modified C++ code, but I haven't attempted to see what the differences are, nor
whether the Java code could still be considered to be a fair equivalent.

-- chris

([*] to be honest, that surprised me -- I'd have expected the overhead of
heap-allocating hundreds of millions of objects to have more impact than that)
 
V

Vit

To the issues of JAVA performance:
I have compiled both original version (Ray) and this optimized version
(RayTracing):

with the JET compiler (http://www.excelsior-usa.com/jet.html)
and got the following results (in CPU secs):

RAY: JVM EXE
input = 100 12,4 5,2 =39%
200 39,7 19,0 =48%
300 84,3 42,8 =51%

RAYTRACING: JVM EXE
input = 100 7,6 4,0 =52%
200 28,2 13,8 =49%
300 64,9 30,4 =46%

Percentage shows the ratio of compiled and optimized native code speed
vs. JVM speed. What is interesting: a better written source code is
better optimized by a compiler -- see that increasing the job size
takes less and less time in the optimized program...

Ah, yep, this was about another way to accelerate your program ;)

Vit
 
R

Remon van Vliet

Dale King said:
You know I've been indoctrinated in the Java is as fast as C as well,
but someone was pointing out benchmarks that show it is twice as slow as
compiling the code with gcj. I've not had time to look into the actual
results (and I haven't found any comparing to 1.5), but it makes me
wonder if maybe we've believed something that isn't true.

Claiming java code runs as fast as native C code is naive at best, it simply
isnt. There are numerous sites with benchmarks on the net that prove my
point. There are certain scenarios where Java will be as fast (or faster)
than native C code, but such scenarios are fairly rare in applications such
as raytracers. I have personally written a real-time raytracer in Java, and
have found performance to be dramatically lower than it's C counterpart,
while the code was almost the same.

Note that you can improve performance by using the server VM (-server),
which almost doubled the performance of my raytracer. The server VM does
it's best to get peak-performance (most likely by aggressively
JIT-ing/inlining a lot of code), the client VM is more concerned with fast
start-up and reducing memory footprints.

Remon
 
R

Remon van Vliet

Did you run the JVM code with the -server option on? If not, try that and
see if it makes a difference, it should.

Remon van Vliet
 
J

Jon Harrop

Remon said:
Did you run the JVM code with the -server option on? If not, try that and
see if it makes a difference, it should.

I did and it makes no difference because it is the default. However, running
with -client actually appears to be slightly faster (17.8s vs 18.3s). That
might not be a significant difference though.
 
K

Kenneth P. Turvey

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

Dale said:
Tor Iver Wilhelmsen wrote:
You know I've been indoctrinated in the Java is as fast as C as well,
but someone was pointing out benchmarks that show it is twice as slow as
compiling the code with gcj. I've not had time to look into the actual
results (and I haven't found any comparing to 1.5), but it makes me
wonder if maybe we've believed something that isn't true.

In my experience Java is slower than C. Java has many qualities that make
it nicer to program in than C, but raw speed isn't one of them.

- --
Kenneth P. Turvey <[email protected]>


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFCr3YK1KarboZXuegRAiVzAJwKPO6H33B5/wduNZG1TxiDn4RynwCcDmaX
XA0NKfgsor2T9izMOzn57q0=
=kZND
-----END PGP SIGNATURE-----
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,140
Latest member
SweetcalmCBDreview
Top