views:

2167

answers:

20

Ok, this is not trolling. It's a real, technical question.

Java has the reputation of being slow. There are jokes about it. I am not a great java user, the only occasional use I have is for applets, which are indeed quite slow, even on modern hardware.

My question: is Java really slow? If yes, why? Is it because of inefficient JVMs? Garbage collection? Pure bytecode libraries instead of JNI-wrapped C code ? Many other languages have these features, but they don't have this fame. Where is (or was) the bottleneck?

+1  A: 

Java is a high-level language and its reputation nowadays is to have performance on par with other, comparable high-level languages.

  1. It has dynamic binding semantics. Compared to C++ where non-virtual methods are compiled as function calls, even the best Java compiler in the world has to produce code that is less efficient. But it's also a cleaner, more high-level semantic.

  2. I do not remember the details, but I heard in the early days of Java that there was a mutex per Java object, to be acquired and released by each method. That tends to make it better adapted to concurrency, although unfortunately just a mutex per object will not protect you from races or deadlocks or any of the bad things that can happen in concurrent programs. That part, if true, is a little naive, but it came from good intentions. Feel free to fill me in on the details if you know more about this aspect.

  3. Another way in which Java is a high-level language is by having Garbage-Collection. Garbage-Collection may be slower than malloc and free for programs that allocate at once all the memory they need and work with that. The problem is, in languages that do not have Garbage-Collection, programmers tend to write only programs that allocate all the memory they need at once and fail if it turns out some arbitrary maximum size constant has been overflown. So the comparison is apples to oranges. When programmers make the effort to write and debug programs with dynamic allocation of chained structures in non-GC languages, they sometimes find that their programs are no longer faster than in a GC language, because malloc and free are not free! They have overhead too... Plus, not having a GC forces to specify who frees what, and having to specify who frees what in turn sometime forces you to make copies — when several functions are going to need the data and it's not clear which will be using it last — whereas copying wouldn't have been necessary in a GC language.

Pascal Cuoq
1. Probably not true with HotSpot. 2. Only if you mark the method as synchronized.
Winston Ewert
+8  A: 

It's out-dated information from the early days (mid-to-late 1990s) of Java. Every major version of Java has introduced significant speed-ups compared to the previous version. With Oracle apparently merging JRockit with Sun's JVM for Java 7, this trend looks set to continue.

Compared to many other popular modern languages (Python, Ruby, PHP), Java is actually significantly faster for most uses. It doesn't quite match C or C++ but for many tasks it's close enough. The real performance concerns ought to be about how much memory it ends up using.

Dan Dyer
+27  A: 

Initially Java was not particularly fast, but not overly slow either. These days Java is very fast. From the people I've talked to the impression of Java being slow comes from 2 things.

  1. Slow VM startup time. The early Java implementation took a long time to start up and load the require libraries and the application compared to native applications.

  2. Slow UI. Early Swing was slow. It probably did not help that most windows users found the default Metal L&F ugly either.

Given the above points, it's no wonder people got the 'Java is slow' impression.

