I just wrote a small blog post about my experience in working with Java for game programming. It is mostly things I stumbled upon while working on Caromble! for the last few years. Check it out: http://www.goo.gl/GD7nm

Really nice article focusing on the primary pain points without digressing into off-topic ramblings. I also like the concluding message (at least my interpretation of it): the tool does not do the job, you do.

What you wrote about Java and C++ in terms of performance is simply wrong, these are just prejudices. Java has been able to become even in some cases a bit faster than C++ during the last 10 years. Don't blame Java. If you get worse performance, it will be probably mainly your fault. I used a lot C and a bit C++ before switching to Java once for all; if it was really slower, I would still code in C.

Objects pooling is often inefficient since Java 1.4 except in a few very particular cases and I get excellent performances without using Java 1.7 try construct. You advise to call System.gc() between levels which is a really bad idea even in this case, it can cause a lot of troubles in the JVM cache. What you wrote about direct NIO buffers is very incomplete, you must release the native memory they use by yourself if you don't run out of memory on the Java heap, not on the native heap, I already wrote about that in my blog. Moreover, I modified Ardor3D so that you can free the memory allocated by this kind of buffers when used in VBOs in the renderer, you can simply override the method deleteVBOs(final AbstractBufferData<?> buffer) and call it between levels for example.

What you wrote about Java and C++ in terms of performance is simply wrong, these are just prejudices.

I really didn't want to go into discussions about Java vs other programming languages -there's already enough information to find on that elsewhere. I merely wanted to help people that are (planning to) write games in Java with things I learned along the way.

Objects pooling is often inefficient since Java 1.4 except in a few very particular cases

Agreed, you only need to consider pooling objects once you have problems with garbage-collector-stutters in your game. And even then, you probably only need to implement pooling in a hand full of methods to solve these issues.

We use the Java 1.7 try construct purely for convenience, it makes sure that once the temp object goes out of scope its gets returned to the pool (instead of manually calling pool.push()). This is especially useful when you have multiple return statements within the scope of the temp object.

What you wrote about direct NIO buffers is very incomplete, you must release the native memory they use by yourself if you don't run out of memory on the Java heap, not on the native heap, I already wrote about that in my blog. Moreover, I modified Ardor3D so that you can free the memory allocated by this kind of buffers when used in VBOs in the renderer, you can simply override the method deleteVBOs(final AbstractBufferData<?> buffer) and call it between levels for example.

Well that is all a bit out of scope of the article. The only point I was trying to make is that you need to be more careful with Directbuffers in Java than with ordinary objects; garbage collecting them will lead to stutters in your game a whole lot sooner than with normal Java objects (and they are harder to find with the Java Visual VM as well).

In my humble opinion, if you're unable to prove that, don't write than Java is really slower than C/C++/whatever. There is no consensus about that. Doug Lea's (biased?) microbenchmarks and the reactions it caused illustrate what I mean.

Well that is all a bit out of scope of the article. The only point I was trying to make is that you need to be more careful with Directbuffers in Java than with ordinary objects; garbage collecting them will lead to stutters in your game a whole lot sooner than with normal Java objects (and they are harder to find with the Java Visual VM as well).

They will be garbage collected if and if only you run out of memory on the Java heap whereas they allocate memory on the native heap. If you run out of native memory, your game will simply stop working which is worse than some stutters . You say in your article that we need to be more careful with direct NIO buffers but you miss the main point. Reusing direct NIO buffers is a good idea but it is not enough and it is not always possible. Several JMonkeyEngine and Ardor3D users already ran out of native memory. However, I have to admit that explaining how to handle direct NIO buffers is not easy. I would advise to avoid unnecessary duplication of data (not only in this kind of object) including mesh data (you already wrote that), use slicing when it is possible, favor indirect NIO buffers when direct NIO buffers are not absolutely necessary (for example when they are not used for OpenGL) and to free the native memory they use when you're sure of what you're doing. My last suggestion is very important especially if your game doesn't use a lot of memory on the Java heap.

