Jump to page: 1 27  
Page
Thread overview
Java vs C Benchmarks
Jun 17, 2003
Mark Evans
Jun 17, 2003
Walter
Jun 22, 2003
Mark Evans
Jun 22, 2003
Jeff Peil
Jun 22, 2003
Mark Evans
Jun 21, 2003
Mark T
Jun 22, 2003
Alisdair Meredith
Jun 22, 2003
Fabian Giesen
Jun 23, 2003
Helmut Leitner
Jun 23, 2003
Georg Wrede
Jun 23, 2003
Alisdair Meredith
Jun 23, 2003
Fabian Giesen
Jun 24, 2003
Georg Wrede
Jun 23, 2003
anonymous
Jun 24, 2003
Helmut Leitner
Jun 23, 2003
Alisdair Meredith
Jun 23, 2003
Ilya Minkov
Jun 23, 2003
Alisdair Meredith
Jun 23, 2003
Ilya Minkov
Jun 23, 2003
Alisdair Meredith
Jun 23, 2003
Fabian Giesen
Jun 24, 2003
Farmer
Jun 24, 2003
Walter
Jun 23, 2003
Fabian Giesen
Jun 23, 2003
Walter
Jun 24, 2003
Helmut Leitner
Jun 24, 2003
Alisdair Meredith
Jun 24, 2003
Fabian Giesen
Jun 24, 2003
Walter
Jun 24, 2003
Helmut Leitner
Jun 24, 2003
Walter
GC workgroup invitation
Jun 25, 2003
Helmut Leitner
Jun 25, 2003
Georg Wrede
Jun 25, 2003
Helmut Leitner
Jun 26, 2003
Walter
Jun 26, 2003
Helmut Leitner
Jun 26, 2003
Helmut Leitner
Jun 26, 2003
Walter
Jun 26, 2003
Patrick Down
Jun 26, 2003
Fabian Giesen
Jun 26, 2003
Juarez Rudsatz
Jun 27, 2003
Helmut Leitner
Jun 27, 2003
Sean L. Palmer
Jun 27, 2003
Fabian Giesen
Jun 26, 2003
Walter
Jun 27, 2003
Russ Lewis
Jun 28, 2003
Fabian Giesen
Jun 28, 2003
Helmut Leitner
Jun 28, 2003
Fabian Giesen
Jun 28, 2003
Helmut Leitner
Jun 28, 2003
Fabian Giesen
Jun 28, 2003
Helmut Leitner
Jun 28, 2003
Fabian Giesen
Jun 30, 2003
Helmut Leitner
Jun 30, 2003
Fabian Giesen
Jun 30, 2003
Russ Lewis
Jul 02, 2003
Mark Evans
Jun 24, 2003
Fabian Giesen
Jun 24, 2003
Walter
Jun 24, 2003
Fabian Giesen
Jun 25, 2003
Walter
Jun 25, 2003
Fabian Giesen
June 17, 2003
From a guy who does lots of number crunching; interesting results.

http://www.idiom.com/~zilla/Computer/javaCbenchmark.html



June 17, 2003
"Mark Evans" <Mark_member@pathlink.com> wrote in message news:bcnoeo$1npv$1@digitaldaemon.com...
>
> From a guy who does lots of number crunching; interesting results.
>
> http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

It's an interesting article. The author is right that there is no reason that Java numerics code should be slower than in C, except when the Java vm is forced to use suboptimal floating point to conform to the Java way of doing floating point that diverges from FPU hardware.

Here are the cases where Java is slower than C:

1) Java doesn't support lightweight objects, or lightweight arrays. This means that Java allocates and deallocates an excessive number of objects compared to C code.

2) The Java startup time can be very slow, due to loading the huge VM and the necessity of compiling it before use.

3) Anytime you need to access some feature not found in the Java library, you need to go through the JNI translation layer.

4) Doing much of anything with arrays in Java requires lots of allocation/deallocation cycles.

5) Java chars are 16 bits, and dealing with a lot of them winds up being slow compared with C dealing with byte sized chars.

6) Java has no out parameters, sometimes necessitating creating lots of dummy classes for returning multiple values. Again, this adds to the allocation/deallocation pressure.

7) The string functions are all synchronized, costing speed. Strings are copy-on-write, which gets expensive.

8) Some of the library functions are inefficiently designed, such as file I/O.

9) There are inefficiencies in the library caused by it trying to present a common interface across diverse platforms.

Note that only (2) is related to Java being byte code. None of these are related much to integer manipulation and numerics code, which is why Java can do well with them. These difficulties are pretty hard to overcome.

