9 ms·
Debunking the Java Performance Myth
- sempron64 9y agoI think an important element in comparing Go to Java for webserver apps is language design. While Java 8 and Go's performance may be similar in small single-threaded request handler benchmarks, Java's baseline design encourages the creation of lots of expensive runtime abstractions, and makes parallelism difficult. Go on the other hand encourages a minimum of abstractions and makes parallelism trivial. That means that the marginal cost of business logic is much higher in Java, in both response times (due to unnecessary serialization) and overall computation. Some of this can be averted by careful engineering, but Java definitely isn't a "pit of success" in this regard - the easiest thing to do is usually the wrong thing.
- twic 9y ago> Java's baseline design encourages the creation of lots of expensive runtime abstractions Abstractions yes, expensive, perhaps not. One of the nice things about Java is that the JIT can collapse a lot of abstraction at runtime. Not all of it, but a lot of it. I am skeptical about the idea that Java naturally guides programmers towards expensive abstractions. > and makes parallelism difficult Presumably, you mean something like "makes lightweight concurrency difficult, because all the backend APIs for database access etc are blocking", which is unfortunately true.
- sidlls 9y agoI think perhaps it's more of a "pure OO" approach than the language itself. I've seen plenty of Java and C++ code where there is one interface class for every concrete class, even when just one concrete class is ever implemented, for example. I've also seen cases where some "factory" pattern is force-fit into the architecture, and the objects it creates are kinda sorta related, but ought not be in code. It gets exponentially worse as more interfaces and more levels in a hierarchy are allowed. The compiler isn't always going to be able to collapse or elide these.
- diebir 9y agoThe thing about Go I do not get is why somebody would go back to essentially C to develop modern code? The tools are lacking, the language features are lacking, the libraries are lacking, so why? Go is still garbage collected language, so in a sense it combines the most problematic features of C and Java.
- flavor8 9y agoI'm not sure that there's a myth to be debunked, is there? Java's known to be high performance as a web application server, if good architectural choices are made. The well referred to https://www.techempower.com/benchmarks/ https://www.techempower.com/benchmarks/ reliably has some of the better Java frameworks ranking near the top along with C and C++ servers.
- mikeash 9y agoYeah, the title confuses me greatly. I assumed this was going to be an article about how Java is slow, debunking the myth that it’s really fast.
- whois 9y agoReally? You've never heard people joke about Java being slow? Half the programmers I've met have this cult like hate of java and cite performance as the main reason.
- timthelion 9y agoJava is slow, but not in this case. Tight loop java is fast. Anything that touches memory is slow. Anything that involves loading jar files is slow. Anything that involves starting the VM is slow. But tight loop java is fast, indeed, being a JIT, potentially faster than C (better branch prediction given that the JIT can optimize at runtime). So the claim that Java is slow is true. That's why so many people hate it. The fact that Java is fast is also true.
- tsmarsh 9y agoJava is slow compared to C/C++ and Fortran and comparable with SBCL / Rust. But it is fast compared to Python, JavaScript, PHP and Ruby. It's the rise of these languages that confuses me. They somehow got away with the 'fast enough' argument whilst Java is constantly being compared to languages that are designed for fine tuning for the target architecture. In my mind it is Java that is 'fast enough' and,with Java 8, very expressive. The continued success of these incredibly slow interpreted languages in enterprises where you need to buy servers feels like an anti-pattern.
- ssijak 9y agoOne more dumb test not even giving the code and test environment fully. Btw, this tests are useless. Add some real usecase, a database, some number crunching, jobs execution and see python fail even more for example.
- falcolas 9y agoThe JVM has indeed matured to the point where it's on par with other VM style languages, and better than interpreted languages. This wasn't always the case: early in Java's lifetime it was a slow, memory intensive hog. That stigma has stuck. That said, it's still pretty heavyweight (both the language and the runtime). It also wouldn't be my first choice for compute intensive tasks (for example, a non-toy ray tracer). It would do the job eventually, but at a cost. Of course, I wouldn't pick Go or Python either.
- agumonkey 9y agoReminds me people blaming clojure slow boot on the JVM when it was in fact clojure tooling that took time. Things aren't straightforward, we need to go deep before concluding. Profilers, profilers, profilers.
- amaranth 9y agoThere are people in college or entering the workforce who weren't even alive during the "Java is slow" period. The HotSpot JIT has been around since 1999. I wonder if we'll ever be able to let this go.
- Timothycquinn 9y agoWould be interested in seeing Elixir/Phoenix compared here. I've seen some amazing scalability figures from those folks: http://phoenixframework.org/blog/the-road-to-2-million-websocket-connections http://phoenixframework.org/blog/the-road-to-2-million-webso... For posterity sake, throw in Ruby on Rails as well.
- brightball 9y agoElixir is more focused on concurrent performance than raw performance. It’s still very fast but favors consistency above all else. I remember seeing a great benchmark that compared Elixir to Python and Go where they charted the variability of response times. Python and Go were very spikey with Go producing the fastest overall time. Elixir was extremely steady. Makes it an ideal choice for real time ops, holding millions of web sockets, ensuring a heavy process doesn’t affect the experience of everything else that’s executing. You’ll also get natural clustering ability and a level of fault tolerance that’s almost silly. I’ve been trying to find the time to demonstrate this with the tech empower benchmarks honestly. I want to see what will happen if you run all of them at the same time for a particular platform.
- rlander 9y agoIt baffles me how people give Elixir the credit for this. Everything you mentioned here have nothing to do with Elixir, but with how Erlang and its preemptive scheduler were optimized for soft real-time apps.
- jswizzy 9y agoYep, Elixir mostly just changed the syntax to something more C like instead of ant turds. Erlang is a beautiful design but the prolog syntax never really caught on.
- brightball 9y agoBEAM gets the credit but the parent mentioned Elixir so that’s how I responded. It’s just quicker than writing Elixir/Erlang/BEAM/OTP everytime. Wasn’t trying to misappropriate the credit.
- boggio 9y agoFlask is synchronous and it shouldn't be labeleld "Python 2.7 or Python 3.6". Comparing that to async frameworks is not quite fair. (Also is SpringBoot async?)
- ssijak 9y agoSpring Boot can be both reactive or ordinary thread pool based to serve requests or anything from the stack really. It is very very powerful framework and comparing something barebones to Boot is really dumb. Not to mention that author intentionally made java look like a monster when he could use some simple tweaks to reduce jvm memory usage by much and he hid what dependencies really imported. And also if he did not like Boot he could just fire barebons Jetty up and use 20mb heap tops.
- chvid 9y agoDid you publish the source code for the test servers (in the various languages)? I am curious to what a "normal" Java microservice look like.
- coldtea 9y agoNot very different than a "normal" Node microservice. It might even take fewer lines.
- JepZ 9y agoWell, I have not taken a look at the implementation yet, but java is certainly known for delivering a decent performance even if the programmer is a little careless regarding perfromance. In Go on the other hand, doing simple 'mistakes' like declaring a variable inside a loop can bring you to performance hell: Declaration in a loop: var sum int for i := 0; i < n; i++ { x := i + i sum = x - i } Declaration outside the loop: var sum int var x int for i := 0; i < n; i++ { x = i + i sum = x - i } Benchmark results: BenchmarkInLoop-8 2000000000 0.40 ns/op BenchmarkOutLoop-8 2000000000 0.47 ns/op And the same is certainly true for C/C++. Src: https://nopaste.xyz/?68c6800acd9200d6#mDstI36uBPBU4Td8k//GNC+P7mmbB1ldMw3DGMuxeQo= https://nopaste.xyz/?68c6800acd9200d6#mDstI36uBPBU4Td8k//GNC...
- Retric 9y agoThis is a common compiler optimization. It says little about a language, just the compiler in use.
- yoklov 9y agoDeclaring a primitive variable inside vs outside a loop in c or c++ will have no effect when compiled with optimizations on by any major compiler. For non-primitive types it will depend on a number of factors, and the better choice for perf could go either way.
- DannyBee 9y agoYes, because if the loop is not always-executing, it may be cheaper to not initialize the complex object, even if it is safe to so.
- yoklov 9y agoI've also (recently) had poor performance on MSVC when "outside the loop" meant "a function argument", for a type that was essentially a struct wrapping a single primitive. It ended up being ABI weirdness that was confusing MSVC (and forceinline ended up fixing it).
- traspler 9y agoSpring Boot really comes away awful in this article (and the one he links in the article). I have mostly worked on projects using Dropwizard and Spring Boot and have come to like some of the easy to use abstractions but I have only scratched the surface of these frameworks, I assume, and most of it I will probably never use. Most of the time it did not matter that much to give the Server a GB more memory but recently we had some real issues with CloudFoundry. To me it seems that it's not possible to somehow magically tweak Spring Boot to behave better. So I came to wonder, what other framework would strike a better balance? Maybe not offer the crazy specialised stuff Spring offers or maybe needing some more work to get something to run but then offer vastly better memory and speed charactersitics? I guess one way would be to implement the things I actually use myself with less abstractions but that honsetly feels very daunting to me. The Java ecosystem is so vast and between Handling the Requests, DB access (with or without ORM), persistance, caching, security, I really have no clue on where to even start doing something like this myself. If someone more seasoned here has some input, I would be highly interested!
- RhodesianHunter 9y agoYou mentioned Dropwizard early on, in my experience I have found it to be the polar opposite of Spring. Where Spring is an "everything but the kitchen sink" framework, Dropwizard is just a collection of best-in-class libraries that are easily swapped out if you prefer something else. I don't get to do so often professionally, but if given my choice of tools ill generally opt for a combination of Dropwizard in Kotlin.
- traspler 9y agoOne big drawback of Dropwizard (at least for us) was that it was very problematic to deploy it as a war in a tomcat environment. There is wizard-in-a-box but there were a lot of issues with that as well.
- unscaled 9y agoWell, if you're doing microservices you're usually nullifying most of the benefits of this kind of architecture if you're just deploying them on war files on a single application container.
- msl09 9y agoPretty good article but I wish we had the source code so we could compare code complexity also.
- barrkel 9y agoThe primary reasons for choosing a particular language for your application server usually come down to developer ergonomics, developer availability and library availability / integration for your specific domain. Performance rarely comes into it; performance while scaling into astronomical request numbers is important for top web sites, but most app servers don't see that kind of load. Even if some requests needs crunchy CPU power, it's better to offload them into something asynchronous than try really hard to make them perform well enough to be synchronous. Typically, hefty CPU jobs come in varying sizes, they're rarely guaranteed to be runnable under the 200ms or so latency bar for synchronous requests.
- tomelders 9y agoI find that laughably generous. In my experience, Java gets a pass because it's "enterprise", whatever the hell that means. I've never heared anyone make a compelling case for Java on technical merit. It's always "we're a Java shop, because we're enterprise".
- ssijak 9y agoYou say there is no technical merit to use Java ecosystem over something else?
- tomelders 9y agoNope. Thats not what I said.
- RhodesianHunter 9y ago"I've never heared anyone make a compelling case for Java on technical merit." IMO this is a sign that you should expand the company you keep rather than being indicative of any flaw with Java.
- jlmorton 9y agoIf you're a business making a language choice based on the technical merits of the language itself, you are very much doing it wrong.
- Retric 9y ago1,000 requests per second for a hello world micro service is horribly slow. I don't know what architecture they are using bit ~100,000 / CPU for simple requests is completely reasonable making this test very dubious IMO.
- tyingq 9y agoSome of the stacks he tested had significant failure rates at 1000/sec though. Bumping it up would have made the comparison less interesting. Perhaps it was just a small VPS?
- rsynnott 9y agoOne issue here is that it’d really be more appropriate to run the test twice and take the second result. This should get most JITing out of the way. It’s hard to be sure what’s happening given the lack of source code, but 1000 requests per second where the request doesn’t do much is a fairly minor load for a well-written java service on modest hardware. I would expect the ‘lightweight’ java example to do better, assuming it’s just jetty or something.
- emforce 9y agoHi All, this has received an incredible amount of views and comments since I posted this and left the house! I appreciate the feedback comments! I'm very much still playing around with different technologies and writing about them as I go, this is more a learning experience for me that I've documented and I would take what I'm saying with a pinch of salt. I thought I'd also clarify that I'm using the code/docker images that I created in the previous article as the base from which I'm running my tests as that seems to have gotten missed by a few peeps!
- jacques_chester 9y agoI definitely missed it. Maybe adding a link to this one as well would be helpful. Edit: I see the code using the `com.sun.net.httpserver` package, but not the Spring Boot version.
- ajnin 9y agoHow does an "Hello world" request on localhost take an average of 50~100ms using any framework ? 1ms would already be too much. Something seems way off with this benchmark.
- pipio21 9y agoThe myth that java is slow is not a myth it is true for medium to big programs with lots of interconnections, because with the abstraction you loose control on the program behavior. You gain in other things, like abstraction, but the penalty is enormous. We use very high level languages in house, but when we do it performance is not the priority. Doing "Hello worlds" is not a valid debunking of anything because , guess what? printing a Hello world in a screen is a very simple operation. We have millions of lines of code and we have done tests on just converting 20-30Ks of our c,c++ code to java and the result has been disaster: Hundreds or thousands of times slower. That's right. In my opinion if other companies are deluded wanting to be lazy, much better for us as competitors, but children should not be intoxicated with bad advice. My advice is do not believe me or anyone else, when in doubt just test on your own.
- sk5t 9y agoLike with any language, the level of abstraction is up to you... one could just as easily "lose control" with C++. Hundreds or thousands of times slower Java? Have you considered that the conversion was done with a weak mastery of the language or runtime? The HFT folks working in Java would be taken aback to learn the language doesn't work.
- deleted 9y ago[deleted]
- luord 9y agoDamn, I will have to take a look at aiohttp. That's impressive, I'm glad that python, my favorite language, can have that kind of performance.