The performance in Java depends greatly on how well the compiler and runtime can optimize your code and application. A recent Minecraft fix greatly improved performance because a certain piece of code that was basically executed for every drawn block was head-butting with the optimizer. If the optimizer can do its job well, you might even see more sparks flying than a similar native application.

The question is: how do you make sure you do not get in the way of the optimizer? That requires intimate knowledge I'm afraid, which hooks back into my favorite saying: programming is and will always be hard. You just don't get it for free.

What you wrote about Java and C++ in terms of performance is simply wrong, these are just prejudices. Java has been able to become even in some cases a bit faster than C++ during the last 10 years. Don't blame Java. If you get worse performance, it will be probably mainly your fault.

I don't think he's writing a scientific paper here, just a blog post. If the engineers at Google draw the same conclusions in a benchmark that looks pretty good to me I have no trouble believing that highly optimized (i.e. requiring a LOT of effort and expertise) C++ code can blow Java out of the water in some cases. Here's some quotes from the benchmark which give a great summary IMHO:

Quote

C++ provides the best performance by far, but it requires the most extensive language-specific tuning.

Quote

The algorithm was simplest to implement in Java, but garbage collection settings make both Java and Scala difficult to benchmark accurately.

The most important point I think is: who cares? Maybe for some highly specific cases in which you have to squeeze out every last drop of performance this may matter. But I don't think it matters at all for 99.99% of the games out there, and people should choose the language they like and are most productive with.

I don't think he's writing a scientific paper here, just a blog post. If the engineers at Google draw the same conclusions in a benchmark that looks pretty good to me I have no trouble believing that highly optimized (i.e. requiring a LOT of effort and expertise) C++ code can blow Java out of the water in some cases.

Yay for scala being the second!

Some quotes from the PDF (and some reasons for learning scala):

Quote

A. Code Size [...] Code is an important factor in program comprehension. Studies have shown that the average time to recognize a token in code is a constant for individual programmers. As a result, less tokens means goodness. Note that the Scala and Go versions are significantly more compact than the verbose C++ and Java versions.

Also, in the graph the 'scala pro' version (written from an experienced scala programmer, 2nd fastest code in the benchmark) had the least lines of code. Only 297. Almost 3 times less than C++ and almost 4 times less then Java (java was the worst, btw)...

Another interesting quote - not about 'use scala' this time:

Quote

C. Tuning Garbage Collection Originally the Java and Scala benchmarks were run with 64-bit Java, using -XX:+UseCompressedOops, hoping to get the benefits of 64-bit code generation, without incurring the memory penalties of larger pointers. Run-time is 134 secs, as shown in above table. To verify the assumptions about 64/32 bit java, the bench- mark was run with a 32-bit Java JVM, resulting in run-time of 290 secs, or a 2x slowdown over the 64-bit version. To evaluate the impact of garbage collection further, the author pickedthe GC settings from a major Google application componentwhich is written in Java. Most notably, it uses the concurrent garbage collector. Running the benchmark with these options results in run- time of 106 secs, or a 3x improvement over the default 32-bit GC settings, and a 25% improvement over the 64-bit version. Running the 64-bit version with these new GC settings, run-time was 123 secs, a further roughly 10% improvement overthe default settings.

And now - again about scala - that is very, very interesting:

Quote

F. Scala Tunings Daniel Mahler improved the Scala version by creating a more functional version, which is kept in the Scala Pro directories. This version is only 270 lines of code, about 25% of the C++ version, and not only is it shorter, run-time also improved by about 3x.

And finally, I like the conclusion:

Quote

We find that in regards to performance, C++ wins out bya large margin. However, it also required the most extensivetuning efforts, many of which were done at a level of sophisti-cation that would not be available to the average programmer.Scala concise notation and powerful language features al-lowed for the best optimization of code complexity.The Java version was probably the simplest to implement,but the hardest to analyze for performance. Specifically theeffects around garbage collection were complicated and veryhard to tune. Since Scala runs on the JVM, it has the sameissues.

If the engineers at Google draw the same conclusions in a benchmark that looks pretty good to me I have no trouble believing that highly optimized (i.e. requiring a LOT of effort and expertise) C++ code can blow Java out of the water in some cases. Here's some quotes from the benchmark which give a great summary IMHO:

Quote

C++ provides the best performance by far, but it requires the most extensive language-specific tuning.

Quote

The algorithm was simplest to implement in Java, but garbage collection settings make both Java and Scala difficult to benchmark accurately.

The most important point I think is: who cares? Maybe for some highly specific cases in which you have to squeeze out every last drop of performance this may matter. But I don't think it matters at all for 99.99% of the games out there, and people should choose the language they like and are most productive with.

IBM draws different conclusions in HPC (IBM engineers conclude Java beats Fortran except in scalability) and I have no trouble believing that smart Java code can blow C++ out of the water in more and more cases.

An unsafe language like C++, or really more the C parts of it, can technically outrun any managed language runtime like Java, because they can bang on arbitrary memory to write almost any instruction sequence they want, and that's without embedded assembly. The problem is, how much effort does that take for how much actual payoff, and what are the bugs that are created when the results of the effort aren't 100% perfect?

Heck, in C++ you can even have assembler blocks if you're that kind of maniac, but again, requires more effort and care on the part of the programmer to avoid making the computer explode.

My personal philosophy regarding languages is that it's not the tool that makes the project, but the programmer's skill.

I'm kind of pressured into that mindset, since in my line of work, I'm actually forced to use specific programming languages for specific devices, and performance is expected to be the same regardless.

I just wrote a small blog post about my experience in working with Java for game programming. It is mostly things I stumbled upon while working on Caromble! for the last few years. Check it out: http://www.goo.gl/GD7nm

An unsafe language like C++, or really more the C parts of it, can technically outrun any managed language runtime like Java, because they can bang on arbitrary memory to write almost any instruction sequence they want, and that's without embedded assembly.

At the end of nineties, C/C++ fans gave the same kind of arguments to explain that as Java is written in C (Jikes was written in C++), it can't outperform C which is wrong. One of my teacher wrote a program that converted Java (1.3) to C code during his thesis and he only obtained a very small gain (less than 5%) after years of work. Brian Goetz explained that memory allocation and method calls are between 2 and 4 times faster in Java. I really think that almost no human being is able to write a better machine code or assembler code that a compiler like GCC except in particular cases on a small piece of source code and if you really believe you can be more efficient than the JVM, don't use Java. I'm sad to see these kinds of prejudices about Java even here on JGO.

An unsafe language like C++, or really more the C parts of it, can technically outrun any managed language runtime like Java, because they can bang on arbitrary memory to write almost any instruction sequence they want, and that's without embedded assembly.

At the end of nineties, C/C++ fans gave the same kind of arguments to explain that as Java is written in C (Jikes was written in C++), it can't outperform C which is wrong. One of my teacher wrote a program that converted Java (1.3) to C code during his thesis and he only obtained a very small gain (less than 5%) after years of work. Brian Goetz explained that memory allocation and method calls are between 2 and 4 times faster in Java. I really think that almost no human being is able to write a better machine code or assembler code that a compiler like GCC except in particular cases on a small piece of source code and if you really believe you can be more efficient than the JVM, don't use Java. I'm sad to see these kinds of prejudices about Java even here on JGO.

No one use standard memory allocator for performance critical code and inlined method have zero method call overhead.

And I'm sad about statements like this one, which implies two very wrong things:

That people approach languages based on prejudice rather than on rational assessment. If actual verifiable proof is presented of one language outperforming the other, then that's that. But way too often I see that proponents of either "side" are careful to ignore or outright dismiss whatever piece of evidence is presented that contradicts them.

That participating in JGO somehow makes you part of the "team" and your opinions have to conform to that of others.

Again, programming languages are tools, and discussing their strengths/weaknesses is fine. But when people start taking it personally, then it's time to take a step back.

Again, programming languages are tools, and discussing their strengths/weaknesses is fine. But when people start taking it personally, then it's time to take a step back.

Well I'm sure you know why is that way.Basically the name Java has forever been tainted, wrongly so, with poor performanceyou shouldn't associate your commercial products, especially games with java, because it can only hurt you - since there is this prejudice