Java does have one important advantage over C. Being compiled at runtime, the generated code can be customized to the idiosyncracies of the particular processor it happens to be running on. C, on the other hand, tends to be compiled to the lowest-common-denominator chip. A lot of the difference between CPUs of the same family is how they schedule instructions, extra instructions for floating point, etc. Optimal code generation for one CPU may be very different from that of another CPU in the same family (Intel is famous for doing that).


June 21, 2003
"Mark Evans" <Mark_member@pathlink.com> wrote in message news:bcnoeo$1npv$1@digitaldaemon.com...
>
> From a guy who does lots of number crunching; interesting results.
>
> http://www.idiom.com/~zilla/Computer/javaCbenchmark.html
>
>
>

More Java hype. Please read the following piece taken from the site:

"In cases where the compiler cannot determine the necessary information at compile time, the C pointer problem may actually be the bigger performance hit. In the java case, the loop bound(s) can be kept in registers, and the index is certainly in a register, so a register-register test is needed. In the C/C++ case a load from cache is needed"

There are major errors with this statement:

1) C/C++ does not do bounds checking on simple arrays. Buffer overrun anyone ?

2) The actual address of the pointer is kept in a register, too. Basically, the guy says that since Java does not have pointer arithmetic and uses indices to process arrays, it is faster, because the pointer arithmetic in C must access the memory for the pointer. That's plain wrong. Consider the following:

//index-based processing
for (int i = 0; i < max; i++) {
    a[i] = ...;
}

and then consider this:

//pointer-based processing
for(int *i = a; i < pmax; i++) {
    *i = ...;
}

The article says that the index-based one is faster, because it is pure register-based (except from the final assignment, of course), because the pointer-based processing requires pointer access.

That's stupid. *i may be a pointer, but the value of the pointer is kept in a a register. By pointer arithmetic, the array address calculation before the final assignment is eliminated. There is no cache access involved.

In reality, Java is much slower than C/C++.

Another foul part:

"Most everyone says GC is or should be slower, with no given reason- it's
assumed but never discussed. Some computer language researchers say
otherwise.
Consider what happens when you do a new/malloc: a) the allocator wanders
through some lists looking for a slot of the right size, then returns you a
pointer. b) This pointer is pointing to some pretty random place.

With GC, a) the allocator doesn't need to look for memory, it knows where it is, b) the memory it returns is adjacent to the last bit of memory you requested. The wandering around part happens not all the time but only at garbage collection. And then of course (and depending on the GC algorithm) things get moved of course as well"

The guy does not know the basics:

1) a GC does not run all the time, so the next 'new' might happen when the memory is not yet compacted. A GC thread runs periodically and collects resources. In this case, the memory is walked as in C.

2) An implicit thread makes determinism difficult to achieve. You don't know when the GC will kick in and freeze the app. That's a mighty problem when you have timers.

3) In order to make memory compacting possible, Java uses triple indirection, i.e. a pointer to a pointer to the object. The GC knows the 2nd pointer's location, and thus it can freely change memory locations by simply change the 2nd pointer. All pointers to the 2nd pointer will automatically point to the new object's location. Example:

//java code

byte[] myByteArray = new byte[10];

myByteArray[0] = 1;



//the equivalent C++ code:

char *p2 = new char[10];

char **p1 = &p2;

(**p1)[0] = 1;



A GC may move the byte array around, and change the 2nd pointer to point to the new location. You have several costs:

1) data copied around every now and then.

2) triple indirection. Need we say more ?

3) the thread itself.

We can see from the above example that arrays are completely different in Java than in C++. Not only that, but when arrays are passed around in methods, Java passes 2 arguments instead of one. The first argument passed is the array's 'environment', i.e. a struct that describes the array. This makes possible to find the array size. If you don't believe me, look at JNI.

Another error-prone statement:

"The big benefit of GC is memory locality. Because newly allocated memory is adjacent to the memory recently used, it is more likely to already be in the cache".

Memory locality and memory adjacent blocks are two completely unrelated things. Even if two memory blocks are in far away addresses, if they are constantly used, they would be already in cache.  For example:

//array1

int *array1 = new int[200];

...bla bla bla more allocations...

int *array2 = new int [200];

now the two arrays are in wildly different memory locations, but, does it matter ? no!!! Check out the following loop:

for(int i = 0; i < 10000000; i++) {

    for(j = 0; j < 200; j++) {

        array1[j] = rand();

        array2[j] = rand();

    }

}