For users or developers used to developing native apps, or even VB apps, these 2 points are the most visible thing in an application, and it is the first impression you will get about an application (unless it's a non-gui application in which case only the 1. applies.).

You will not convince a user that "it executes code very fast" when the application takes 8 seconds to start vs his old VB app that start immediately - even though code execution and startup time might not be connected at all.

Ruining the first impression is a great way to start rumors and myths. And rumors and myths are hard to kill.

In short, Java is not slow. People having the "Java is slow attitude" is based on first impressions of Java 10+ years ago.

nos
why the longer startup time ? Please don't be afraid to be technical. What I don't get I will look up once I have the keywords.
Stefano Borini
Java was very slow a few years ago but in recent benchmark tests it runs nearly as fast as C/C++ and in some situations it runs faster.
ChadNC
Startup times are quick nowadays. It *was* slow years ago, which was implementation details - e.g. the jvm loaded/decompressed almostthe entire standard library - not just the stuff the app needed
Anonym
ok, so basically the startup time was dominated by the repeated decompression of the whole library. but then I don't get another thing. Why did it have to be decompressed anew every time ?
Stefano Borini
Java apps on OSX 10.6 on my Macbook start much slower than apps written in Objective-C. What evidence for quick startup times?
Zan Lynx
@Zan ok but if java has to start up a non-memory resident JVM anew, even with optimizations, it will never be as fast (in startup times) as a native Obj-C code which hooks into most likely preloaded libraries of OSX.
Stefano Borini
@Stefano on decompression: they reduce redundant decompression, and reduce the amount that is loaded in recent builds. Java 7 will provide modularity, so you only load a tiny part of the library, and should provide startup times comparable to normal apps. Unfortunately, Java 7 is showing no signs of ever being released.
BobMcGee
Decompression is absolutely not a performance problem. My computer in 1992 decompressed executables when starting programs which improved performance over loading a longer file from the hard drive. The disparity between CPU and hard drive has grown enormously over the intervening years. However, there is a problem with using the zip archive format for rt.jar (why?!!!) and the contained class files are not linked (nuts!!).
Tom Hawtin - tackline
@Tom: You need to distinguish between compression algorithms. LZF, LZF, and LZJB are fast enough to improve on disk performance, and these are what you encountered in 1992. They're specifically designed to trade lower compression for very fast compress/decompress speed. DEFLATE is not designed for speed. While the CPU cost for ZIP has become less significant (and negligible on bleeding-edge CPUs) it still takes significant time when we're talking about multiple MB. Taking this another step: MP4 and LZMA are still very slow to compress/decompress even on modern CPUs.
BobMcGee
@Zan: note that the JVM for Mac OS X is written (or at least adapted) by Apple. Sun has invested quite some time to make startup times faster on the platforms they support (Windows, Linux and Solaris), but they couldn't do it for Mac OS x (since they don't maintain that port). It might be that Mac couldn't/didn't apply/port all those optimizations over to Mac OS X.
Joachim Sauer
I don't consider java to be slow (i know of a game maker who makes games in them); just bad for UI reasons. Not a single "regular" java app i've seen has a decent, completely working UI.
RCIX
@RCIX: You've never seen Eclipse? Lotus Notes? OK, bad example. ;) We have some apps here at work that look just like native Windows apps that are written in Java. The problem though is that it is slow. It's a lot better than it used to be, but my computer (2.4 GHz Core 2 Duo with 3 GB of RAM) still slows to a crawl when this app starts up.
jasonh
@jasonh: I don't consider Eclipse to have a decent UI because it doesn't particularly jive with any OS but windows. I'd have to see these apps that look just like windows apps...
RCIX
@RCIX: Unfortunately they're proprietary, so I don't have any links.
jasonh
@joachim, the trick Sun uses under Windows to make Java start faster is to have a process keep a copy of the essential JVM files in memory instead of being swapped out to disk. The random access to the JVM jar files makes unswapping much slower than needed.
Thorbjørn Ravn Andersen
+1  A: 

No, it's not slow, and in some cases it is faster than C code itself. Especially in Java 6, where allocation in the Java language is already much faster than it is in C.

The latest Java compilers are extremely efficient at performing optimizations.

It is possible for Java code to be faster than C, and it's headed in that direction.

Steve
Every case I have seen where Java benched faster than C or C++ was quickly solved by running a profiler over the C code, inlining a function or two, and recompiling with profiling feedback and inter-module optimization.
Zan Lynx
Java code can be profiled too! Granted, speeding it up usually requires more than just adding a compiler option. For me it usually involves replacing collections with arrays or replacing mathematical functions with lookup tables.
finnw
+1  A: 

I'm going to take it on faith that you're not trolling and answer this.

15 years ago when Java hit the mainstream, C++ was the dominant language, and the web was still fairly new. Also, JVMs and GC were relatively new concepts in mainstream development. The early JVMs were kind of slow (compared to C++ running on bare metal) and also suffered from sometimes long garbage collection pauses, which led to a reputation of Java being slow.

