Programmers agonize over whether to allocate on the stack or on the heap.
Some people think garbage collection will never be as efficient as direct memory management, and others feel it is easier to clean up a mess in one big batch than to pick up individual pieces of dust throughout the day. This article pokes some holes in the oft-repeated performance myth of slow allocation in JVMs.
I know that there is some of the ‘escape analysis’ code in mustang, but does it give any performance improvement? I read on some forum that they are not taking advantage of it yet, or something like that.
Can someone comment on the status of this?
Also what kinda of apps will benefit?
Will my tomcat server be able to handle greater load because of this?
Anyone got any benchmarks with it turned on vs off?
Just looking for some hard evidence that this is actually going to benefit my apps.
Escape Analysis won’t be in Mustang, its being worked on.
So the IBM article is wrong?
Here is a quote from the article:
“Escape analysis is an optimization that has been talked about for a long time, and it is finally here — the current builds of Mustang (Java SE 6) can do escape analysis and convert heap allocation to stack allocation (or no allocation) where appropriate.”
See this forum:
http://192.18.37.44/forums/index.php?topic=10280.0
Here are the runtime flags mentioned in the article:
-XX:+DoEscapeAnalysis
-XX:+PrintEscapeAnalysis
-XX:+PrintOptoAssembly
-XX:+PrintIdeal
It says you have to have the ‘debug’ version of the VM for this to work.
Does .NET 2.0 do escape analysis?
If I’m understanding what Escape Analysis is (and I might not be), .Net really wouldn’t have a need for it as it supports user defined stack types intrinsically. Someone correct me if I’m wrong though.
If I’m understanding what Escape Analysis is (and I might not be), .Net really wouldn’t have a need for it as it supports user defined stack types intrinsically. Someone correct me if I’m wrong though.
The semantics of “value types” allow the VM to allocate instances on the stack, but usually require that the VM make copies of them when passed around. The semantics of reference types allow the VM to pass around references instead of making copies, but usually require that the VM allocate instances on a global heap.
Escape analysis is a way for the VM to safely put reference types on the stack (or to inline/embed them in the containing instance). There’s probably something analogous to allow the VM to safely pass around pointers to value types (instead of copying them).
Both the JVM and the CLR could benefit from escape analysis. Though the CLR has value, it also has the standard reference types that Java has.
Also, unlike C++, C# doesn’t allow this optimization on a per-instance basis. All instances of a type must either by pass-by-value or pass-by-reference. So you can’t really acheive the same performance as escape analysis by judiciously using value types.
BTW, I think it was a mistake for the the C# language to support value types. Though you may hear people say it “unifies the type system”, it actually does the opposite by forcing the programmer to be aware of two different object passing semantics. It was a premature performance optimization. The transparent performance gain provided by escape analysis is much cleaner.
BTW, I think it was a mistake for the the C# language to support value types. Though you may hear people say it “unifies the type system”, it actually does the opposite by forcing the programmer to be aware of two different object passing semantics. It was a premature performance optimization. The transparent performance gain provided by escape analysis is much cleaner.
C++ designers doing premature optimization? Shocking!
Seriously, though, the reason nobody in their right mind has tried to write a auto-stack allocation pass for C++ is because of pointers. It’s hard to tell what can escape when pointers and lack of type safety can create data flow completely opaque to the optimizer. This is a problem that Java (and most languages that aren’t C/C++) suffers to a much lesser extent. Moreover, lack of value types make it very difficult to support RAII, which would make the STL impossible, removing the sole redeeming feature of the language.
Rayiner,
The poster was referring to C# (i.e. C-sharp), not C++.
Anybody know offhand how jrockit is with all this stuff?
I guess there’s better places I could look if I really wanted to know :p
From the article:
“…allocation in modern JVMs is far faster than the best performing malloc implementations. ”
Maybe that’s true, but in my experience with many large inhouse applications writtten in Java, the Java apps tend to be written in such a way that they do thousands or even tens of thousands more allocations than an equivalent C++ app. Yes, I know this is mainly due to app design and developer factors, but its true also that Java itself encourages these sorts of designs. Corporate Java apps provide an unending source of post-implementation performance and capacity tuning work.
Now, if you get a good C++ developer who understands memory allocation, not only will he code efficiently, he may even override new and delete or write one of many possible custom class-specific allocators tuned for his specific domain, resulting in code significantly faster than that which uses the supplied malloc/free/new/delete.
However, there are probably a hundred bad C++ developers for every good C++ developer who could do that well, and certainly many thousands of corporate Java developers for every good C++ developer. In the larger scheme of things, Java wins.
A higher allocation rate is not in and of itself a major problem. The problem is the lifetime of those allocations, and how those allocated objects are handled. Generational GC’s were invented for functional languages. Therefore, they work best when objects are used temporarily, and copying is preferred to mutation. The problem with Java is that its an imperative language, and encourages keeping objects around in memory (incurring the overhead of copying them to the mature heap). This is not an inherent problem, and can be fixed using a programming style more aware of the nature of the GC*.
*) Note, it’s not a weakness that the programmer must be aware of the nature of the GC and write code accordingly. Indeed, C/C++ programmers do this too. The whole mentality of “allocate sparingly, keep objects around for a long time” is due to the fact that malloc()/free() are fairly slow per-call. Meanwhile, in a GC, malloc() is very fast, but keeping objects around on the heap is slow. Both mechanisms require programmer’s to adjust accordingly.
Now, if you get a good C++ developer who understands memory allocation, not only will he code efficiently, he may even override new and delete or write one of many possible custom class-specific allocators tuned for his specific domain, resulting in code significantly faster than that which uses the supplied malloc/free/new/delete.
Java doesn’t allow you to do this, but it is not difficult to allow for this in the context of a garbage collected system. MPS (Open Dylan’s garbage collector) supports multiple heaps, some of which can be garbage collected (using different algorithms tuned for the task), some of which can be uncollected (for holding C/C++ objects), and some of which can use specialized algorithms like pool allocation. Using a more flexible memory manager will get you most of the benefit of writing custom memory management code, without the time investment of writing custom memory management code.
Maybe that’s true, but in my experience with many large inhouse applications writtten in Java, the Java apps tend to be written in such a way that they do thousands or even tens of thousands more allocations than an equivalent C++ app. Yes, I know this is mainly due to app design and developer factors, but its true also that Java itself encourages these sorts of designs.
Agreed, and the reason this is important is because many of those extra allocations can now be optimized away by escape analysis. So I think this could be a big deal.
If I’m understanding what Escape Analysis is (and I might not be), .Net really wouldn’t have a need for it as it supports user defined stack types intrinsically. Someone correct me if I’m wrong though.
.NET doesn’t NEED it, but it would still be a useful optimization because many developers don’t think about optimizing in that way. You’re correct, though, that it allows this type of optimization by hand. There are cases where you may not do this manually (for good reason) but the compiler could detect there’s no reason not to do it with the current code. But I’m doubful that would really affect the performance of any real-world app.
The speed of the allocation / deallocation of memory is fine, the question is why is the average java app consume a lot more memory then a native app? I reguarly use 5 java apps (jedit, eclipse, jBuilder, Azureus, limewire), and they all tend to consume a lot more ram.
Is this because of having to store a lot more data for each object to allow for things such a reflection?
Is this due to the garbage collector infrequently running?
Is this because the object oriented approch of java encourages you to use objects where other languages would have you using structs / variables / whatever?
“The speed of the allocation / deallocation of memory is fine, the question is why is the average java app consume a lot more memory then a native app?”
Because of the virtual machine that makes sure the code you are running is safe, etc.
But also, this is not always true. For example, Firefox routinely uses 50 to 70 Mb of RAM on my system. Most of my Java applications use less.
Firefox uses that much memory because it has to store uncompressed image data (for immediate display) and maintain an in-memory cache (which will grow as you browse more).
It’s mainly the JVM. Fortunately Sun (with a little prodding from Apple) has been improving this situation since Java5 by sharing pieces of memory between instances.
I find that Java apps use a lot of memory simply because they can. There’s a parameter that you can pass to the JVM to limit how much memory it uses.
The application will run slower because it’ll hit the memory limit and run garbage collection more often, but it isn’t really bad.
The big problem with it is when an application needs a lot of memory for some operation but doesn’t need it all the time. Then, the program will crash if the JVM memory is too limited, but it’ll also leave all that memory used when it isn’t actually needed.
Which leads to another Java problem: these applications with lots of allocated RAM that is never touched get swapped out to disk, then when the GC does run, it has to swap all these pages back off disk to check them, even though nothing is actually using them.
“Then, the program will crash if the JVM memory is too limited, but it’ll also leave all that memory used when it isn’t actually needed.”
It is possible to force the garbage collector to run programatically with System.gc() if you want to programatically free up resources at some point.
It only suggests the VM to collect, nothing more..
We’ve seen this happen with our simulations on cellular networks where we created a lot of objects. We found that one of the limiting factors was the heap-size, where increasing it resulted in performance improvements.
For us, setting this number to about 1Gb on a machine with 2Gb RAM led to less aggressive garbage-collection, leaving more resources for the simulation. However, it did not use all that memory in every run; instead, things went very smoothly until we pushed the simulation to a very high number of nodes, at which point, it complained about running out of heap-space, and then crashed.
The speed of the allocation / deallocation of memory is fine, the question is why is the average java app consume a lot more memory then a native app? I reguarly use 5 java apps (jedit, eclipse, jBuilder, Azureus, limewire), and they all tend to consume a lot more ram.
JEdit and JBuilder have a much higher feature set then comparable products. You can’t compare an aircraft carrier to a row boat. The aircraft carrier is FAR MORE CAPABLE and therefore BIGGER.
These java people can keep saying all this crap about how Java isn’t slower at this or at that, but when you boil it all the way down…..
I have yet to find a Java application that doesn’t run like crap, dog slow, etc. When you use a Java app, you know it, because they just suck so bad it’s obvious.
It’s either that Java is horrible, or Java has attracted the worst programmers on the planet. I don’t care which, if Java is inherently bad or if Java programmers are inherently bad, it still results in lousy programs.
– Kelson
Concur. While Gosling is orders of magnitude smarter than me, when I saw JBoss take longer to boot than the Lose2000 OS on which it ran (the app in question was rather minimal), something ~3 minutes, IIRC, I thought: wow, no need to shop for a turkey this Thanksgiving…
In defense of Java and JBoss, the application likely had some issues, unless on thinks that a direct mapping from an object hierarchy to a set of database tables is a Good Thing…
“Concur. While Gosling is orders of magnitude smarter than me, when I saw JBoss take longer to boot than the Lose2000 OS on which it ran (the app in question was rather minimal), something ~3 minutes, IIRC, I thought: wow, no need to shop for a turkey this Thanksgiving…”
Speed of startup on a Web application server is of little importance. Performance when it is running is what matters. And when it comes to performance of Web applications written in Java, typical algorithms benchmark 10 to 15 times faster in Java than in Perl. (Java compiles mathematical algorithms that are commonly used down to native code with Hotspot). So Java would seem to be a much better option for a complex Web app than Perl for example. And for obvious reasons, C / C++ are usually not good options for writing Web applications.
JBoss is not designed to start fast. It is designed to run fast once it is up and running. Seriously, how often do you restart an application server, once a year?. It doesn’t matter much if it takes 3 seconds or 3 minutes to start.
“I have yet to find a Java application that doesn’t run like crap, dog slow, etc. When you use a Java app, you know it, because they just suck so bad it’s obvious.”
ThinkFree Office blows OpenOffice away when it comes to performance. It starts up many times faster, and is significantly faster when using it as well.
And guess what? ThinkFree is written entirely in Java.
And Microsoft Office is better than ThinkFree…
– Kelson
So we have three data points:
OpenOffice is written in C/C++ and is slow.
ThinkFree Office is written in Java and is fast.
Microsoft Office is written in C/C++ and is fast.
A statistician would say: you don’t have enough data to make a valid judgement.
An engineer would say: the algorithms of the software likely matter less than the language.
A programmer would say: C/C++ must be better!
The statistician is, of course, the one whose right, but the engineer’s conclusion is useful, while the programmer’s conclusion is completely in left-field…
OpenOffice is written in C/C++ and is slow.
I don’t get it.
Sun Microsystems makes Java and says “Everybody use Java”.
Sun Microsystems OpenOffice and says “Everybody use OpenOffice.”
But Sun Microsystems doesn’t use Java to implement OpenOffice. Is this an admission by Sun that Java is too slow even for Sun’s own product line? That Java has problems in a real application that Sun doesn’t want to deal with?
If the chef won’t eat his own food, who cares what the restaurant critics say?
If Sun doesn’t believe in its own hype, why should you?
“But Sun Microsystems doesn’t use Java to implement OpenOffice. Is this an admission by Sun that Java is too slow even for Sun’s own product line?”
Not at all. OpenOffice is the open source version of StarOffice. And StarOffice was both written before Java was invented, and was not even written by Sun. Sun bought StarOffice from a German company.
And once again, I would point out that there are at least two office suites written in Java that I know of. One is ThinkFree. And ThinkFree makes OpenOffice look dog slow.
Parts of OpenOffice.org are written in Java. All of OpenOffice.org isn’t written in Java because the codebase was an acquisition and not a from-scratch development. What Sun is saying is, “We’re not going to reimplement the entire codebase from the ground up in Java because it costs a lot of money and takes a lot of time.” The acquisition would be worthless if they were going to spend the money necessary to write a competitor for Office from scratch, wouldn’t it? They face a similar problem with GNOME/JDS. Reimplement the entire desktop in Java (Hey, why stop there? Why not waste even more money on Java * projects! Sun didn’t waste enough on that before!) to “eat their dogfood,” or have useful low-cost product when they wanted it.
While you’re trying to be cute, I don’t think the engineer’s position would differ much from the statistician’s unless he suffered from some brain-deteriorating condition. Then again, I’m not sure what sort of engineer you mean.
I suppose it depends on the type of engineer, but most would not think to do a Z test before coming to a conclusion on a subject. Engineering deals with problems complex enough that intuition often plays a bigger part than mathematical precision.
“And Microsoft Office is better than ThinkFree…”
ThinkFree is almost as fast as Microsoft Office. And it costs $45 instead of $300 for Office 2003 Standard.
But that’s not the point. The point is that it is an example where a similar application written in C++ performs far worse than one written in Java. So your argument is void.
…Java has attracted the worst programmers on the planet…
Oh yeah! You don’t know how that’s badly true in the business!
Especially when it comes to J2EE you’ll find some of the weirdest “specialists” in the programming field.
For being a relatively simple language, it has also repelled the same dittoheads who think “java sucks cuz cool guy who thinks he’s cool, thinks so”. Believe it or not, most of this java woes are due to people participating in groupthink, dating back to 1995 when java was slow…but have yet to clear up their minds.
The real performance myth is the one that says programmers care about language performance. They don’t. They say they do, but either consciously or unconsciously, they are lying.
Making a high-level language fast is challenging. It took the Lisp/Smalltalk folks decades to build good compiler technology for these languages. The best Lisp implementations have hundreds of man years of effort in implementing optimizations to make the systems fast. They did this because they listened to the mainstream programmers who said: “we won’t use it unless it’s fast”. In the context of breaking into the mainstream, this effort was largely wasted.
Java took a different approach. Instead of spending hundreds of man years making the language fast, they spent their time making it useful. They built massive libraries and frameworks that gave programmers pre-packaged solutions. Programmers said they cared about Java’s performance, but they really didn’t. They adopted it en-masse anyway. The proof is in the pudding: there are many more Java programmers now than C/C++ programmers, and the migration started long before Java’s performance became acceptable. And this makes sense: it is cheaper, after all, to buy twice the hardware to run a server app than to pay for twice the developer time to build the app in the first place.
Bringing us back to the article: this difference in approach is why you’re just now seeing Java/C# implementing performance optimizations that are old hat in the Lisp/Smalltalk world. I mean, consider escape analysis. Compilers that do escape analysis for Lisp are a dime a dozen. It’s old technology. And it’s not like Sun is unaware of this technology. It’s not like Guy Steele forgot everything that had been learned making optimizing compilers for Scheme. It’s not like Sun forgot all the advances they had made doing type inferencing in Self. No. Somebody obviously made a conscious decision to go for practicality before performance. Ultimately, this proved to be the right decision. Regardless of what people say, they will use something that is slow but useful. They will not use something that is fast but less useful. There is a reason why GNOME has many users, and BeOS has almost none. There is a reason people started adopting Java even when it was an order of magnitude slower than C++. This is the proof of the real Performance Myth.
An interesting idea Rayiner but I can’t agree. You say Java has been adopted en-masse, but this isn’t exactly true in many areas where performance is critical.
How many desktop apps are written in Java? Nearly none.
One reason is that large desktop Java apps are slow, just try out IntelliJ IDEA some time. I’ve never seen a program that has a little garbage collect button on it before, but when you click it you figure out why it’s there – it can take 5-10 seconds on my (admittedly old) computer to run a full GC in this app.
Another reason is that the JVM is a huge download. Bandwidth performance is just as critical as malloc() performance.
I would never write a consumer desktop app in Java/Swing for these reasons. I’d like to because Java is a much nicer and more robust platform than C++ and associated libraries is, but the performance issues would stop me.
I’d like to use J2ME as another example of where Java isn’t really suitable: it’s alright to talk about advanced optimisation techniques that aren’t yet implemented in any JVM but I’ve recently been suffering due to the lack of advanced GC in mobile phones (they aren’t even compacting usually). A more realistic design of the Java language – for instance one that included something like the C# stackalloc keyword – would have helped tremendously here.
Unfortunately Sun have consistently refused to make Java less automatic and more pragmatic, and they’ve suffered as a result. I daresay the large number of Java programmers in the world today is almost entirely a result of it being the de-facto teaching standard in higher education rather than it being inherantly superior.
You say Java has been adopted en-masse, but this isn’t exactly true in many areas where performance is critical.
I didn’t say that nobody cares about performance, I said most don’t care about performance. There are still problem domains (scientific computing, for example), where people use FORTRAN for performance. However, if you listened to all the performance belly-aching back when Java came out, you’d think that Java was unusable for everything. Yet, all but the most performance-intensive tasks use it these days. I was blown away to see a professional finite elements (a structural analysis technique) package written in Java. These things require a non-trivial number of computations. Apparently, whoever developed it considered Java’s performance adequate. Heck, lots of people are even writing computational fluid dynamics code in Java these days!
How many desktop apps are written in Java? Nearly none.
Desktop apps in aren’t particularly performance intensive. Generally, you won’t notice if the language used is 10x slower, as long as the algorithms don’t do anything braindead. I have a feeling that much of Java’s lack of success on the desktop has to do with Swing, both its braindead algorithms and its completely alien widget set.
Another reason is that the JVM is a huge download. Bandwidth performance is just as critical as malloc() performance.
That’s kind of a silly argument though. It’s not like the C runtime isn’t a multimegabyte download. You just never see it because it comes with the compiler.
I daresay the large number of Java programmers in the world today is almost entirely a result of it being the de-facto teaching standard in higher education rather than it being inherantly superior.
Heh. If that were true, we’d all be using Scheme right now…
I didn’t say that nobody cares about performance, I said most don’t care about performance.
Are you talking about programmers or end-users (or both)? As an end-user, performance does matter to me. The perception that Java is slow remains because in the real world – not some theoretical world of ideal conditions – there remains an enormous number of slow, ugly Java apps (I have to use a whole slew of them everyday at work). It may well be poor programming rather than the language itself, but for many users, the actual “user experience” is what counts – and in Java’s case it remains thoroughly unimpressive.
Are you talking about programmers or end-users (or both)?
Both. Neither cares. The fact that Java is perceived as slow doesn’t matter. That hasn’t stopped people from using it all over the place. The same is true of lots of programs. Windows is perceived as slow (or at least, was perceived as such for the longest time). That didn’t stop anybody from using it. MacOS X *was* slow (and painfully so) for a long time. Users flocked to it. GNOME is still slow. That hasn’t stopped Novell or RedHat from making very good money selling GNOME desktops.
Aside from a few niche cases (games, mainly), nobody cares about performance. They’ll bitch about it incessently, but they won’t stop using an otherwise useful product because of it. Therefore, it makes all the sense in the world to work first on making a product as useful as possible (as Sun did with Java), and working on performance when you get around to it, than to release a well-optimized product and work on features later. If you do the former, you’ll have users to see the future, faster releases. If you do the latter, you’ll never get to make a feature-filled release, because you won’t have any users for the first one.
What programmers care about, depends largely on what they’re developing and what skills they possess. The complaints of lisp performance (either compute or gc latency) of old don’t necessarily translate to the performance demands of today. The performance benefits realized by better compilers (SBCL, CMUCL) can be outweighed by the absence of competitive free compilers for other platforms (namely Windows). The performance benefits of lower-level languages (C, C++) can be outweighed by complexity of the language (the number of people that genuinely understand C++ is not a significant percentage of the people that use it), making people look for a middle ground (Java).
Despite years of research in runtime optimization for Smalltalk and Self (the benefits of which are seen in the JVM), they’re still not on par with the JVM in performance. If you think that Smalltalk lacked a collection of useful objects for performing tasks now relegated to Java, because of Java’s standard library is so feature-rich (Hah), then I assure you that you’re mistaken. It certainly was not more practical for Sun to reinvent Smalltalk in the image of C++ and design and create new class libraries than it would have been to provide a comparable Smalltalk environment. I mean really, most libraries were written in C and C++ in those days, so Java certainly didn’t have “more practical” over them, either. Java wasn’t originally developed at all to be in the position it’s in now.
Java is used on the backend because of its performance, not despite it. Perl has an enormous resource in CPAN, and a vastly superior means of creating bindings to native libraries than JNI, but it’s lost ground to Java since the mid ’90s. It certainly wasn’t more practical to write backend code in Java in the mid ’90s. Language complexity, similarity to C languages, more rigid development, performance, threading that mostly worked, groupthink, etc made Java the competitor in the backend that it became.
And it didn’t happen en masse. Java tried to be a desktop platform and failed. It failed because AWT was broken. It failed because later Swing was broken. It failed because the computational optimization that the JVMs’ JIT compilation provides comes at the cost of memory, and having a desktop full of heap-eating Java programs that take seconds to start and that are ugly and don’t integrate with other Windows programs doesn’t appeal to end-users. It picked up momentum on the backend because it scaled better and was less fluid than Perl, looked more like C, and wasn’t as hard to use as C++.
Millions and millions of dollars were wasted in the dot com era rewriting everything in Java, because it was safer than C, provided better performance than Perl, and because everyone else was doing it too.
Lots of people don’t need to care about performance, and so they don’t. PHP, Perl, Python, Visual BASIC, et al amount for a lot of code between them. Where performance matters here, people throw money at hardware rather than developers. They may also desire performance tradeoffs that Java doesn’t provide well (startup latency, predictable memory consumption). And in other cases they do care about performance (even when it’s unnecessary for them to do so), and they write in C or C++. And make no mistake, while Java is definitely popular, the majority of code people find on their desktop is still churned out in C and C++. People eschew Java and C# programs on the desktop whenever possible even now. If Microsoft succeeds in supplanting its own platform with .NET, it will be by sheer force of will rather than eager adoption. Whereas Windows backend developers that hated Java because it wasn’t created by Microsoft that suddenly find themselves singing the praise of managed runtimes have jumped on it to reimplement all of the stuff that was reimplemented in Java in the first place with glee.
Sigh. So much of the software industry is devoted to wasting money.
…with the poster who said Java is all about ease of programming. Sure it is not perfect but then again neither is every other programming language out there. Java should be used with discretion…it is great in certain situations but not in all. Java is not about how fast the program starts up but rather how fast the program runs once the program has booted up.
There is no denying that Java is a great technology so for those naysayers…shut up. But there is no denying that there are loads of languages that are great for writing apps which we are used to using as an end user like chat clients, word processing suites, etc etc that run really really fast when compared to their written-in-Java counterparts.
All I am trying to say is Java is not perfect. They are trying and the technologies it has brought about are quite interesting to say the least.
Most c++ objects are either allocated on the stack or copy constructed into a container. In other words, near zero calls to malloc/free. Shhhhhhheeeeeezzzzz when will the Java guys realise that c++ is not c, and that the programming style is completly different.
You’re half correct. In modern C++ style, most C++ objects are copy-constructed into a container. Now, ask yourself: where does the memory in the container come from? If you guessed “from malloc()/free()”, you get a cookie!
Well sure, but for an addition cookie, ask yourself this, how many alloc/free’s does a vector actually do after inserting – say 100 items and then removing them. Implementation defined of course – but if you guessed less than 8 you are most likely correct… And of course usage after that is probably free.
Now, how many allocs are needed to do the same thing in java?
Actually, most C++ implementation start with 16 place holders in a vector, and double this capacity everytime it’s needed. So to insert 100 elements, it would allocate 16, 32, 64, and then 128 place holders (thus 4 malloc).
Plus keep in mind that the allocators of STL classes are not just simple calls to malloc, but are a bit more optimized than that (hey?! what?! Sun guys are not the only one bringing in optimizations?).
And if you’re really picky, or working with a lot of constraints (e.g. embedded systems), you can use your own STL allocator (all STL classes take the allocator type as a template argument).
After that, if you care about speed and know about how many objects will be allocated in the vector (roughly or exactly), you can use the reserve() member function to lower the number of memory allocation (to 1 in the best case).
1-to-4 “C++ malloc” at (worst case) 100 cycles each vs 100 “java malloc” at 10 cycles each… hmmm
The question is, what is the relative overhead? In the C++ case, extended a vector in the average case has no alloc and one copy. In the Java case, it has one alloc and no copy (if the same optimization is used). For a generational GC, an alloc is on the order of a couple of instructions. That makes extending that vector very possibly faster than copy-constructing into a vector.
Of course, in both cases, the performance is likely dominated by whether the call to the constructor can be elided.
“Most c++ objects are either allocated on the stack or copy constructed into a container. In other words, near zero calls to malloc/free.”
Um… What do you think happens when you use the “new” operator in C++? Ahd where do you think that container memory comes from?
Ok the cookie winner who said Java was made to be usefull and not overly performant was on the ball (but it does perform amazingly well).
Have a look at Javac (java compiler (makes byte code)), it has ZERO optimisations not even dead code removal! instead all this is left for the HotSpot stuff to work out.
IMHO the compiler (hotspot or javac) should if possible work out when it`s safe to use pointers or value types where and when it makes sense to do so but unfortunately only the HotSpot is relied upon to do everything with no thought to the simple AHOT optimisations that could be included into Javac.
No i`m not preaching for a full optimising AHOT compiler for java or a pre parser, just the simple plain drop dead obvious AHOT stuff that would make life alot easier.
But atleast with the above they are starting to pull their heads out of the sand.
This message was brought to you by:
B (for beer)
A (for aniseed)
D (for do you think the policaman saw me with no pants on?)
“Have a look at Javac (java compiler (makes byte code)), it has ZERO optimisations not even dead code removal!”
Wrong. javac does remove dead code. In fact, you can make a block of code conditional on a constant, and javac is smart enough to know that the code will never be called if the constant condition is not met, and will remove that code. This is in the cases where javac will even let you include “dead” code. Much of the time, javac will flag it as an error. (Example, you cannot include assignments or executable statements after an unconditional return.)
Also, javac can, when possible, inline methods that are declared as final.
“instead all this is left for the HotSpot stuff to work out.”
The only problem with HotSpot right now is that optimizations are not persistant across program executions. Although the word is that they will be in a near future release of the JVM. Optimization can usually be done better at runtime. In fact the JVM can make optimizations that C and C++ compilers cannot even dream of based on the fact that it can profile code at runtime and optimize thins. This is why some algorithms have actually been shown to perform better in Java than in C++. The JVM profiles the code at runtime, figures out what it is actually doing, and optimizes it based on that.
“javac is smart enough to know that the code will never be called if the constant condition is not met, and will remove that code.”
Ok I was patially wrong, i`ve been playing with this and on DECLARED constants it does work but on say a boolean that is NOT declared as final but is in local scope and is assigned false and does not again change it does not! (this is an easy optimization).
The current javac uses “final” almost as a “optimize me” flag which is not semantically correct, having to declare a local variable as final even if it`s value does not change is nuts, this is what a compiler is for.
“javac will flag it as an error. (Example, you cannot include assignments or executable statements after an unconditional return.)”
Erm that is syntax not optimization
“The only problem with HotSpot right now is that optimizations are not persistant across program executions.”
I`ve alway thought the HotSpot compiler/runtime was a great place to do many things, it`s more like running GCC in profile mode then a traditional static AHOT compiler and we really need a way to keep the information created from a execution to be persistant, aslong as the hotspot is always free to rewrite any piece of this information at any point.
Imagine a program that gets better with age (well up to a point) and if this profile information could be exported it may be usefull in analyzing the source code later on.
My only concern is that we may be missing the low hanging fruit of simple static analysis.
“Ok I was patially wrong, i`ve been playing with this and on DECLARED constants it does work but on say a boolean that is NOT declared as final but is in local scope and is assigned false and does not again change it does not!”
There is a good reason for this though. If it did do as you suggest it should, you would potentially break any classes that relied on the class in question if you ever change that value in the future. Thus, every class tha relied on that class would have to be recompiled. Things like this are part of the reason that C++ suffers from what is sometimes called the “fragile base class” problem. This is a problem that Java does not have.
“you would potentially break any classes that relied on the class in question if you ever change that value in the future”
If the variable and it`s effects can not be accessed outside of it`s scope then please tell me how another class could potentially depend on it?
It sounds to me as though your thinking of tightly coupled classes and global/public scoped variables which if your using that to a large degree then you need to be beaten with a big stick!, if a method does something then the implementation does not matter only the result, think of why get/set methods are usefull.
// scope
if (false) {// do stuff}
// end scope
and
// scope
boolean value = false;
if (value) { // do stuff}
// end scope
// scope
final boolean value = false;
if (value) { // do stuff}
// end scope
are the same thing, as long as it`s effects do not escape the scope, this is a trivial example but currently the first and third are optimized away and the second is not.
I`m not saying that we need a fully optimizing AHOT compiler to do every single static analysis trick in the book, just drop dead simple ones like the above (even if it`s for very limited scope it`s still a win).
And there is nothing stopping java having the “fragile base class” problem.
Here`s an example of an article about it for the Java language
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html
“If the variable and it`s effects can not be accessed outside of it`s scope then please tell me how another class could potentially depend on it?”
I wasn’t clear. What I meant is that you potentially break any derived classes. and the final keyword is gradually going out of favor in Java in favor of runtime optimizations that can do exactly what you suggest.
“And there is nothing stopping java having the “fragile base class” problem.”
It’s possible of cource, to write a fragile base class in Java. But you have to work at it. In C++ on the other hand, it is the opposite. It is difficult to write a base class that is not fragile.
“this is a trivial example but currently the first and third are optimized away and the second is not.”
This is also bad style. If a value is going to constant, it should be declared as such, if for no other reason than that it makes the code self-documenting.
So really, I don’t think that the compiler should optimize stuff like this away. And I would not rely on any C / C++ compilers to optimize this away either. In C++ it would have to be declared as const to be optimized away. In C, it would have to be placed inside a pre-processor conditional. Some compilers might do what you suggest. But others won’t. So this is bad style, and non-portable code.
It’s completely portable. It doesn’t do anything, so the compiler removes it. The functional behavior is identical; that’s the point of optimization.
If you can read x86 assembly then try an assortment of optimizing C compilers with aggressive optimizations. Watch as the code doesn’t appear at all in the assembly output by the compiler. Oooh. Ahhh. No const necessary. No preprocessor (like it even makes sense to attempt to use the preprocessor to conditionally exclude code from the output stream based upon the value of a local variable).
Both the standard Java compiler and the majority of compilers for the CLR opt to defer most optimization to the virtual machine. This isn’t especially useful on targets that use an interpreter, but I don’t really care at all enough about this to bother having that discussion.
Your defense seems sort of weak. The compiler being primitive isn’t a feature, it just isn’t necessarily a detriment. Well, except that the more simple a compiler is the easier it is to ensure that it’s correct. That’s not especially strong of a defense either.
“It’s completely portable. It doesn’t do anything, so the compiler removes it.”
You are missing the point though. The point is that ANSI / ISO C does not specify that this is what compilers will do. So relying on this as an optimization is bad style. Depending on what compiler it is compiled on, it may or may not be removed. That’s what I say when I mean non-portable. In fact, this kind of code is worse than non-portable. It is implementation dependant. Sure it will work on any compiler. But it may not be optimized away on some compilers.
“It is implementation dependant. Sure it will work on any compiler. But it may not be optimized away on some compilers.”
Thats the point, currently it doesn`t do it although if it did it would make the code size smaller and give the HotSpotVM less code to run through, there is no downside.
ANSI/ISO C has nothing to do with Java byte code, and I`m certainly not saying the example I used was for some sort of IFDEF or some such but you can clearly see that this is the_right_thing_to_do TM for normal code.
And the difference between it being there and not being there semantically is ZERO, either way the code is not needed but in the unoptimized case we pay with bloated code and a comparison that is not needed.
As for self documenting code you should never care what the binary result is, only that the code is clear enough to understand and final does not always fit.
There was something simmilar in idea to this in the JNode OS code and explains why it is such a silly thing, they basically used a final variable inside a for-loop and used the result outside the for-loop, this was to make it optimize away.
Reading it looked more like “make one object and iterate a few times then use it outside” NOT “on each iteration make a new object then use one of them outside”, now thats confusing!
“ANSI/ISO C has nothing to do with Java byte code, and I`m certainly not saying the example I used was for some sort of IFDEF or some such but you can clearly see that this is the_right_thing_to_do TM for normal code.”
I know it doesn’t. But it sounded like you were implying that a C / C++ compiler would optimize that away, where as a Java compiler will not. What I was saying is that may or may not be true in a C or C++ compiler. It is implementation dependant.
“As for self documenting code you should never care what the binary result is, only that the code is clear enough to understand and final does not always fit.”
A variable that is intended to be constant should be declared as such. How can you say final does not always fit? final makes it 100% clear that the variable’s value cannot (and should not) change.
“final makes it 100% clear that the variable’s value cannot (and should not) change.”
Yes and a programer is forced to use it for any sort of optimisation, this is silly when it is bleedingly obvious that some code can be converted into a constant or optimized away without the forcing the user to write a keyword.
> It is implementation dependant.
No kidding. The point is that the Java compiler is primitive, and that’s precisely what he was criticizing.
The entire point of an optimizing compiler is to generate the most efficient code the compiler can determine is correct.
You’re not relying on anything, because code steam A and code stream B are functionally identical. One is more efficient. Your attitude is “worse code is better, because that’s what javac generates.”
“No kidding. The point is that the Java compiler is primitive, and that’s precisely what he was criticizing.”
How many times do I have to say I was not referring to Java. I was refering to the fact that it may not exist in Java, but it doesn’t really matter if it exists in C or C++ either since it is implementation dependant in C and C++. You are relying on an optimization that may or may not exist depending on what compiler your program is built with. And that is bad style when there are other ways to do it that gurarantee it will be optimized.
And no, the Java compiler is not primitive. It is quite a bit more advanced than gcc. And many optimizations are not done at compile time because they can be done better at runtime. That’s the beauty of the virtual machine.
> How many times do I have to say I was not referring to
> Java.
How many times do I have to tell you that he lodged his criticism at the output of javac? What you’re talking about is, well, stupid because it’s obvious. Any optimizing C compiler will perform the optimization he pointed out with sufficiently-aggressive optimizations enabled. No, no compiler has to perform the optimization. Your insight is truly amazing. No compiler has to perform the optimization with annotations, either. Would you like a Captain Obvious Award with the Refuses to See the Point Because He’s a Java Zealot Special Mention?
And yes, javac is primitive. And large amounts of optimization is only practical using static analysis, because the computational overhead at runtime is prohibitive. Much as many specializations are more practical at runtime, because profiling information is available.
Go back to using the preprocessor to conditionally exclude C code based upon the usage pattern of local variables.
Do you honestly not understand the concept of an optimizing compiler?
“Do you honestly not understand the concept of an optimizing compiler?”
Yes, I fully understand the concept. It seems that you don’t however. The point is when you do something like this, you are relying on a feature that may or may not be present in all compilers your code might be compiled with. That is bad style when there are other ways to do it that guarantee it will be optimized away. You are relying on something that is implementation dependant. In otherwords, it does not do what you intend it to do on all compilers.
But also, as I said before, this is bad style if for no other reason than it violates the principle of least privilege, which is a principle of good software engineering practice. If it can be determined at compile time that the value of a variable is not going to change, than it should be declared as such.
You clearly don’t understand the concept of an optimizing compiler. You are not relying on anything; the code is functionally identical. One code stream is more efficient than the other. You point at the inferior one and say, “that’s better.” That’s stupid. You don’t even realize how stupid your position is, despite that you “rely” on the JVM JIT compiler to transform that mediocre codestream into something useful.
If you understood, well, frankly any sort of compiler you would realize that _all_ of this is compiler dependent. javac doesn’t have to output an inferior code stream, it just does so because it’s a fairly primitive compiler.
> despite that you “rely” on the JVM JIT compiler to
> transform that mediocre codestream into something
> useful.
And in doing so you waste memory when you do have the JIT compiler (if it even bothers to optimize this at all), and you impede performance when you don’t (embedded systems, cell phones, whatever). Not to mention you apparently rely on the compiler to exploit annotations provided to improve correctness to perform optimization, despite that being identical behavior.
But nevermind, inferior code streams are superior because optimizations are implementation-dependent. Time to rip out HotSpot, because relying on it to perform the necessary optimization to make you mediocre code streams useful is a violation of good software engineering principles. Auto-vectorization? Pfft, you can’t rely on that; explicitly injecting SIMD instructions is the only way to go!
Excuse me, I’ve had enough amusement as your expense.
“Excuse me, I’ve had enough amusement as your expense.”
Excuse me, I am through arguing with a troll who is so lame he can’t even think his post through before writing it and thus has to respond four seperate times.
By the way, those who resort to accusing others of having no understanding, almost always only do so to make themselves feel better about that they don’t have any understanding of their own. Given that your attitude suggests you are probably one of those 15 year olds who wants to think they are a cool hacker, I suspect the above statement applies to you perfectly.
I haven’t just accused you of having no understanding, but demonstrated beyond all question that you don’t even have an undergraduate-level understanding of what compilers do. You can lodge all of the ad hominem against me you want, but I think you’ll notice that you’re the one that constantly posts incorrect things out of ignorance and then back-pedals away from them. If that’s the person you want to be, then by all means continue because it’s really quite funny.
Ok. I will bite this one last time. But then I am done wasting my time with you.
“You are not relying on anything; the code is functionally identical. One code stream is more efficient than the other.”
You are relying on an optimization that may or may not exist. And NO, the code is NOT funtionally identical. One performs the conditional test each time. The other does not because it has been optimized away. That is not funtionally identical code.
“You point at the inferior one and say, “that’s better.””
No, that is not what I am saying. What I am saying is two things:
1: You should not be relying on this as an optimization in C or C++ either, since it may or may not exist. Remind me again why you have such an aversion to doing it right and declaring it as a const if it is not going to change?
2: If it is not going to change, it should be declared as const or final. This is simply good style, and follows the principle of least privilege (but it sounds like you were abscent for software engineering 101). If the variable should not change, you should not leave open the possibility that a programmer can accidently change it. Readability, and error prevention dictates it should be declared const or final, and you should not be relying on the compiler to optimize it as such if you don’t declare it as such.
Basically, my argument is that it is a non-issue because you should not be writing code like this anyway. It violates good principles of software engineering.
> You are relying on an optimization that may or may
> not exist. And NO, the code is NOT funtionally
> identical. One performs the conditional test each
> time. The other does not because it has been
> optimized away. That is not funtionally identical
> code.
Those are exactly functionally-identical code streams. They perform the same end behavior, with the only difference being that one code stream is more efficient than the other. This is the nature of _all_ optimization. A compiler that performs loop unrolling provides code that is functionally identical to one that does not.
> 1: You should not be relying on this as an
> optimization in C or C++ either, since it may or may
> not exist. Remind me again why you have such an
> aversion to doing it right and declaring it as a
> const if it is not going to change?
Providing such annotations does not guarantee optimization. If you don’t understand that, please try banging it into your head until you do. The annotations are superfluous from the compiler’s standpoint because it can _prove_ that the code in question is never executed.
Why don’t you unroll loops by hand? Why don’t you allocate registers for each function? Why don’t you pad datastructures? Why don’t you provide explicit instruction-level parallelism?
> 2: If it is not going to change, it should be
> declared as const or final. This is simply good
> style, and follows the principle of least privilege
> (but it sounds like you were abscent for software
> engineering 101).
Producing an inferior code stream is not superior. What you think should or should not be annotated doesn’t matter at all. Such annotations guarantee absolutely no optimization. The optimization is simply easier for the less sophisticated optimizer to make because the programmer has explicitly performed its job for it while providing annotations for assisting the programmer to obtain correct code.
Frankly I don’t think you’ve even graduated from a university, because it amazes me just how little you seem to understand compilers. You constantly rely upon HotSpot to do precisely the same thing, providing what you don’t even believe to be functionally-equivalent code streams. You babble about the benefits of JIT compilation, when it violates what you believe to be “the principle of least pirvilege” by performing transformations on code streams to produce more efficient code.
> Basically, my argument is that it is a non-issue
> because you should not be writing code like this
> anyway. It violates good principles of software
> engineering.
Your argument boils down to “javac doesn’t perform an optimization and therefore the optimization is bad, and I will stick to that regardless of how clearly it demonstrates that I’ve never written or worked on an optimizing compiler in my entire life.” Amusingly, most languages don’t even have the annotation you think guarantees optimization (despite that it doesn’t).
Go to college.
“Your argument boils down to “javac doesn’t perform an optimization and therefore the optimization is bad, and I will stick to that regardless of how clearly it demonstrates that I’ve never written or worked on an optimizing compiler in my entire life.””
I HAVE written compilers. Have you?
An optimization that says “this arithmetic operation can be done faster if it is bitwise shifted” is one thing. This optimizes details that the programmer should not be bothered to worry about, and details that if the programmer did worry about, would decrease code readability.
In the case in question, however, you are basically asking the compiler to make up for lazy programming, and programming that is bad style. That is something I am not a fan of. Again, what is your aversion to doing it the right way?
int c = 5;
final int c = 5;
Are you just too lazy to type that extra word “final”?
“Such annotations guarantee absolutely no optimization. The optimization is simply easier for the less sophisticated optimizer to make because the programmer has explicitly performed its job for it while providing annotations for assisting the programmer to obtain correct code.”
Wrong. In Java, this annotation does guarantee that code wrapped inside a conditional and based on the final variable will be removed by the compiler. And it also follows good software engineering prinicples (which is something you still haven’t addressed. The fact that it is bad style from an engineering standpoint and decreases code readability, and it hardly anymore work to di it the right away. You need to type one extra word.)
If you want to write crap code that relies on compiler magic to make up for programmer laziness, be my guest. But don’t plan on working for my company. Again, it’s not like we are talking about substituting a bitwise shift for some other arithmetic operation here. In this case, we are talking about the compiler making up for excessively lazy programming.
> I HAVE written compilers. Have you?
Yes. That’s why I participated in this discussion at all, despite not caring even remotely about the output of javac. I don’t believe you, though. Your lack of understanding is too complete. Explain how to perform the necessary optimization the original poster desired.
> An optimization that says “this arithmetic operation
> can be done faster if it is bitwise shifted” is one
> thing. This optimizes details that the programmer
> should not be bothered to worry about, and details
> that if the programmer did worry about, would
> decrease code readability.
This contradicts your position that
1) That optimization doesn’t provide functionally-equivalent code streams
2) That optimization violates software engineering principles, by performing (provably-correct) transformations that result in code streams you feel should only be provided given sufficient annotation.
> In the case in question, however, you are basically
> asking the compiler to make up for lazy programming,
> and programming that is bad style. That is something
> I am not a fan of. Again, what is your aversion to
> doing it the right way?
All optimization boils down to catering to “lazy programming,” where “lazy programming” means not hoisting responsibility for efficiency needlessly to the programmer. Despite that this annotation you’re so fond of does _not_ guarantee optimization, it doesn’t matter because the programmer doesn’t _have_ to worry about providing such an annotation because the compiler can transform the code stream into a more efficient one without any assistance. There is no “aversion” to “doing it the right way,” doing it “the right way” is simply unnecessary.
> Wrong. In Java, this annotation does guarantee that
> code wrapped inside a conditional and based on the
> final variable will be removed by the compiler.
No it does not.
Nothing in sections 4.12.4, 13.4.9, 14.21, or 15.28 requires that the compiler not emit code in the presence of such annotations. javac simply happens to implement this as a means of providing conditional compilation in a language without any means of expressing conditional compilation.
> The fact that it is bad style from an engineering
> standpoint and decreases code readability
First, what you have presented is an opinion, not a fact. Second, providing annotations or not providing annotations is irrelevant. The annotation is simply unnecessary for the optimization, and the code stream provided is less efficient. Hoisting responsibility of optimization to the programmer when it is unnecessary is an inferior strategy. That’s precisely the stance that HotSpot takes, regardless of what annotations you happen to insert into your codebase.
> decreases code readability
Automatic optimization does absolutely nothing to alter code readability.
> If you want to write crap code that relies on
> compiler magic to make up for programmer laziness
That’s precisely what you’re doing when you use javac. It’s outputting ‘crap code’ and relying on ‘compiler magic’ (the JIT compiler on platforms where it’s available) to make up for programmer laziness (targetting a stack-based virtual machine, using a mediocre compiler, not explicitly optimzing everything by hand, using dynamic dispatch, …).
“2) That optimization violates software engineering principles, by performing (provably-correct) transformations that result in code streams you feel should only be provided given sufficient annotation.”
You are putting words in my mouth, and over-generalizing my position in order to support your strawman argument. I did not contradict myself.
“All optimization boils down to catering to “lazy programming,” where “lazy programming” means not hoisting responsibility for efficiency needlessly to the programmer.”
I disagree. Often optimization boils down to “readable programming”, not lazy programming.
“There is no “aversion” to “doing it the right way,” doing it “the right way” is simply unnecessary.”
And again, I am not fond of compiler tricks that encourage programmers to write sloppy code that violates good software engineering principles. There is a difference between good software engineering principles, and programmer laziness. Which is something it seems you cannot grasp.
“First, what you have presented is an opinion, not a fact.”
Now I KNOW for sure you missed out on software enginnering 101. The principle of least privilege is one of the most fundamental aspects of good software engineering. If a variable will not be modified, it should be declared as such to prevent the programmer from accidently modidying it later. Let me guess. You are probably on of those programmers who routinely passes around pointers without declaring them to be const too right? Again, it violates principles of good software engineering, and is bad style. If the pointer will not be modified in the called function, it should be declared as const so it cannot be modified. This is not advanced stuff. This is software engineering 101. The final keyword is no different.
And you ignore the entire content of my post to backtrack from your own stupid comments and engage in substanceless lying. Nice.
> If a variable will not be modified, it should be
> declared as such to prevent the programmer from
> accidently modidying it later.
I thought that was pretty funny. As I told you previously, most languages don’t even have such an annotation. In those that do, none that I can think of requires conformant implementations to provide such an optimization. Since the question is the removal of unnecessary operations from the code stream in order to maximize efficiency, the presence of the annotation is wholly irrelevant. “The less optimizing compiler is superior because I don’t like that thing that you do.” Nevermind that the optimizer won’t just optimize the trivial case provided by the original poster that you babble incoherently about in every post, but rather be able to determine that a chain of method calls result in a constant and perform the optimization (which won’t be performed by javac regardless of the annotation of the recipient).
But since you’re rambling about annotations for improving correctness, I’m going to infer that Java is inherently a language that violates “good software engineering.” First, there are no instances of constant objects, merely constant references to instances of objects. If an instance isn’t going to be mutated, then it must be annotated explicitly as a constant instance. Since Java has no such constant instances, all Java code is therefore bad. If the argument to a function is intended to be used solely as a source of valid input then it must be annotated as such, but since Java has no such annotation all Java code is therefore bad. If a function expects a parameter to be non-null then it requires annotation to prevent passing null references to the function, but since Java has no such annotation all Java code is therefore bad. If a method is intended to be overriden by a subclass, then it must have annotation stating this, but since Java doesn’t have any such annotation all Java code is therefore bad. If a function expects only a subset of the values of a given type, then the function should be annotated as such in order to prevent the passing elements outside of this set to the function, but since Java doesn’t have any such annotation all Java code is therefore bad.
I suggest that you immediately stop writing all of that “crap code” in Java. It’s funny you don’t have the intellectual honesty to acknowledge your own failings, instead repeating the same irrelevant tripe.
“And you ignore the entire content of my post to backtrack from your own stupid comments and engage in substanceless lying. Nice.”
I’m not lying at all. You would make a very good politician considering the amount of spin you put on my comments.
“Nevermind that the optimizer won’t just optimize the trivial case provided by the original poster…”
It’s irrelvant. It’s bad style. The optimization was basically:
int i = 5;
if (i < 3) {
}
“If an instance isn’t going to be mutated, then it must be annotated explicitly as a constant instance.”
Again, you are resorting to extremes to support your strawman arguments. What I am suggesting is that you should take advantage of what the language provides to promote good software engineering.
and i should be optimized away because the compiler should recognize that I is not changing. Bad style. End of story. Bad style.
“If a method is intended to be overriden by a subclass, then it must have annotation stating this, but since Java doesn’t have any such annotation all Java code is therefore bad.”
It’s called “final” again, and it works the other way around. And YES, if you do NOT want a method to be overridden in a subclass, it should be declared final. Again, this is simply good software engineering since it indicates to those subclassing the object that they should not override the method.
“I suggest that you immediately stop writing all of that “crap code” in Java. It’s funny you don’t have the intellectual honesty to acknowledge your own failings, instead repeating the same irrelevant tripe.”
No, whats funny is the extremes you are having to resort to in order to try to support your argument that good software engineering is not important, and that compilers should make up for excessively lazy programming on the part of programmers.
> I’m not lying at all.
The content of your post was substanceless lying completely unrelated to what I keep telling you. Why don’t you tell me some more about how I have an opinion about how you choose to annotate your code? As if I care.
> It’s irrelvant. It’s bad style. The optimization was
> basically:
It’s funny how I specifically tell you the implications of the optimization, but you don’t even get it.
> Again, you are resorting to extremes to support your
> strawman arguments.
That’s only extreme to you because Java doesn’t support it. It’s simply the logical progression of your asinine philosophy. Frankly it has absolutely nothing to do with my arguments (which you never fail to ignore), but rather simply serves as entertainment.
> It’s called “final” again, and it works the other way
> around. And YES, if you do NOT want a method to be
> overridden in a subclass, it should be declared
> final.
If you don’t understand the difference between explicitly stating that a method cannot be overloaded, and specifically stating the intention of overloading a method then I suggest you try being a little less retarded.
> No, whats funny is the extremes you are having to
> resort to in order to try to support your argument
> that good software engineering is not important,
Look, you don’t know anything about optimizing compilers, and I don’t think you know particularly much about software engineering either. Your capability to engage in reasoned discourse is constrained by your own lack of intellectual honesty. Since you don’t understand the subject matter you cannot help but mistakenly conflate your opinion regarding how code should be written with what constitutes a superior optimizer. You don’t know what you’re talking about, your posts are constantly filled with erroneous claims which you simply ignore and you don’t bother being logically consistent. You aren’t even capable of understanding what my ‘argument’ is in this discussion. That’s just how much you don’t get it.
THis discussion is going no where. All it is now is a pissing contest that is wasting my time and yours. And no I did not even bother to read your last post since I do not wish to respond, or carry this discussion on any further. It is pointless, and almost certainly, you and I are the only two who are still reading it anyway.
Consider it closed.
on the heap is slow, <insert language here>. There are a lot of objects which are allocated, with very short life times, swapping these over to stack allocations reduces their cost dramatically. Considering how dominated java program performance is by allocations, it’s worth it.
Mind you, allocations come in a distant second to the grand piece of suck that is swing. Basically, if you want a fast GUI, do nothing in swing events, pass it onto another thread, it’s a pain in the ass, but that’s the only way.
A few notes about the JVM’s memory usage. As of 1.5, the JVM can share class information loaded into memory across instances. This has reduced incremental costs dramatically. The initial overhead incurred by the JVM is because it has to loads of a lot of java facilities, instead of using the OS ones — windows does a lot of for it’s apps, the JVM has to carry similar weight. Once up and running you can load other java programs and find them not using that much more memory beyond the initial overhead, because instances replicate a lot less.
“Mind you, allocations come in a distant second to the grand piece of suck that is swing. Basically, if you want a fast GUI, do nothing in swing events, pass it onto another thread, it’s a pain in the ass, but that’s the only way.”
How is this different from any other toolkit? If you perform long running operations on the same thread that GUI events are dispathed on, you are going to freeze the GUI until that operation returns. I use Gtk quite a bit too, and it has the exact same problem.
No matter how many articles Java proponents publish, the fact remains that Java is slow compared to languages like C++. If you directly compare the results of the language shootout ( http://shootout.alioth.debian.org/ ), there is not a single benchmark where Java is faster or more memory friendlier than C++.
If indeed it is true … that for some very extreme scenario, with extreme optimization being done to both environments, at what point java being slower becomes too slow? Cripes, even the cheapest computers are going to have a 3 ghz CPU in them in less than 2 years, and there are still people bickering about “java’s slow, oh java’s sooo slow…oh wait, its slow…btw did I mention…”
Whats the high? Whats the agenda?
I hear the argument that hardware is so cheap and faster every day since years. Yet Java applications are still noticable slower than native applications. And even tough I’m going have a uber computer with 100 TB RAM next week I get out of memory errors with Eclipse today (during updating).
To put things in perspective — I don’t have a problem with Java being slow per se, but the attitude of the Java proponents, to disscuss away the facts (not only with reference to performance but other issues as well) is most annoying.
Your view is relatively moderate as compared to some people who simly speak without any forethought. Its precisely to this that sometimes many professional java developers have a forced induction of bewilderment, for lack of better words. In short, most people simply say things which are untrue, for the sake of saying it … who knows their deeper motives. (Usually I see no reason to add to these discussions, but of late its simply too easy to let blatant misrepresentation of facts inform potential customers incorrectly; again, not directed at you)
The shootout is perhaps the single stupidest thing ever to appear regarding language performance. It’s built on the “1000 monkeys will eventually type all the works of Shakespeare” principle.
Yeah, as others have pointed out, this link is worthless. The benchmarks are not even remotely accurate.
More controlled benchmarks have conclusively shown that in some cases, Java can outperform C++ because of the runtime optimization. As I said in another reply, Java can perform dynamic optimizations on code that C++ cannot even dream about since it is limited to only static optimizations at compile time.
Yes, Java is so fast that it can outperform C++ only in controlled lab environments. Yeah right, welcome to the real world!
Not only the benchmarks speak, the real world examples speak as well. Java is at this time no performance match for any traditional compiled language.
“Yes, Java is so fast that it can outperform C++ only in controlled lab environments. Yeah right, welcome to the real world!”
Yes. I will tell you about the real world. In the real world, Java is mostly used for server applications that do 100% duty cycle, where startup time is not important, and where the JIT can work its magic. In the real world, these types of applications are horribly unsuited to C++, and are also dangerous to write in C++. In the real world, speed of development and security are usually more important than squeezing out a slight improvement in performance, even if such an improvement is possible. C++ has neither speed of development, or security. In the real world other common options for server side application development, such as Perl, are 10 to 15 times slower than Java. PHP fairs even worse than Perl when it comes to performance.
“Not only the benchmarks speak, the real world examples speak as well. Java is at this time no performance match for any traditional compiled language.”
Incorrect. For most common operations, there is virtually no speed difference these days beween that operation performed in C++ and that operation performed in Java, once the JIT has been allowed to work its magic. Again, the main problem right now is that JIT optmizations are not persistant across program executions. This is detrimental on the desktop, but of no consequence on servers. However, that will be changing as well, Persistant JIT optimizations are on Sun’s to do list.
Simba,
you are changing topics. The original poster stated something about runtime performance “in the real world” and you repeated by using completely unrelated arguments about development style and security. May we take it for granted then that you don’t have relevant arguments here?
As for the runtime performance you claim there is no difference between C++ and Java when all evidence shows the opposite. Take a look at slashdot.org which covers the topic now as well. Benchmarks end public perception conclude that Java is slow — end of story.
“As for the runtime performance you claim there is no difference between C++ and Java when all evidence shows the opposite.”
Where is this evidence? So far the only evidence you have provided is a benchmark that everyone except you agrees is hopelessly flawed.
“Benchmarks end public perception conclude that Java is slow — end of story.”
I’ve quoted scientific studies that say it is not. What have you quoted? A benchmark that everyone agrees is hopelessly flawed.
By the way, here are some tests I ran myself. I did not write the code, but I compiled it myself on my system. Tell me again that the benchmarks conclude Java is slow?
In the following tests, Java outperforms C on every test except for the “life” test. Tests were conducted with mingw gcc 3.4.2 on WinXP using -O2 optimization, and Java 1.5.0_04. Bigger numbers are better for all tests. Tests are averages throughout a range of sizes / numbers:
Fast Fourier Transform: C: 521.9 | Java: 528.4
Fibonacci: C: 249.6 | Java: 372.9
Life: C: 288.1 | Java: 150.8
Infilife: C: 359.1 | Java: 434.9
Again, in all tests with the exception of the Life test, Java performed better than C.
In the following tests, Java outperforms C on every test except for the “life” test. Tests were conducted with mingw gcc 3.4.2 on WinXP using -O2 optimization, and Java 1.5.0_04. Bigger numbers are better for all tests. Tests are averages throughout a range of sizes / numbers:
Fast Fourier Transform: C: 521.9 | Java: 528.4
Fibonacci: C: 249.6 | Java: 372.9
Life: C: 288.1 | Java: 150.8
Infilife: C: 359.1 | Java: 434.9
Again, in all tests with the exception of the Life test, Java performed better than C.
Your optimizations are different than shootout ones, which use -O3 -fomit-frame-pointer -funroll-loops ; but it shouldn’t matter that much.
But for completeness, please retest with some more optimizations. For example the Fibonacci test is heavily dependant on the function call overhead. In other words it will depend heavily on optimizations that reduce the overhead. Try -fomit-frame-pointer and -mregparm=3 . -mfpmath=sse2 will help for FPU benchmarks, especially on a P4. Okay, Java can do these things automatically, which is a strong point of Java.
By the way, these test are from the *original* Shootout benchmark, which is much more flawed than the one you have criticised.
“By the way, these test are from the *original* Shootout benchmark, which is much more flawed than the one you have criticised.”
Yes, I found out they were flawed last night (although not as flawed as the ones I criticized because at least these ones did test on more than one value and did multiple repetitions), and redid them with some corrected versions I found. Here are the new results:
FFT: C: 69488 | Java: 62446
Life: C: 615405 | Java: 607263
Infilife: C: 6699 | Java: 19279
These new tests show C slightly ahead of Java on the FFT and Life tests, but the difference is statistically insignificant from a performance perspective. Java clearly blows C away though on the Infilife test.
“O3 -fomit-frame-pointer -funroll-loops”
I haven’t tried this on all of the tests yes. I did try it on the FFT test, and it yielded no performance increase. In fact, the results were actually slightly worse on the FFT test with these optimizations turned on.
I mainly chose to do the tests with -O2 since this is the most common optimization that typical software is built with on gcc.
Also, to be entirely fair, it’s possible I would get somewhat better results from C if I had access to Visual C++ to run these tests. It can probably do a better job of optimization on Win32 than GCC can.
I only read claims about the shootout being useless but no arguments. At least it is an open benchmark and everyone is free to discuss its shortcomings on public mailing lists. You can submit solutions if you think the present ones are not optimal.
Anyway, the shootout results do not seem to be that unrealistic. Show me the (unflawed) benchmarks that indicate that Java could be faster than C++. I find it somewhat reveiling that from the perspective of the Java zealots every benchmark that does not select Java as the performance king is discredited. They ignore empirical results as well as the public perception. What is the name of the reality distortion field you are living in?
“Anyway, the shootout results do not seem to be that unrealistic. Show me the (unflawed) benchmarks that indicate that Java could be faster than C++.”
http://www.kano.net/javabench/
The author indicates which tests he used, what operating system he performed the tests on, and what optimization settings he used for both GCC and Java. Java outperformed GCC in many of the cases.
Another study showed that on a standard bubble short, Java outperforms GCC even when GCC has all optimizations turned on.
In their paper “Benchmarking Java against C and Fortran for Scientific Applications”, J.M. Bull, et al. from the Edinburgh Parallel Computing Center found that Java performance was always within 20% of the same algorithims written in C or FORTRAN. The authors concluded that “On Intel Pentium hardware, especially with Linux, the performance gap is small enough to be of little or no concern to programmers.” In this same test, Java actually outpeformed some C compilers.
So now tell me again that I am ignoring empirical results. You call me a Java zealot, but it sounds more to me like you are one of the Java haters, who will accept the results of any benchmark, no matter how flawed that benchmark is, to support your assertion that Java is slower than C++.
I concluded that the shootout was useless the minute I downloaded some of the Dylan benchmarks, and realized that my results were nothing like the ones published on the site. Apparently (at least in earlier versions of the shootout), the data set for the benchmarks was so small that the C versions would complete in like 0.01 seconds, while the Dylan version would take like 0.1 seconds. When I jacked up the number of iterations, the two versions performed very similarly. I traced the issue to the fact that the Dylan runtime took a fixed amount of time during program startup, which meant that the Dylan program didn’t even get started by the time the C program had exited. Yet, does the user really care about a 0.1 second startup cost? Or is the user more concerned about performance with large data sets?
Beyond that, its fundamentally flawed to compare performance on a given benchmark when the various implementations are written by different authors. It’s the opposite of the scientific method — you change only one variable at a time! The fact that the Shootout has a lot of different benchmarks doesn’t make up for that basic flaw. A shitty experiment repeated dozens of times is still a shitty experiment!
In my own experiments (I’ve been meaning to get around to doing a proper Lisp vs. Scheme vs. Dylan vs. C++ benchmark), I’ve written a version of Fannkuch (one of the benchmarks on the shootout site) that was as fast in Bigloo Scheme as in C++. Meanwhile, the shootout says that Scheme is 1/6 the speed in Fannkuch as C++. Whose conclusion am I going to trust?
I’m developer of one of those manually memory managed languages, the Free Pascal compiler.
It has already been mentioned, but no matter how many money the Java proponents put into their utopic programming language, they haven’t yet beaten a compiler written by 10 people in their spare time:
http://shootout.alioth.debian.org/benchmark.php?test=all&lang=fpasc…
This article also shows how ignorant Java people are. If I would want to write a manual memory manager that just increases a pointer, I can, no problem.
The problem is that this is memory inefficient as hell. Actually, Free Pascal has an crazy efficient heap manager that can both do allocations in O(1) and is able to limit memory wasting. It’s hard to beat, even by ourselved.
Reading this article, now I understand why we use up to 50 times less memory in that benchmark. I also understand why it’s no surprise to see a 800MB using JVM on my machine.
I am not going to comment on the rest of your post, but just dont push links to that benchmark – it’s so flawed its not even funny. Doesn’t even compare apples to apples!
The Free … what?
Comparing a “hobby” or “educational” programming language to Java that has milions of programmers on it is flatout rediculous.
Furthermore, finding optimal solutions for very specific problems is a lot easier then finding solutions that apply to a broad spectrum.
Take a look at a very simple exampe: A large array of Point objects, for example the contour of a complex polygon
Point[] points=new Point[1000000];
In languages with value types such as C#, this will allocate a continuous block of memory with a size of 8 Megabytes which directly contains the points. In java, this would be a pointer array consuming 4 megabytes plus one million tiny objects on the heap, each consuming 8 bytes for their data and another 8 bytes of gc overhead.
So the java application consumes 20 megabytes instead of 8. You may say that memory is cheap and so this is not a problem. But all that memory has to be managed and touched, and the points are spread all over the heap, so the CPU cache will have a very hard time doing its work.
The problem gets even worse by the fact that the generics implementation of java is just syntactic sugar around object references, so even seemingly harmless constructs like a ArrayList<int> will create millions of tiny heap allocated objects.
Just face it people, java is slow and it will remain slow forever.
If you’re working with complex geometry you should be using direct buffers. In your example, allocating a direct buffer will not only allow most efficient way of sending said geometry to the GPU, but also will position it in a memory range which is not affected by GC, but managed by the programmer not unlike it is done when using a native development environment.
import java.nio.*;
That’s not a language limitation you’re showing, but a compiler one. Any good Lisp, Scheme, or ML compiler will create the 8MB array, not the 20MB one. It’s just a matter of having a good unboxing optimization. There is no reason why Java couldn’t have it too.
For every compiler their is a better compiler… Such an optimization is hard, very hard for a language like Java. The fact is that only Java needs such optimizations. It’s a great tool for bloatware.
> That’s not a language limitation you’re showing, but a
> compiler one. Any good Lisp, Scheme, or ML compiler
> will create the 8MB array, not the 20MB one. It’s just
> a matter of having a good unboxing optimization. There
> is no reason why Java couldn’t have it too.
Yes there is. If you have an array of final and immutable classes, I can see how you can handle it as an unboxed array transparently. But most java classes are mutable and not final, so that won’t work. An optimization for generic object arrays that creates an unboxed array as long as the objects are all of the same type would be very hard to do.
And the java generics implementation internally represents every generic type as an object reference, so the byte code contains no type information at all.
Sorry, but especially since the arrival of java generics it is no longer possible to do these kinds of optimizations.
In any language, maintaining a large array of Object types for what should be primitives, is not recommended. In C++, on creation and destruction one would have to deal with same problem of constructor/destructor unwinding as in Java, or for that matter in any OO language. Sure its doable for reasonable arrays, but once it grows out of hand (as the initial poster indicated about complex geometry) IMO it should be stored linearly in a memory region, i.e: x, y, z triplets stored in a FloatBuffer as such:
FloatBuffer b = …
b.put(i, x);
b.put(i + 1, y);
b.put(i + 2, z);
This is just a common sense thing to do. Btw, anyone who things method call overhead (JNI in this case) will be unbearable needs to know this: both client and server hotspot compilers (at least on windows) use intrinsics to convert this into just a few native instructions, and which use SSE and/or other vectorization to produce most optimal solution. In many cases this will be even faster than a plain vanilla C implementation, unless its compiled for a specific processor arch to take advantage of SIMD.
Yes there is. If you have an array of final and immutable classes, I can see how you can handle it as an unboxed array transparently. But most java classes are mutable and not final, so that won’t work.
Final classes make the optimization easier, but they aren’t a requirement. Global dataflow analysis and type inference can often tell you the concrete types of the objects that’ll appear in a container. If you know an aray will only ever contain objects of type Bar, you can unbox that array. Any functions you call with that array can then be cloned in the binary (using a partial-specialization pass) to expect an unboxed array instead of a boxed one.
The optimizations aren’t particularly easy, but the compiler technology for performing them is quite mature.
(I missed a typo in the previous post, rendering it silly)
OpenOffice is written in C/C++ and is slow.
I don’t get it.
Sun Microsystems makes Java and says “Everybody use Java”.
Sun Microsystems makes OpenOffice and says “Everybody use OpenOffice.”
But Sun Microsystems doesn’t use Java to implement OpenOffice. Is this an admission by Sun that Java is too slow even for Sun’s own product line? That Java has problems in a real application that Sun doesn’t want to deal with?
If the chef won’t eat his own food, who cares what the restaurant critics say?
If Sun doesn’t believe in its own hype, why should you?
So is this new escape analysis in Mustang or not?
Has anyone run any benchmarks with the new VM using the new flags?
I’m doing some benchmarks with Mustang right now. Will post the results in a few hours.
Here’s a few preliminary results. Bigger numbers are better:
Fibonacci averages:
Java 5: 56853.5 | Mustang: 62385.25
FFT averages:
Java 5: 2859.8 | Mustang: 2990.5
I will do some more tomorrow.
Is bigger better or worse?
I believe the unit of that benchmark is “cookies”. Obviously, the more cookies, the better!
Are you using the -client or -server virtual machines?
Are you using the -XX flags to turn on escape analysis?
One more thing…what platform you on?
I heard that on Windows, they are using a newer compiler for Mustang (VS.Net 2003 compiler vs the C++ 6.0 compiler). Might that alone make up the difference in performance?
There is no -X flag for enabling escape analysis, and I think it is enabled by default in Mustang.
The results I gave before, and the results I compared Java 5 against C with were in client mode. Using server mode, Java turns in even more impressive numbers. Here are the raw data averages for the tests for Java 5, Mustang. All tests were conducted on Windows XP using mingw GCC 3.4.2 with -O2 optimization, and Java 5, and Java 6 with the -server flag. Bigger numbers are better for all tests, and results are left to right in order of fastest to slowest:
Fast Fourier Transform:
Mustang: 4826.7 | Java 5: 4287.9 | C: 2617.3
Fibonacci:
Java 5: 91331.3 | Mustang: 90134.6 | C: 37961.1
Life:
C: 6112.9 | Mustang: 6105.9 | Java 5: 6060.7
Infilife:
Mustang: 1146.2 | Java 5: 1042.7 | C: 858.1
AFAIK you need the following flags to enable it in the mustang builds:
java -server -XX:+DoEscapeAnalysis
“java -server -XX:+DoEscapeAnalysis”
On these tests, enabling escape analysis didn’t really make a difference. The only test where there was an overall improvement was the life test, and it was pretty small. Only about 2.11%
Regarding escape analysis, it has been pointed out to me that most of the optimizations that actually use the information from escape analysis have not been implemented yet, including the two big ones which are stack allocation, and lock elimination. The minor performance improvement seen in Life was due to only minor optimizations that currently use info from escape analysis. But the major ones are still coming.
GC is evil for realtime apps. It is definitely better to have predictable behavior than ocasional GC sweeps.
GC is evil for realtime apps. It is definitely better to have predictable behavior than ocasional GC sweeps.
Check out java realtime:
java.sun.com/docs/books/realtime/
http://ptolemy.eecs.berkeley.edu/conferences/05/presentations/dbaco…
Not much.
Usually compiler spends only a fraction of time for compiling.
Depending what are you testing – java speed vs hotspot compiler speed.
Imagine you make a code generation twice as fast. So putting say 3% time spending in hotspot you’ll get 1.5% speedup.