In the loop above, the first access to the array1 and array2 will bring those arrays to the cache. After that, they would be in the cache for as long as the loop takes place. But they are not adjustent!!!

The big bottleneck of  Java is that everything is allocated on the heap. So, the following type of code is quite often met:

//setting a point by using new Point ? what a waste of resources!!!

widget->setPosition(new Point(10, 10));

And this is because Java can only allocate objects on the heap and not on the stack. This makes the Java memory fragmented much more than in C++.



Another bunch of lies:

"Modern Java virtual machines do some amazing things: they profile the program while it is running, determine which parts to optimize, compile them, then uncompile and recompile them if new classes are loaded that override methods that were inlined!

The people working on hotspot in particular have hinted that Java should sometime be faster than C because of this. Why?

-Because the compiler knows which classes are actually loaded and being called, it can remove the overhead of virtual methods.

- dynamic compiler may also get the branch prediction hints right more often than a static compiler. "

But those two things are also done on the static compilers too!!! the only difference between static and dynamic compiling is that dynamic happens while the program is running. There are no more information available dynamically than statically!!! In detail:

1) a virtual method can be made non-virtual if the parent or ancestor class is never used(i.e, the interface is never virtual). In C++, the programmer uses virtual methods because they are actually gonna be used in some place as virtual methods! that means, that the compiler should not check for a method being called virtually!!! In a few simple words, in C++ we make a method 'virtual' because our design says it's gonna be called virtually, otherwise we would not make it virtual!!!

2) branch prediction is done entirely by the hardware, except on
EPIC(Itanium, Merced etc). C/C++ compilers don't do branch prediction.

Actually, the virtual machine has great overhead. That's why Java compilers exist. If a JVM can do an equal job, then there would be no need for a static compiler.

Conclusion:

"Java is now nearly on parity with C++ in performance. This means we'll see cases where new releases of C++ compilers do better than Java, and vice-versa, just as different C/C++ compilers often have performance differences of up to a factor two or so. On the other hand, performance does depend (a lot) on how the program is written."

I work for a company that makes defense applications for THALES (ex Thomson), in C++, ADA and Java. Java is slow!!! Believe me. Maybe in the future it won't be. Maybe in some extreme cases a Java compiler will do better. But...right now, it is slow as hell. By far the slowest of the 3 languages!!!




June 21, 2003
>
>More Java hype.
This website seems to support your observations: http://www.coyotegulch.com/reviews/almabench.html


June 22, 2003
Walter,

Glad you like the article.  For the record I do not agree with everything that I post, but benchmarks interest me more than flame fests.  The author of this article really just cited other benchmark authors, such as the university study comparing Java/C++/FORTRAN for numerics work.  It has very nice charts and wide coverage, and is of recent vintage. http://www.philippsen.com/JGI2001/finalpapers/18500097.pdf

Personally I think Java is dumbed-down.  Some of the Java variants interest me, like Nice.  I am however open-minded about the future of Java, e.g. http://www.sun.com/microelectronics/picoJava/overview.html

Certainly I would rather see picoJava take off than M$oft imposing an encrypted-instruction-set .NET Windows-only chip on our little planet.

But my real purpose is simply to stir the pot a bit so that the stew cooks evenly.  The computer field moves very rapidly and "what everybody knows" may not be as true now as it once was, or ever was.  I try to keep an open mind and pay attention to real data.

Mark


June 22, 2003
"Mark Evans" <Mark_member@pathlink.com> wrote in message news:bd2vvh$2u7e$1@digitaldaemon.com
> Certainly I would rather see picoJava take off than M$oft imposing an encrypted-instruction-set .NET Windows-only chip on our little planet.

Mark,

Sun and Microsoft are both corporations, I don't see why you'd blindly prefer one over the other.  In this case you are comparing a proprietary system (Java) with one which is largely an open standard (the ECMA CLI covers the instruction set and much of the class library used in the .NET runtime.)  Sun is not some heroic entity that only does good and Microsoft is not some vile entity seeking to do evil.

-- 
Jeff Peil


June 22, 2003
>Mark,
>
>Sun and Microsoft are both corporations, I don't see why you'd blindly prefer one over the other.  In this case you are comparing a proprietary system (Java) with one which is largely an open standard (the ECMA CLI covers the instruction set and much of the class library used in the .NET runtime.)  Sun is not some heroic entity that only does good and Microsoft is not some vile entity seeking to do evil.
>
>-- 
>Jeff Peil
>
>