Ken Liu
was this due to the technology behind the GC ? I know they have some strategies (like generational layers for objects) to be more efficient in the GC phase. What was the strategy at that time ?
Stefano Borini
IANA JVM expert, but I think at the time there was a single threaded mark/sweep algorithm used for GC, which required the whole JVM to pause while the GC was being performed. Nowadays there is concurrent mark/sweep and also there are other many other performance enhancements in the JVM.
Ken Liu
Modern GC algorithms are nice but I think that the biggest improvement was JIT.
Pascal Thivent
+1  A: 

As Pascal says, Java is on par with other high level languages, however as someone who worked with the original JVMs on Windows 98, at the time the level of abstraction provided by the java virtual machine was, shall we say, painful.

Basically it was software emulation with little or no optimization that we take for granted today in the JVM.

caskey
+6  A: 

Java WAS slow, back in the day. It has become much faster, due to a few generations of performance enhancements. Last I heard, it is usually within 10% of C# speed -- sometimes faster, sometimes slower.

Java applet startup is still slow because you've got to start a whole JVM, which has to load all it's classes. Somewhat like booting another computer. Once the JVM starts it is quite fast, but the startup is usually what people remember.

Also, there are at least a few people that will never believe in the viability of Java.

Kaleb Brasee
But of course "everyone" knows C# is slow too ;)
John
LOL, I've had people tell me that C# is 10 times faster than Java.
Kaleb Brasee
JVM startup is still much slower than CLR startup, unfortunately. This is because Sun has dragged its feet in the worst way in releasing Java 7, so we're stuck with incremental patches to the **4 year old** Java 6.
BobMcGee
Wow, Java 6 is 4 years old??? Yep I guess so (if you count the beta). Still feels new to me -- I just stopped using 1.4 at work.
Kaleb Brasee
@Kaleb Let me guess: you are working in an IBM environment >:)
Pascal Thivent
You are correct! Ah, the wonderful world of WebSphere... :/
Kaleb Brasee
@Kaleb: Jesus, you IBM folks are really behind the times. Java 1.4 is usable, but kind of sucktastic, since 1.5 and 1.6 added a lot of performance boosts and syntactic sugar. Bounds-check and System.arraycopy optimizations were introduced since then. So were a lot of synchronization improvements. I think it's fair to say 1.4 genuinely IS slow.
BobMcGee
LOL, I know -- every time I have to iterate manually or use an array instead of a generic List, I want to break my laptop in half... IBM has actually had Java 5 available on WAS 6.1 for years, but I've been stuck on WAS 6.0 :( I have been using Java 5/6 since it came out for my own stuff, but am just limited by old server versions at work. There are double-digit percent performance improvements from 1.4 to the newest versions for a lot of things, and I am looking forward to them.
Kaleb Brasee
+54  A: 

Java is "slow" because you have to wait for the VM to start up. This used to be quite slow.

Modern Java is not slow, as others have noted. But, there are a couple exceptions:

  • Array access is still MUCH slower compared to C, due to bounds checks and so on. This improves with every version, and Java 7 should provide a massive boost here.
  • Lack of arbitrary memory access can make some I/O and bit-level processing slow (compression/decompression for example). This is a safety feature of most high-level languages now.
  • Java uses a LOT more memory than C, and if your application is memory bound or memory bandwidth bound (caching, etc) this makes it slower. The flip side is that allocation/deallocation is blazing fast. This is a feature of most high-level languages now, and due to use of GC rather than explicit memory allocation.
  • Streams-based I/O is slow as shit due to the (IMO poor choice) to require synchronization on stream access. NIO fixed this but is a pain to use. Java 7 should fix this with a new stream-based but unsynchronized I/O library.
  • Java doesn't provide the same low-level functionality C does, so you can't use dirty tricks to make some operations faster. This provides portability, but you can't use (for example) inline assembler or clever x86 tricks. This is a feature of most high-level languages now.
  • String operations are slow. Java uses immutable, UTF-16 encoded strings. This means you need more memory, more memory access, and some operations are more complex than with ASCII. It's the right decision for portability but carries a performance cost.
  • Startup times still suck. If I recall correctly, useless, bloated crap like CORBA still gets loaded or at least handled in some fashion.

