 |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | Is Java Slow? | |
< < | No. Once upon a time, when Java was brand new, there were some real performance issues. Today however modern Desktop VMs have the equivalent of C/C++ performance. This was shown as early as 3 years ago in benchmarks done by a gentleman by the name of Chris Rijk, and things have only improved since Chris's benchmarks. | > > | No. Once upon a time, when Java was brand new, there were some real performance issues. Today however modern Desktop VMs have the equivalent of C/C++ performance. This was shown as far back as 2000 in some independant benchmarks by a man named Chris Rijk published on the very well respected site Ace's Hardware. You can find those here: http://www.aceshardware.com/Spades/read.php?article_id=153 | | | Note however that I say "equivalent" not "the same as." Just as there are faster and slower idioms in C (for instance, sequential access of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, well written Java code averages out to about the same speed as a program that does the equivalent functions in well written C/C++. | |
< < | This was shown as far back as 2000 in some independant benchmarks by a man named Chris Rijk published on the very well respected site Ace's Hardware. You can find those here: http://www.aceshardware.com/Spades/read.php?article_id=153 | > > | | | | Since then Java has only continued to get faster. |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | Note however that I say "equivalent" not "the same as." Just as there are faster and slower idioms in C (for instance, sequential access of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, well written Java code averages out to about the same speed as a program that does the equivalent functions in well written C/C++. | |
< < | This was shown as far back as 2000 by some independant benchamrks by a man named Chris Rijk published on the very well respected site Tom's Hardware. You can find those here: http://www.aceshardware.com/Spades/read.php?article_id=153 | > > | This was shown as far back as 2000 in some independant benchmarks by a man named Chris Rijk published on the very well respected site Ace's Hardware. You can find those here: http://www.aceshardware.com/Spades/read.php?article_id=153 | | | Since then Java has only continued to get faster. | | | * TribalTrouble
* MegaCorps Online
* Wurm Online | |
> > | * Flying Guns | | | Why does John Carmack say Java is too slow? | | | If you use Java utility libraries, particualrly large and compelx ones like Swing, you will pull a fair bit of code in. But thats code you requested and, if you don't like the cost, you can always write your own replacements. Its really up to you to set your trade-offs between ease of programming and efficiency in java, just liek in any other langauge. Java just gives you more options to chose from. | |
< < | Havign said all this, there ARE very very small Java(tm) configurations. The CLDC configuration as deployed on many existing cell phones, for instance, uses the KVM-- a VM designed to take up only a few K of overhead. The flip side is you lose a lot of the more interesting and performancing enhancing features of the J2SE? configuration. TANSTAAFL. | > > | Having said all this, there ARE very very small Java(tm) configurations. The CLDC configuration as deployed on many existing cell phones, for instance, uses the KVM-- a VM designed to take up only a few K of overhead. The flip side is you lose a lot of the more interesting and performancing enhancing features of the J2SE? configuration. TANSTAAFL. | | | |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | |
> > | | | | Is Java Slow?
No. Once upon a time, when Java was brand new, there were some real performance issues. Today however modern Desktop VMs have the equivalent of C/C++ performance. This was shown as early as 3 years ago in benchmarks done by a gentleman by the name of Chris Rijk, and things have only improved since Chris's benchmarks.
Note however that I say "equivalent" not "the same as." Just as there are faster and slower idioms in C (for instance, sequential access of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, well written Java code averages out to about the same speed as a program that does the equivalent functions in well written C/C++. | |
> > | This was shown as far back as 2000 by some independant benchamrks by a man named Chris Rijk published on the very well respected site Tom's Hardware. You can find those here: http://www.aceshardware.com/Spades/read.php?article_id=153
Since then Java has only continued to get faster.
Thanks to .uj for pointing out that some people still need to be told about what was proved six years ago
This benchmark says Java is slow...
Benchmarking Java is a very complicated thing to do correctly because of the complication of the Just In Time compiler (JIT, see below). Problems need to be of significant size, act the way real programs do and not the way microbenchmarks typically act, and run long enough to let the JIT do its thing.
Chris gives an excellent summation of the right way to do Java benchmarks in his article referenced above.
Furthermore, as Chris Rijk demonstrates, programs written for C will almost always perform better in C. But programs written for Java will almost always perform better in Java. Different languages handle different kinds of algorthyms better or worse. Thus a benchmark has to be about results and, rather then a straight port, re-coded to each platform's strengths in order to give meaningful results.
| | | I thought Java was interpreted.
No. Java has a runtime management system called a Virtual Machine or VM, but that VM is free to take any strategy it wishes to execute code. Since the second generation or so of Java VMs on the desktop, the VMs have used a strategy called Just In-time Compilation or JIT. The JIT compiles the code the same way a C compiler does except it waits until run-time to do the compilation. | | | Unfortunateley, since he hasn't explored modern desktop Java at all, he is somewhat blind to where the cell phones are heading. | |
< < | My Java program is slow, what can I do about it? | > > | My Java program is slow, what can I do about it? | | | I'm glad you asked. First off, I'd suggest reading the book Steve and I wrote on how to performance tune Java code. Its a little old now and some of the stuff is a bit out of date (mostly the stuff regarding garbage collection, which the modern VMs do much faster then they used to) but the majority of it still applies. If you can't afford to buy it, you can read it here: |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | * Jake2
* TribalTrouble
* MegaCorps Online | |
< < | * Worm Online | > > | * Wurm Online | | | Why does John Carmack say Java is too slow? | | | If you use Java utility libraries, particualrly large and compelx ones like Swing, you will pull a fair bit of code in. But thats code you requested and, if you don't like the cost, you can always write your own replacements. Its really up to you to set your trade-offs between ease of programming and efficiency in java, just liek in any other langauge. Java just gives you more options to chose from. | |
< < | Havign said all this, there ARE very very small Java(tm) configurations. The CLDC configuration for instance uses the KVM-- a VM designed to take up only a few K of overhead. The flip side is you lose a lot of the more interesting and performancing enhancing features of the J2SE? configuration. TANSTAAFL. | > > | Havign said all this, there ARE very very small Java(tm) configurations. The CLDC configuration as deployed on many existing cell phones, for instance, uses the KVM-- a VM designed to take up only a few K of overhead. The flip side is you lose a lot of the more interesting and performancing enhancing features of the J2SE? configuration. TANSTAAFL. | | | |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | Most desktop computers are accurate enough on most calculations to satisy Java, so this is rarely an issue on the desktop. An exception however is trigonometry (Sin, Cos, Tan) on the x86 platform. At the level of accuracy Java requries, x86 built in trig primatives are broken at angles less then -45 degree or greater then positive 45 degrees. For angles outside of this range the built-in functions return incorrect approximations. Ergo when Java is asked to caclulate a trig function for an angle outside of this range, it defaults to a software trig function which has the necessary accuracy but is slower. | |
< < | This isn't as bad as it first sounds. Trig functions are repeating waveforms. Additionally they reflect around the key points of 90 degrees and 45 degrees. By juudicious use of a handful of compares, mods and subtracts it is possible to reduce any angle down to an angle with an equivalent trig result in the 0 to 45 degree range. (See my JeffGems page for how to do this.) | > > | This isn't as bad as it first sounds. Trig functions are repeating waveforms. Additionally they reflect around the key points of 180 degrees and 90 degrees. By juudicious use of a handful of compares, mods and subtracts it is possible to reduce any angle down to an angle with an equivalent trig result in the -45 to 45 degree range. (See my JeffGems page for how to do this.) | | | The situation gets thornier however on smaller devices, particulrly those in the embedded space such as set-top boxes and cell phones. Embedded processors are designed primarily for size, cost and power consumption and not necessarily for accuracy. Ergo there are some embedded processors that fail Java's accuracy requirements even for basic math operations. Today, according to the specifications, Java has no choice but to simulate the math on these inaccurate processors in software. There has been talk about maybe someday allowing some kind of "platformfp" flag that would give Java permission to be as inaccurate as the platform it is on but this is not an option today. | |
> > | Doesn't this VM stuff take up a lot of memory?
Well, how do you define "a lot"? Is there some over-head to a Java(tm) Platform? Sure there is. J2SE?, the largest and most sophisticated Java(tm) Configuration takes about 4 meg of memory base over-head.
Is that a lot? Well its a big percentage of a console "Hello World" app, but its less then 1% of a 500 megabyte video game.
For that 4 meg, the VM is doing a lot for you-- from run-time compilation and optimization to very very efficient memory handling and extremely sophisticated garbage collection. It also gives you the ability to attach a profiler and get very detailed information on the running state that can be very important when finding bottlenecks or application memory management issues. You can trace the allocation and references to every object in the program if need be. You can download code from machines that have never seen your machine and it will be automaticaly compiled correctly for your machien and integrated tightly into your running program with as much efficiency as if it had been there when the core program was compiled. It gives you detailed back traces for any exception so you cna see exactly what went wrong where.
In short, its a pretty big bargin at only 4 meg of memory. As explained above to get close to the same performance and features using an ahead of time compiler actually takes much more memory.
Now there are other ways to bloat your Java code. In particular, reflection information can become quite large. Reflection information is basically the equivalent of what C compilers build into the debug version of a C program. Java always includes it because Java has all sorts of fancy run-time features thhat let you use it to discover the details of classes on the fly. This is a very powerful feature, but not all programs need it. If you don't and you are short on memory, you can always prune it down to practically nothing by use of an "obfuscator."
If you use Java utility libraries, particualrly large and compelx ones like Swing, you will pull a fair bit of code in. But thats code you requested and, if you don't like the cost, you can always write your own replacements. Its really up to you to set your trade-offs between ease of programming and efficiency in java, just liek in any other langauge. Java just gives you more options to chose from.
Havign said all this, there ARE very very small Java(tm) configurations. The CLDC configuration for instance uses the KVM-- a VM designed to take up only a few K of overhead. The flip side is you lose a lot of the more interesting and performancing enhancing features of the J2SE? configuration. TANSTAAFL.
| | | |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | So the upshot of all this is that ahead of time compiling Java leads to either slow Java code or a much bigger RAM requirement then doing it the JIT way. | |
> > | Why is Java a late bound language?
This is an interesting question and one that properly should be answered by the original designers of the Java(tm) Platform, but I'll give you my perceptions.
Java is designed to be a highly modular language. This allows for very clean seperation of logical units of code. It is worth noting that the inspiration for Java came equally from C++ and from Modula2/Modula3. As I understand it, it was the perception of the original language designers that the more modular a language is, the more re-usable code becomes and the less re-inventing the wheel that needs to be done when starting a new project.
My own experience has certainly backed that up. As a C programmer of 15 years and a C++ programmer of 10 years, I have personally always strived towards more modular and reusable code. In the end however the early-bound nature of languages like C and C++ have always pushed me away from building a truely reusable code base. (The formal observation of why this happens in C++ is summed up in the "fragile base class" explaination.) In Java, I have a utils package I have been growing over the years and I very seldom need to re-write anything I've put into it.
While modularity is possible in C through DLLs, the interface to DLLs is limited to a fixed call interafce and does not have the flexability of a Java class library where I can either instantiate the objects as is, or import and modify them through inheritance. While in theory you can do almost anything you can do with inheritance through function pointers in C, in practice you have to think much further ahead and build specific infrastructure into your DLL code to allow for this.
As important, because modularity is central to Java, it is fast in Java. As explained above the VM is tuned to deal with such late bound code as a primary purpose. C DLLs by definition cannot be inlined or oherwise take part in global optimization. The same is true for the late-binding mechanism in C++ -- virtual method calls.
For all these reasons, I find Java late binding a vast improvement over the previous primarily early bound languages.
Special thanks goes to the Beyond3D?.com community for pointing out the need for the above point. | | | My Java cell phone sure seems slow.
There are three main kinds of Java today, ranging from the most modern and capable to the least: J2SE?, J2ME/CDC and J2ME/CLDC. (for more information see my "WhatIsJava?" section.) |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | No. Once upon a time, when Java was brand new, there were some real performance issues. Today however modern Desktop VMs have the equivalent of C/C++ performance. This was shown as early as 3 years ago in benchmarks done by a gentleman by the name of Chris Rijk, and things have only improved since Chris's benchmarks. | |
< < | Note however that I say "equivalent" not "the same as." Just as there are faster and slower idioms in C (for instance, sequential access of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, Java code averages out to about the same speed as a program that does the equivalent functions in C/C++. | > > | Note however that I say "equivalent" not "the same as." Just as there are faster and slower idioms in C (for instance, sequential access of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, well written Java code averages out to about the same speed as a program that does the equivalent functions in well written C/C++. | | | I thought Java was interpreted. | | | The other, more common reason to see GC problems in game is if you have an object leak. This is code that is creating objects and holding onto references to them (thus getting them promoted out of the short-lived objects) but you have forgotten about and thus create new ones. This out-of-control allocation and retention of objects eats up all your available memory and starts forcing the system to do long-lived garbage collects (GCs) when it should have no need to. Again, you can detect this with your profiler which will show you what is currently allocated and what still references it. | |
> > | Someone told me that math is faster in C then in Java
Okay, now this time "someone" isn't entirely incorrect. In general math on desktop computers today in Java is as fast as math in C, but there are a few exceptional cases where this is not true.
The reason is because Java has accuracy gauarntees on its math while C does not. C code is free to use the local hardware and return whatever result the hardware returns. C results for the same math calculation thus can and do differ on different computing platforms. Java on the other hand is gauranteed to return the same results on all computing platforms. For the same gaurantee of correctness, C would take as long as Java for every math operation.
Most desktop computers are accurate enough on most calculations to satisy Java, so this is rarely an issue on the desktop. An exception however is trigonometry (Sin, Cos, Tan) on the x86 platform. At the level of accuracy Java requries, x86 built in trig primatives are broken at angles less then -45 degree or greater then positive 45 degrees. For angles outside of this range the built-in functions return incorrect approximations. Ergo when Java is asked to caclulate a trig function for an angle outside of this range, it defaults to a software trig function which has the necessary accuracy but is slower.
This isn't as bad as it first sounds. Trig functions are repeating waveforms. Additionally they reflect around the key points of 90 degrees and 45 degrees. By juudicious use of a handful of compares, mods and subtracts it is possible to reduce any angle down to an angle with an equivalent trig result in the 0 to 45 degree range. (See my JeffGems page for how to do this.)
The situation gets thornier however on smaller devices, particulrly those in the embedded space such as set-top boxes and cell phones. Embedded processors are designed primarily for size, cost and power consumption and not necessarily for accuracy. Ergo there are some embedded processors that fail Java's accuracy requirements even for basic math operations. Today, according to the specifications, Java has no choice but to simulate the math on these inaccurate processors in software. There has been talk about maybe someday allowing some kind of "platformfp" flag that would give Java permission to be as inaccurate as the platform it is on but this is not an option today.
| | | -- Main.jeffpk - 03 Dec 2005 |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | Why isn't Java pre-compiled like C? | |
< < | The JIT may seem like an odd concept to you. After all, C compilers compile the C code ahad of time so it is ready to go as soon as you start the program. Why wait for the last minute for Java? Wouldn't it be simpler and less costly to compile Java ahead of time as well? | > > | The JIT may seem like an odd concept to you. After all, C compilers compile the C code ahead of time so it is ready to go as soon as you start the program. Why wait for the last minute for Java? Wouldn't it be simpler and less costly to compile Java ahead of time as well? | | | As in many things, in this case the seemingly intuitively obvious answer is dead wrong. The reason Java is not compiled ahead of time like C (or pascal or most other languages that came before it) is because Java is a very different kind of language. C and the other languages we mentioned are all "early bound languages." What this means is that in a C program, the code that has to be run as a result of every function call is known at compile time. In C++ this is true for all but "virtual" method calls. Java however is late-bound. Because classes are loaded individually at run-time, and because any call can be over-ridden by a sub-class (except final calls but they only exist for specific security programming reasons and otherwise should be avoided) the code that will be run as a result of any given method invocation cannot be determined ahead of time. | | | Again, on modern VMs no. In fact, some of the garbage avoidance strategies we used to use with older VMs, like object pooling, are actually detrimental to performance today. | |
< < | In general, modern J2SE? VMs handle the allocation and delallocation of short-lived objects just about invisibly. This means you are free today to create objects just to pass in and out of method calls or hold temporary values, a practice which makes your code a whole lot neater, less buggy, and simpler to maintain. | > > | In general, modern J2SE? VMs handle the allocation and deallocation of short-lived objects just about invisibly. This means you are free today to create objects just to pass in and out of method calls or hold temporary values, a practice which makes your code a whole lot neater, less buggy, and simpler to maintain. | | | | |
< < | Long lived objects are gnerally fine too because in most games those objects are loaded and then aren't freed up til a level change. You can afford a GC hit during those "down times" when the player isnt in the middle of gameplay. (Likely you'll be blocked on IO loading resources anyway.) The thing you do want to avoid is "mid-lived" objects. These are objects that you keep around for awhile, enough time for the VM to think they aren't short-lived, but then dispose of in the midst of gameplay. Its fairly unusual for this sort of life-cycle to show up in game programming but if you are seeing GC pauses then its possible you have this sort of problem. You can detect and correct it with the help of your trusty profiler. | > > | Long lived objects are generally fine too because in most games those objects are loaded and then aren't freed up til a level change. You can afford a GC hit during those "down times" when the player isnt in the middle of gameplay. (Likely you'll be blocked on IO loading resources anyway.) The thing you do want to avoid is "mid-lived" objects. These are objects that you keep around for awhile, enough time for the VM to think they aren't short-lived, but then dispose of in the midst of gameplay. Its fairly unusual for this sort of life-cycle to show up in game programming but if you are seeing GC pauses then its possible you have this sort of problem. You can detect and correct it with the help of your trusty profiler. | | | | |
< < | The other, more common reason to see GC problems in game is if you have an object leak. This is code that is creating objects and holding onto references to them (thus getting them promoted out of the short-lived objects) but you have forgotten about and thus create new ones. This out-of-control allocation and retn\ention of objects eats up all your available memory and starts forcing the system to do long-lived garbage collects (GCs) when it should have no need to. Again, you can detect this with your profiler which will show you what is currently allocated and what still references it. | > > | The other, more common reason to see GC problems in game is if you have an object leak. This is code that is creating objects and holding onto references to them (thus getting them promoted out of the short-lived objects) but you have forgotten about and thus create new ones. This out-of-control allocation and retention of objects eats up all your available memory and starts forcing the system to do long-lived garbage collects (GCs) when it should have no need to. Again, you can detect this with your profiler which will show you what is currently allocated and what still references it. | | |
-- Main.jeffpk - 03 Dec 2005 |
| |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance | | | No. Once upon a time, when Java was brand new, there were some real performance issues. Today however modern Desktop VMs have the equivalent of C/C++ performance. This was shown as early as 3 years ago in benchmarks done by a gentleman by the name of Chris Rijk, and things have only improved since Chris's benchmarks. | |
< < | Note however that I say "equivalent" not "the same is." Just as there are faster and slower idioms in C (for instance, sequential acces of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, Java code averages out to about the same speed as a program that does the equivalent functions in C/C++. | > > | Note however that I say "equivalent" not "the same as." Just as there are faster and slower idioms in C (for instance, sequential access of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, Java code averages out to about the same speed as a program that does the equivalent functions in C/C++. | | | I thought Java was interpreted. | | | The JIT may seem like an odd concept to you. After all, C compilers compile the C code ahad of time so it is ready to go as soon as you start the program. Why wait for the last minute for Java? Wouldn't it be simpler and less costly to compile Java ahead of time as well? | |
< < | As in many things, in this case the seemingly intuitively obvious answer is dead wrong. The reason Java is not compield ahead of time like C (or pascal or most other languages that came before it) is because Java is a very different kind of language. C and the other languages we mentioned are all "early bound languages." What this means is that in a C program, the code that has to be run as a result of every function call is known at compile time. In C++ this is true for all but "virtual" method calls. Java however is late-bound. Because classes are loaded individually at run-time, and because any call can be over-ridden by a sub-class (except final calls but they only exist for specific security programming reasons and otherwise should be avoided) the code that will be run as a result of any given method invocation cannot be determined ahead of time. | > > | As in many things, in this case the seemingly intuitively obvious answer is dead wrong. The reason Java is not compiled ahead of time like C (or pascal or most other languages that came before it) is because Java is a very different kind of language. C and the other languages we mentioned are all "early bound languages." What this means is that in a C program, the code that has to be run as a result of every function call is known at compile time. In C++ this is true for all but "virtual" method calls. Java however is late-bound. Because classes are loaded individually at run-time, and because any call can be over-ridden by a sub-class (except final calls but they only exist for specific security programming reasons and otherwise should be avoided) the code that will be run as a result of any given method invocation cannot be determined ahead of time. | | | | |
< < | It turns out that knowing what code will be run is critical for many important optimization techniques and so Java code compield ahead of time would be virtually un-optimized and thus very slow. At run-time however the VM can examine the actual running code and determine what code is really being called from any function call and do those optimizations. Due to Java's late binding it cannot be sure even then, however, that the situation won't change and some future time that particualr function call is executed, differnt code won't be called. By watching the environment however it can determine if the danger exists. If the danger crops up, then the VM actually backs those optimizations out, changing the code on the fly. | > > | It turns out that knowing what code will be run is critical for many important optimization techniques and so Java code compiled ahead of time would be virtually un-optimized and thus very slow. At run-time however the VM can examine the actual running code and determine what code is really being called from any function call and do those optimizations. Due to Java's late binding it cannot be sure even then, however, that the situation won't change and at some future time the particular function call is executed, differnt code might be called. By watching the environment however it can determine if the danger exists. (For instance, this can never ocurr if the target classt has no loaded sub-classes.) If the danger crops up, then the VM actually backs those optimizations out, changing the code on the fly. | | | None of this is possible with an ahead of time compiler. | | | So the upshot of all this is that ahead of time compiling Java leads to either slow Java code or a much bigger RAM requirement then doing it the JIT way.
My Java cell phone sure seems slow. | |
< < | There are three main kinds of Java today, ranging from the most modern and capable to the least: J2SE?, J2ME/CDC and J2ME/CLDC. (for more information see my "WhatIsJava?" page.) | > > | There are three main kinds of Java today, ranging from the most modern and capable to the least: J2SE?, J2ME/CDC and J2ME/CLDC. (for more information see my "WhatIsJava?" section.) | | | All the cell phones today use J2ME/CLDC. The design and functionality of J2ME/CLDC isintended for highly limited devices, which is what the current cell phones are. They have slow processors and very limited RAM memory. In order to fit the functionality of Java into these devices a lot of the more sphosticated internals of modern VMs had to be removed. The result is a system that is significantly slower then desktop Java (J2SE?) and thus slower then C code on those devices. | |
< < | This is however a tenmporary phenomenon and one that is almost over. Cell phones are advancing approximately the same amount as one generation ofgame consoles advances every year. The next generation of phones will easily be able to move up to the middle level of Java, J2ME/CLDC, which has approximately 85% of the speed of the desktop. The generation after that is likely to see VMs as sophisticated as what we have on the desktop today. | > > | This is however a tenmporary phenomenon and one that is almost over. Cell phones are advancing every year approximately the same amount as one generation of game consoles advances over the previous one. The next generation of phones will easily be able to move up to the middle level of Java, J2ME/CLDC, which has approximately 85% of the speed of the desktop. The generation after that is likely to see VMs as sophisticated as what we have on the desktop today. | | | Someone told me Java is too slow for real games. | | | John Carmack is a very intelligent man and he knows his areas, graphics hardware and software and bit-twiddled C coding, extremely well. Like many men who are experts in their own fields however he sometimes falls prey to the mistake of not knowing what he doesn't know. | |
< < | Mr. Carmack is actually fairly ignorant when it comes to Java technology. His only recent expeince with Java has been with the aforementioned cell phones and, like many who come to Java through the phones, he doesn't seem to understand yet that he is dealing with the most limited form of Java there is. His comments are fudementally accurate except that when he says "Java" he really means J2ME/CLDC. | > > | Mr. Carmack is actually fairly ignorant when it comes to Java technology. His only recent experience with Java has been with the aforementioned cell phones and, like many who come to Java through the phones, he doesn't seem to understand yet that he is dealing with the most limited form of Java there is. His comments are fudementally accurate except that when he says "Java" he really means J2ME/CLDC. | | | Unfortunateley, since he hasn't explored modern desktop Java at all, he is somewhat blind to where the cell phones are heading. | | | Do I need to avoid garbage collection? | |
< < | Again, on modern VMs no. In fact, some of the strategies we used to sue with older VMs like object pooling are actually detrimental to performance today. | > > | Again, on modern VMs no. In fact, some of the garbage avoidance strategies we used to use with older VMs, like object pooling, are actually detrimental to performance today. | | | In general, modern J2SE? VMs handle the allocation and delallocation of short-lived objects just about invisibly. This means you are free today to create objects just to pass in and out of method calls or hold temporary values, a practice which makes your code a whole lot neater, less buggy, and simpler to maintain. | |
< < | Long lived objects are gnerally fine too because in most games those objects are loaded and then aren't freed up til a level change. You can afford a GC hit during those "down times" when the player isnt in the middle of gameplay. (Likely you'll be blocked on IO loading resources anyway.) The thing you do want to avoid is "mid-lived" objects. These are objects that you keep around for awhile, enough time for the VM to think they aren't short-lived, but then dispose of in the midst of gameplay. Its fairly unusual for this sort of life-cycle to show up in game prgoramming but if you are seeing GC pauses then its possible you have this sort of problem. You can detect and correct it with the help of your trusty profiler. | > > | Long lived objects are gnerally fine too because in most games those objects are loaded and then aren't freed up til a level change. You can afford a GC hit during those "down times" when the player isnt in the middle of gameplay. (Likely you'll be blocked on IO loading resources anyway.) The thing you do want to avoid is "mid-lived" objects. These are objects that you keep around for awhile, enough time for the VM to think they aren't short-lived, but then dispose of in the midst of gameplay. Its fairly unusual for this sort of life-cycle to show up in game programming but if you are seeing GC pauses then its possible you have this sort of problem. You can detect and correct it with the help of your trusty profiler. | | | | |
< < | The other, more common reason to see GC problems in game is if you have an object leak. This is code that is creating objects and holding onto references to them (thus getting them promoted out of the short-lived objects) but you have forgotten about and thus create new ones. This out-of-control allocation and retnetion of objects east up all your available memory and starts forcing the system to do long-lived garbage collects (gcs) when it should have no need to. Again, you can detect this with your profiler which will show you what is currently allocated and what still references it. | > > | The other, more common reason to see GC problems in game is if you have an object leak. This is code that is creating objects and holding onto references to them (thus getting them promoted out of the short-lived objects) but you have forgotten about and thus create new ones. This out-of-control allocation and retn\ention of objects eats up all your available memory and starts forcing the system to do long-lived garbage collects (GCs) when it should have no need to. Again, you can detect this with your profiler which will show you what is currently allocated and what still references it. | | |
-- Main.jeffpk - 03 Dec 2005 |
|
> > |
| META TOPICPARENT | name="JeffFAQ" |
Jeff On Performance
Is Java Slow?
No. Once upon a time, when Java was brand new, there were some real performance issues. Today however modern Desktop VMs have the equivalent of C/C++ performance. This was shown as early as 3 years ago in benchmarks done by a gentleman by the name of Chris Rijk, and things have only improved since Chris's benchmarks.
Note however that I say "equivalent" not "the same is." Just as there are faster and slower idioms in C (for instance, sequential acces of arrys by index is significantly slower then 'pointer walking') there are faster and slower idioms in Java. There are some things C/C++ is significantly faster at then Java, most noteably random (non-sequential) access into arrays. There are some things that Java is much faster at then C/C++, noteably allocation and deallocation of memory. This means that algorithyms that are optimal in C/C++ may be sub-optimal in Java, and vice versa. On the whole however, for any sigificantly complex problem, Java code averages out to about the same speed as a program that does the equivalent functions in C/C++.
I thought Java was interpreted.
No. Java has a runtime management system called a Virtual Machine or VM, but that VM is free to take any strategy it wishes to execute code. Since the second generation or so of Java VMs on the desktop, the VMs have used a strategy called Just In-time Compilation or JIT. The JIT compiles the code the same way a C compiler does except it waits until run-time to do the compilation.
Why isn't Java pre-compiled like C?
The JIT may seem like an odd concept to you. After all, C compilers compile the C code ahad of time so it is ready to go as soon as you start the program. Why wait for the last minute for Java? Wouldn't it be simpler and less costly to compile Java ahead of time as well?
As in many things, in this case the seemingly intuitively obvious answer is dead wrong. The reason Java is not compield ahead of time like C (or pascal or most other languages that came before it) is because Java is a very different kind of language. C and the other languages we mentioned are all "early bound languages." What this means is that in a C program, the code that has to be run as a result of every function call is known at compile time. In C++ this is true for all but "virtual" method calls. Java however is late-bound. Because classes are loaded individually at run-time, and because any call can be over-ridden by a sub-class (except final calls but they only exist for specific security programming reasons and otherwise should be avoided) the code that will be run as a result of any given method invocation cannot be determined ahead of time.
It turns out that knowing what code will be run is critical for many important optimization techniques and so Java code compield ahead of time would be virtually un-optimized and thus very slow. At run-time however the VM can examine the actual running code and determine what code is really being called from any function call and do those optimizations. Due to Java's late binding it cannot be sure even then, however, that the situation won't change and some future time that particualr function call is executed, differnt code won't be called. By watching the environment however it can determine if the danger exists. If the danger crops up, then the VM actually backs those optimizations out, changing the code on the fly.
None of this is possible with an ahead of time compiler.
Some ahead of time compilers actually do get close to the JIT's performance, but the way they do it is to actually compile multiple versions of the code ahead of time to cover all the possilble conditions and build that all into the final executable. The result is a program that, even though it doesn't need a JIT at run-time, is much much larger then the JIT version.(including the cost of the JIT.)
So the upshot of all this is that ahead of time compiling Java leads to either slow Java code or a much bigger RAM requirement then doing it the JIT way.
My Java cell phone sure seems slow.
There are three main kinds of Java today, ranging from the most modern and capable to the least: J2SE?, J2ME/CDC and J2ME/CLDC. (for more information see my "WhatIsJava?" page.)
All the cell phones today use J2ME/CLDC. The design and functionality of J2ME/CLDC isintended for highly limited devices, which is what the current cell phones are. They have slow processors and very limited RAM memory. In order to fit the functionality of Java into these devices a lot of the more sphosticated internals of modern VMs had to be removed. The result is a system that is significantly slower then desktop Java (J2SE?) and thus slower then C code on those devices.
This is however a tenmporary phenomenon and one that is almost over. Cell phones are advancing approximately the same amount as one generation ofgame consoles advances every year. The next generation of phones will easily be able to move up to the middle level of Java, J2ME/CLDC, which has approximately 85% of the speed of the desktop. The generation after that is likely to see VMs as sophisticated as what we have on the desktop today.
Someone told me Java is too slow for real games.
That someone is wrong.
The best proofs are existance proofs. Try some of these on for size:
* Jake2
* TribalTrouble
* MegaCorps Online
* Worm Online
Why does John Carmack say Java is too slow?
John Carmack is a very intelligent man and he knows his areas, graphics hardware and software and bit-twiddled C coding, extremely well. Like many men who are experts in their own fields however he sometimes falls prey to the mistake of not knowing what he doesn't know.
Mr. Carmack is actually fairly ignorant when it comes to Java technology. His only recent expeince with Java has been with the aforementioned cell phones and, like many who come to Java through the phones, he doesn't seem to understand yet that he is dealing with the most limited form of Java there is. His comments are fudementally accurate except that when he says "Java" he really means J2ME/CLDC.
Unfortunateley, since he hasn't explored modern desktop Java at all, he is somewhat blind to where the cell phones are heading.
My Java program is slow, what can I do about it?
I'm glad you asked. First off, I'd suggest reading the book Steve and I wrote on how to performance tune Java code. Its a little old now and some of the stuff is a bit out of date (mostly the stuff regarding garbage collection, which the modern VMs do much faster then they used to) but the majority of it still applies. If you can't afford to buy it, you can read it here:
Java(tm) Platform Performance
When actually tuning your program the first and most important thing to do, and we talk about this in the book, is to profile your code. Both Netebans and Eclipse have free profiler plug-ins available and that should always be your first step in solving a performance problem. You may think you know what your performance problem is, but you are probably wrong. I've been tuning code the better part of 15 years and I don't think my initial guess as to what my problem was has been right more then once or even close more then twice.
Once you know where your problem is, if the solution isn't obvious to you, then come on over to the JavaGaming.org forum on performance tuning and ask for some help.
Do I need to avoid garbage collection?
Again, on modern VMs no. In fact, some of the strategies we used to sue with older VMs like object pooling are actually detrimental to performance today.
In general, modern J2SE? VMs handle the allocation and delallocation of short-lived objects just about invisibly. This means you are free today to create objects just to pass in and out of method calls or hold temporary values, a practice which makes your code a whole lot neater, less buggy, and simpler to maintain.
Long lived objects are gnerally fine too because in most games those objects are loaded and then aren't freed up til a level change. You can afford a GC hit during those "down times" when the player isnt in the middle of gameplay. (Likely you'll be blocked on IO loading resources anyway.) The thing you do want to avoid is "mid-lived" objects. These are objects that you keep around for awhile, enough time for the VM to think they aren't short-lived, but then dispose of in the midst of gameplay. Its fairly unusual for this sort of life-cycle to show up in game prgoramming but if you are seeing GC pauses then its possible you have this sort of problem. You can detect and correct it with the help of your trusty profiler.
The other, more common reason to see GC problems in game is if you have an object leak. This is code that is creating objects and holding onto references to them (thus getting them promoted out of the short-lived objects) but you have forgotten about and thus create new ones. This out-of-control allocation and retnetion of objects east up all your available memory and starts forcing the system to do long-lived garbage collects (gcs) when it should have no need to. Again, you can detect this with your profiler which will show you what is currently allocated and what still references it.
-- Main.jeffpk - 03 Dec 2005 |
|