Jeff, I don't see why anyone would blindly do anything.  I did not compare the two companies.  The point of the remark was "Java may have a future in spite of itself."

As for Sun and M$oft, I do have comments.  Sun has given away millions of lines of source code (OpenOffice) while M$oft is still debating whether to open up MS Word format.  The .NET SDK license explicitly prohibits non-Windows development. And what's worse, M$oft engages in serious stock fraud (see billparish.com).  I won't bore you with the DOJ findings of fact against M$oft, you can do your own research.

Mark


June 22, 2003
Achilleas Margaritis wrote:

You quote the following statement that you go on to disagree with:

> "Most everyone says GC is or should be slower, with no given reason- it's assumed but never discussed. Some computer language researchers say otherwise."

Just an observation from 12 months back:
Bjarne Stroustrup made some references to GC during one of his sessions
at the ACCU conference last year.  In particular, he did buy into the "a
well written GC should be free" theory (apart from obvious degenerate
cases)

However, when he tried to produce such a "free" collection the best he could do was a 70% performance hit compared to his regular non-GC code.

He either had to admit he couldn't write a decent GC, or find some other explaination <g>  Given no-one was going to hit him with (i), his conclusion came back to one of your observations - C++ is a stack base language.  Moving everything onto the heap in order to support garbage collection has a cost, and that covered the majority of his 70% cost.

I have certainly seen the classic 'flawed' benchmarchs where GC blows away explicit memory management (allocate 1,000,000 unused pointers, GC recycles the same pointer) so have no doubt there are memory-use patterns that will be well suited to GC and may well see a benefit from it.  I am yet to see any real demonstration of this effect beyond simple bechmarks as above though.  It would be nice to understand what real-world profiles GC is well suited to, but that is not as sexy as an all-conquering redundant benchmark, so if the work has been done it has not had sufficient press for me to notice :¬ (

-- 
AlisdairM
June 22, 2003
> He either had to admit he couldn't write a decent GC, or find some other explaination <g>  Given no-one was going to hit him with (i), his conclusion came back to one of your observations - C++ is a stack base language.  Moving everything onto the heap in order to support garbage collection has a cost, and that covered the majority of his 70% cost.

GC is bound to lose against stack allocation - everything that can be properly allocated on the stack will be up to several orders of magnitude faster than what any more sophisticated allocator can do - because both allocation and deallocation is, for all it's worth, free on current machines, where the part of one clock cycle actively occupied with performing the addition (or subtraction) required will not even notice, especially compared to the cost of e.g. a branch misprediction or a cache miss.

However, that is by no means an interesting measure. Anything that can be allocated on the stack *should* be allocated there - there's no way around that. The interesting question is whether GC is faster than traditional C-style heap allocation. I do believe it atleast won't lose much in most actual applications, which makes it a worthwhile change no matter what, but I don't have actual benchmarks to backup this.

Moreover, I have the feeling that most benchmarks ever done on the issue are actually flawed. According to the paper "Dynamic Storage Allocation: A survey and Critical Review" by Wilson, Johnstone et al, allocator performance has traditionally been evaluated using synthetic traces, rather than using actual allocation traces from actual programs. Similarly, comparision between GC and manual memory management is often done by taking one program employing one of the two mechanisms, preparing a version that uses the other approach, and benchmarking the two.

No matter the result, I don't think that strategy makes sense. No matter how transparent (or non-transparent), memory management IS an issue that affects the design of any large program, so an actually meaningful benchmark would have to state a given program and then compare its implementation for a non- GC environment with a GC version. Care must be taken that the core algorithms and their rough implementation techniques are the same - however, the same cannot be said for data structures; those are heavily influenced by the way memory is managed, no matter what.

I don't know of any such Benchmark, but this is the only kind of empirical study on the issue I could really accept :)

-fg


June 23, 2003

Fabian Giesen wrote:
> ... The interesting question is whether GC is faster than traditional C-style heap allocation. I do believe it atleast won't lose much in most actual applications, which makes it a worthwhile change no matter what, but I don't have actual benchmarks to backup this.

Sorry, I have to comment on this.

Talking about performance or optimization a believe don't count, only what you can measure and prove does count.

GC gives up knowledge about the memory blocks needed or unneeded. To regain this knowledge has a cost. That's my theoretical basis why I think that GC will always (statistically) be slower than good tradition memory management.

But: I would never trust this theory.

--
Helmut Leitner    leitner@hls.via.at Graz, Austria   www.hls-software.com
« First   ‹ Prev
1 2 3 4 5 6 7