In the end, Java was designed to provide security and portability at the expense of some performance, and for some really demanding operations it shows. Most of its reputation for slowness is no longer deserved. Still, Sun always chooses the "better" way rather than the "faster" way whenever it can.

Major Edit:

In all fairness, there are several places where Java is FASTER than most other languages:

  • Memory allocation and de-allocation are fast and cheap. I've seen cases where it is 20% FASTER (or more!) to allocate a new, multi-kB array than to reuse a cached one.
  • Object instantiation and object-oriented features are blazing fast to use (faster than C++ in many cases) because they're designed in from the beginning. This is partially from good GC rather than explicit allocation (which is more friendly to lots of small object allocations).
  • Method calls are basically free. The HotSpot compiler will inline for you, which makes for cleaner code, and sometimes it will do a better job than manual inlining can. Compare to C/C++ where method calls are very expensive, and performance sensitive code should be written as single massive methods.
  • Synchronization and multi-threading are easy and efficient. Java was designed to be thread-aware from the beginning, and it shows. Modern computers usually feature multiple cores, and because threading is built into the language, you can very easily take advantage. Basically an extra 100% to 300% speed boost vs. standard, single-threaded C code. Yes, carefully written C threading and libraries can beat this, but that's a lot of extra work for the programmer.
  • String class is intelligently designed. Substrings can include references to the parent String's character array (saving memory and time). String length is stored (rather than using null delimiters), allowing for many operations (concatenation, substring, length) to run very quickly.
  • Collections are fast. Standard Java beats standard C/C++ in this area, even for most optimized C code. Something to do with the object handling, I think.
  • Array copy is highly optimized. In the lastest 1.6.x versions, Java uses hand-tuned assembler for System.arraycopy. The result is that in arraycopy/memcopy-heavy operations, I've seen my code beat the equivalent in C by reasonable margins.
BobMcGee
That's fair enough. It _is_ worth pointing out that in number-crunching scenarios where you are maxing the CPU out for seconds or minutes, C++ will win out on benchmarks. But such apps are rare, and it's rarer that 10s Vs 20s run-time is important.
John
Actually, Java does fine for raw number crunching (very close to C and Fortran), for the most part. The lack of arbitrary memory access and (say) being able to read arbitrary bytes as a float, int or long makes some kinds of data processing slow. Yes, I know NIO allows this, but it's still not that fast.
BobMcGee
Nice list. I note the majority of point are features of *any* high-level language and **not** particular Java-specific design blunders. I take high-level features in a programming so much for granted these days that I forgot a bunch of them.
Pascal Cuoq
@Pascal: IMO Java and C# should be categorized halfway between the low-level languages (C, Fortran) and the truly high-level languages like Python, Ruby, and Perl. Java does not provide functional features or closures, and is statically typed. Performance-wise and syntactically these languages are closer to C/C++ than to the other high-level languages. Of course, if Sun would get off its ass about Java 7, that might change.
BobMcGee
If you need to do a lot of changes to a String, StringBuilder or directly changing the underlying character array is the way to go.
Helper Method
There are only edge cases where array access is slower. I've done quite a few benchmarks; C only deserves the "much" title when doing things like accessing many tiny arrays in random order; otherwise the JVM handles the bounds checks just like C. Also, startup times are a fraction of a second (basically imperceptible) for small programs. Java _does_ make it easier to load lots of dependencies than C does, but C programs that require lots of dynamically linked libraries will load slowly too. Partially inaccurate information like yours is one main reason why Java is still perceived as slow.
Rex Kerr
aren't C libraries accessed lazy ? the startup time should be low in C because the .so object and consequently the symbol is resolved only when needed, not at startup time.
Stefano Borini
@Rex: The current optimizations to the JVM only elliminate bounds-checks when the access pattern is a linear function of an indexing variable. Simple math over an array similar in speed to C, but hashtables and many common algorithms don't really benefit. ---------------------Startup times vary a lot. GUI apps still take several seconds to load up due to big libraries and JIT time. For command line programs, the startup time is still enough to make the "small, single-purpose utility" pattern you see in C utilities for *NIX a bad match for Java.
BobMcGee
@Stefano: Java is also lazy with libraries. @Bob: Random-access jumping algorithms in C that nonetheless do not require their own bounds check are rare--rarer still if the jump won't cause a cache miss (e.g. quicksorting small lists)--and even so it's a modest penalty. I agree that C wins for *NIX command-line utilities, but for GUIs it's really just the library time--Java has a slowish default, and C has no default (some options are slow). If the question is _is the speed of my program limited because I used Java, rather than other factors_, the answer today is almost always "no".
Rex Kerr
@Helper: I agree. Unfortunately, many libraries and methods explicitly specify String inputs, rather than CharacterSequence implementations. Also, you still have the overhead of UCS-16 to work with. @Rex: Cache misses I agree about, but HashTables have the bounds implicitly limited by the hash function. The issue is also when the indexing variable is further modified (algorithms that backtrack). The limitation on bounds-check elimination is more stringent than the gist I gave. I agree about the speed not being limited by Java, except in cases where CPU-specific features are used (SSE).
BobMcGee
@BobMcGee : why did they chose UTF-16 ? UTF-8 was not yet ratified at that time ?
Stefano Borini
@Stefano: It's the same choice Windows and .NET made as well. My understanding is that UTF-8 required more complex processing and more special cases, while UTF-16 was simpler for most common cases, and thus a bit faster. Characters requiring more than 2 bytes in UTF-16 are much rarer than characters needing more than 1 byte in UTF-8. This compromise is more friendly to international users, and less bloaty than UTF-32. Also, the BOM facilitates endian-independent coding. Note: Java originally used UCS-2 (error in my original post) and not UTF-16, but this was fixed with Java 1.5.
BobMcGee
I'm pretty sure the HotSpot JVM can't inline _most_ calls: the only safe calls to inline are the private method calls and the final method calls. You can't inline virtual methods by definition, and a very large number of methods are indeed virtual.
zneak
A: 