An unsafe language like C++, or really more the C parts of it, can technically outrun any managed language runtime like Java, because they can bang on arbitrary memory to write almost any instruction sequence they want, and that's without embedded assembly.

At the end of nineties, C/C++ fans gave the same kind of arguments to explain that as Java is written in C (Jikes was written in C++), it can't outperform C which is wrong. One of my teacher wrote a program that converted Java (1.3) to C code during his thesis and he only obtained a very small gain (less than 5%) after years of work. Brian Goetz explained that memory allocation and method calls are between 2 and 4 times faster in Java. I really think that almost no human being is able to write a better machine code or assembler code that a compiler like GCC except in particular cases on a small piece of source code and if you really believe you can be more efficient than the JVM, don't use Java. I'm sad to see these kinds of prejudices about Java even here on JGO.

Where Java is faster, you can of course implement Java in C and do it that way. Kinda like how you can build anything out of raw materials, assuming you like working with only raw materials. Actually, I rather stretched the truth saying that you can emit any instruction in C, but most modern compilers support "rawcall" conventions and of course embedded asm. Not that you're really writing C at that point, of course.

Jikes is indeed in C++, but is merely a compiler (and an obsolete one at that). The javac compiler is pure java. Curiously though, the Jikes Research VM is itself in java (presumably with some native code to bootstrap itself).

Basically the name Java has forever been tainted, wrongly so, with poor performanceyou shouldn't associate your commercial products, especially games with java, because it can only hurt you - since there is this prejudice

I'm not disagreeing with that, and I understand it. I just hope we could try to move past that.

Quote

Well most people are morons and approach everything in life based on prejudice.

I know, I know. I'm pretty aware I'm a total idiot myself and will sometimes ramble about things just based on my feelings about it. But hey, being aware of a flaw is the first step to overcoming it.

Language benchmarks are mostly useful to language implementors. Let me quote the referenced benchmark: "A team at Google created a "simple and compact" benchmark that didn't take advantage of language-specific features. An algorithm was implemented using each language's "idiomatic container classes, looping constructs, and memory/object allocation schemes.".

"Simple & compact" = can't be testing much."memory/object allocation schemes" = using default malloc/free in C++ which is dumb if you want high performance."didn't take advantage of language-specific features" = WTF? The not much tested is totally meaningless.

Every single time I've compared code that I've implemented in Java and C, the C version completely smokes the Java...no contest...not even close.

Switching to serious mode: I can't agree or disagree with you, I've lost exactly what you are referring to. If I compare my C code to Java code that performs the same task, the Java code wins at all times. Because its far easier to read, often more compact and written and debugged in far less time. That's my personal reality.

Taking a step back, most folks really shouldn't care about the speed difference between C/C++ and Java. They're smallish linear differences say between 4-20x. And most people will only see the bottom end of that range because they aren't going to be taking advantage of SIMD and cache oblivious methods (to name a couple). And more to the point most people don't need to push tons of computations. And since the speed difference is linear, algorithmic improvement is much more important than the choice of language. Likewise moving away from single threaded to multi-threaded should give a nice additional linear boost. Now of course the same changes could be applied to a C/C++ version as well, so it boils down to your point: which language (or some other choice) can you to get the job done in the least amount of engineering time (and to spec)? Choose that language and run with it.

What am I referring to is simple. I only benchmark very expensive computations and C/C++ exposes a closer to the metal feature set which allow for very significant performance gains. We've covered what Java's (actually the JVM) missing to allow to help close the gap pretty much ad nauseam. Sometimes some programming trickery (a la Riven's structure library) can help, but mostly we're SOL until some features are added to the JVM.

Not serious mode: Java? compact? And you said that with a straight face?

Personally, I've ported some signal processing code between C, Java, C#, and Scala. C ran with 20% less time than Java. C# ran much slower than Java (Windows, Microsoft implementation). Scala actually ran ~5-10% faster than Java which surprised me because I thought they would compile to roughly the same bytecode and run on exactly the same runtime.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org