People normally trot out the "it's interpreted" line. Because once upon a time, it was, and bad press gets handed down by people who dumped Java as 'too slow' and never returned to test newer versions.

Or perhaps "people are idiots" is a better answer.

John
+4  A: 

For most people's experience interacting with it - Java is slow. We've all seen that coffee cup spinning around on our browser before some applet comes up. It takes a while to spin up the JVM and download the applet binaries, and that impacts the user experience in a way that is noticed.

It doesn't help that the slow JVM spin-up and applet download time is conspicuously branded with a Java coffee cup, so people associate the wait with Java. When Flash takes a long time to load, the branding of the "loading" message is specified by the Flash developer, so people don't blame Flash technology as a whole.

All of this has nothing to do with Java's performance on a server, or in the many other ways that Java gets used outside the browser. But its what people see, and what non-Java developers remember when they think about Java.

Spike Williams
+5  A: 

Stefano:

I have been with Java since the beginning, so from my point of view the fame of being slow was created by non-responsive and slow GUI frontends (AWT, and then Swing) and in Applets probably because of the additional slow startup times of the VM's.

Java has stipulated and promoted a lot of research in the VM area, and there have been quite some improvements, including the garbage collection (you can tune a lot of things actually; however, often I see systems where only defaults are used) and hotspot optimization (which at the beginning and probably still is more efficient on the server side).

Java at the backend and the computational level is not that slow. Colt is one of the best examples:

The latest stable Colt release breaks the 1.9 Gflop/s barrier on JDK ibm-1.4.1, RedHat 9.0, 2x [email protected] GHz.

There are many things outside mainstream Java that should be considered, like Realtime Java or special mechanisms to enhance the speed like Javolution, as well as Ahead-Of-Time compilation (like gcj). Also, there are IC's that can execute Java Bytecode directly, like for example the one that is in the current iPhones and iPods ARM Jazelle.

I think that generally today it's a political decision (like no Java support on the iPhone/iPod), and a decision against Java as a language (because many think it is too verbose).

However, there are many other languages for the Java VM nowadays (e.g. Python, Ruby, JavaScript, Groovy, Scala etc.) which may be an alternative.

Personally I continue to enjoy it as a flexible and reliable platform, with excellent tooling and library availability, that allows one to work with everything from the smallest device (e.g. JavaCard) to the largest servers.

Dieter
Ok, so another bad reputation came from the GUI toolkit. Of course I assume that, since modern JVM use native widgets, they hook into the OS libraries, right? or do they use AWT/Swing to render the same look and feel of the host platform ?
Stefano Borini
Dieter
+2  A: 

A hammer is much slower at rolling out dough than many other tools. Doesn't make the hammer "slower", nor less useful for the tasks that it is designed to do.

As a general programming language, Java is on par with many (if not most) for a wide array of programming tasks. There are specific, trivial tests for which Java will not outperform hand-coded solutions in less sophisticated languages, ones that are "closer to the metal".

But when it comes to "real world applications", Java often is the Right Tool. Now, that said, nothing will stop developers from making a slow-performing solution using ANY tool. Misuse of tool is a well known problem (just look at PHP's and VB's reputations). However, Java's (mostly) clean design and syntax does do a lot to reduce misuse.

HTH,

mG.

mobiGeek
Around here, we don't sign our posts because our names are already attached to them.
BobMcGee
+3  A: 

Java has the reputation of being slow because it was slow. The first versions of Java had either no or rather poor Just In Time compilation. This meant that the code, although bytecode, was being interpreted, so even for the simplest operations (like adding two integers) the machine had to do all sorts of compares and pointer dereferences and function calls. The JIT compiler has been ever-improving; now it's at the point where if I write C++ code carelessly and Java code carelessly, Java will sometimes outperform C++ because the JIT compiler realizes that I've got some unnecessary pointer dereferencing and will take care of it for me.

If you want to see just how big a difference JIT compilation makes, check out the interpreted vs. non-interpreted benchmarks at the Computer Languages Benchmark Game. (Pidigits uses an external library to do all the computations, so that benchmark doesn't change; the others show a 6-16x speedup!)

So, that's the main reason. There are a variety of other, lesser reasons that did not help matters: originally, Java startup time was slow (now fixed); web apps in Java take a long time to download (much less true now with widely accessible broadband, and with large things like movies being expected); the UI Swing was not (and still is not) written with performance in mind so it is much less snappy than equivalents in e.g. C++.

Rex Kerr
+4  A: 

The main culprit in the "long startup time" is dynamic linking. A Java application consists of compiled classes. Each class references other classes (for argument types, method invocations...) by name. The JVM must examine and match those names upon startup. It does so incrementally, doing only the parts that it needs at any given time, but that is still some work to do.

In a C application, that linking phase occurs at the end of the compilation. It is slow, especially for big applications, but only the developer sees it. Linking yields an executable file which the OS simply has to load in RAM "as is".

In Java, linking occurs every single time that the application is run. Hence the long startup time.

Various optimizations have been applied, including caching techniques, and computers get faster (and they get "more faster" than applications get "more bigger"), so the problem importance has much reduced lately; but the old prejudice remains.

As for performance afterwards, my own benchmarks on compact computations with array accesses (mostly hash functions and other cryptographic algorithms) usually show that optimized C code is about 3x faster than Java code; sometimes C is only 30% faster than Java, sometimes C can be 4x faster, depending on the implemented algorithm. I saw a 10x factor when the "C" code was actually assembly for big integer arithmetics, due to the 64x64->128 multiplication opcodes that the processor offers but Java cannot use because its longest integer type is the 64-bit long. This is an edge case. Under practical conditions, I/O and memory bandwidth considerations prevent C code from being really three times faster than Java.

Thomas Pornin
+1  A: 

I think some day, maybe not in the too-near future, JIT-compiled languages will outperform compiled languages in any aspect (well, maybe not startup time/memory consumption) due to the fact that JIT-compilers can make heavy use of runtime behaviour and the platform they're running on.

Helper Method
I think what you *mean* to say is that JIT-compiled (not interpreted) code will beat AoT code. Interpretation will always be slower than running compiled code. This is why JIT compilers are used. The catch: there is little difference between an ahead of time compiler and a JIT compiler in terms of output, except that a JIT compiler must compile more quickly, and can use runtime info to hint its optimizations. Platform-specific AoT compilers with platform-specific optimizations will almost always beat JIT because there is no limit how much time they spend on optimization.
BobMcGee
Thanks for the answer, never thought about the little time JIT compilers have at their disposal.
Helper Method
you mean, something like hotspot adaptive optimization ?
Stefano Borini
+7  A: 

You seem to be asking two rather different questions:

  1. Is Java really slow, and if so why?
  2. Why is Java perceived as slow, even though it's faster than many alternatives?

The first of these is more or less a "how long is a rope" kind of question. It comes down to your definition of "slow". Compared to a pure interpreter, Java is extremely fast. Compared to other languages that are (normally) compiled to some sort of bytecode, then dynamically compiled to machine code (e.g. C# or anything else on .NET) Java is roughly on a par. Compared to the languages that are normally compiled to pure machine code, and have (often large) teams of people working on nothing but improving their optimizers (e.g. C, C++, Fortran, Ada) Java does pretty well at a few things, but overall tends to be at least somewhat slower.

A lot of this is related primarily to the implementation -- basically, it comes down to the fact that a user is waiting while a dynamic/JIT compiler runs, so unless you have a program that runs for quite a while to start with, it's hard to justify having the compiler spend a lot of time on difficult optimizations. Therefore, most Java (and C#, etc.) compilers don't put a lot of effort into really difficult optimizations. In a lot of cases, it's less about what optimizations are done, than where they're applied. Many optimization problems are NP complete, so the time they take grows quickly with the size of problem being attacked. One way to keep time within reason is to only apply the optimization to something like a single function at a time. When it's only the developer waiting for the compiler, you can afford to take a lot longer, and apply that same optimization to much larger chunks of the program. Likewise, the code for some optimizations is pretty hairy (and therefore can be pretty big). Again, since the user is waiting while that code loads (and the JVM startup time is often a significant factor in the overall time), the implementation has to balance time saved in one place vs. lost in another -- and given how little code benefits from the hairy optimizations, keeping the JVM small is usually more beneficial.

A second problem is that with Java, you frequently get a more or less "one size fits all" kind of solution. Just for example, for many Java developers Swing is essentially the only windowing library available. In something like C++, there are literally dozens of windowing libraries, application frameworks, etc., each with its own set of compromises between ease of use vs. fast execution, consistent look and feel vs. native look and feel, and so on. The only real sticking point is that some (e.g. Qt) can be quite expensive (at least for commercial use).

Third a lot of code written in C++ (and C even more so) is simply older and more mature. At lot of it contains a core of routines written decades ago, when spending extra time optimizing the code was normal, expected behavior. That often has a real benefit in code that's smaller and faster. C++ (or C) gets the credit for the code being small and fast, but it's really much more a product of the developer and the constraints of the time the code was written. To an extent, this leads to a self-fulfilling prophecy -- when people care about speed, they often select C++ because it has that reputation. They put extra time and effort into optimization, and a new generation of fast C++ code is written.

To summarize, the normal implementation of Java makes maximum optimization problematic at best. Worse, where Java is visible, such things as windowing toolkits and JVM startup time often play a larger role than the execution speed of the language itself anyway. In a lot of cases, C and C++ also get credit for what's really the product of simply working harder at optimization.

As to the second question, I think it's largely a matter of human nature at work. A few zealots make rather inflated claims about Java being blindingly fast. Somebody tries it out, and finds that even a trivial program takes a few seconds to get started, and feels slow and clumsy when it does run. Few probably bother analyzing things to realize that a great deal of this is the startup time of the JVM, and the fact that when they first try things out, none of the code has been compiled yet -- some of the code is being interpreted, and some being compiled while they wait. Worse, even when it runs fast enough, the look and feel will usually seem foreign and clumsy to most users, so even if objective measurements showed fast response times, it'd still seem clumsy.

Adding those together leads to a fairly simple and natural reaction: that Java is slow, ugly and clumsy. Given the hype saying it's really fast, there's a tendency to overreact and conclude think of it as horribly slow, instead of a (more accurate) "slightly slower, and that mostly under specific circumstances." This is generally at its worst for a developer writing the first few programs in the language. Execution of a "hello world" program in most languages appears instantaneous, but in Java there's an easily perceptible pause as the JVM starts up. Even a pure interpreter that runs much more slowly on tight loops and such will still often appear faster for code like this, simply because it can get loaded and started executing a bit sooner.

Jerry Coffin
+1  A: 

Many Java desktop apps (these times: things like Eclipse) have bad GUI responsiveness, probably due to the high memory consumption and the fact that classloader can do lots of IO. It's improving but was worse few years ago.

Many (most) people like to do generalizations so they say "Java is slow" because they perceive the apps are slow when they interact with them.

Wojciech Kaczmarek
do you think the high memory consumption comes from the tool or from the java libraries ?
Stefano Borini
In the case of Eclipse - from the Eclipse infrastructure itself.Same for "heavy" GUIs in the past (JBuilder as I remember it).I have a gut feeling that it's because lots of boilerplate objects are needed to use a plugin architecture (like Eclipse) in a statically typed language. Emacs has plugins as well and its memory consumption is 10-20x less than Eclipse when doing typical coding. Emacs Lisp code is compiled to bytecode and loaded into emacs instance, then run - similar to Java classloader. I guess in Java there are tons of intermediate objects instantiated to allow some plugability.
Wojciech Kaczmarek
+5  A: 

After reading a page full of comments saying Java is not slow, I just have to answer with a differing opinion.

Slowness of a language is a lot dependent on what your expectations are for 'fast'. If you consider C# to be fast, Java surely is fast too. If your problem domain is related to databases, or semi real-time processing, Java is surely fast enough too. If you are happy to scale your application by adding more hardware, Java is likely fast for you. If you consider that a constant factor speedup in the scale of 5-10 isn't ofter worth it, you likely consider Java fast.

If you do numerical computation on large data sets, or are bound to an execution environment, where CPU resources are limited, where a constant speedup in the scale of 5-10 would be huge. Even a 0.5 speed up might mean a 500 hour reduction for the computation to complete. In these cases, Java just does not allow you to get that last yard of performance, and you'd likely consider Java to be slow.

Sami
agreed, and +1 on the whole post because you present a valid point, however, C++ for example has the different fame of being difficult to debug, and easy to blow your whole leg off, but seldom I heard of C++ being slow as much as I heard about java.
Stefano Borini
A: 

The major problem with java applications is that it is huge due to the large size of the stock runtime library. Huge programs fill a lot in memory and tend to swap, meaning they become slow.

The reason the Sun JVM is large is because it has a very good byte code interpreter which works by keeping track of a lot of things. That means much data, which means memory.

You may want to look at the jamvm virtual machine which is an reasonably fast interpreter (no native code) and very small. It even starts up fast.

Thorbjørn Ravn Andersen
+4  A: 

Java is definitely slow especially for quantitative work.

I use a combination of R, Python and C/C++ with optimised multithreaded ATLAS libraries. In each of these languages I can matrix multiply a 3000 by 3000 matrix of doubles with itself in around 4 seconds. Using Colt and Parallel Colt in Java, the same operation take 185 seconds! Astonishing despite these java libraries being parallel in nature.

So all in all pure java is unsuitable for quantitative work. Jblas seems to be the best lin algebra library for java as it uses ATLAS.

My machine is an HP core2duo with 3GB of RAM. I use 64-bit Ubuntu 10.04.

Hamaad Shah
+1 for the example of when Java is slower
Bruno Rothgiesser
Following on from my aforementioned comment, I performed the same matrix multiplication operation using JAMA and it took around 50 seconds. Still too slow compared to other languages.
Hamaad Shah