9 ms·
One the one hand, yes. On the other hand, all of this sounds much more complex and fragile. This seems like an important point to me: "Remarkably, we had only
by dochtman 7y ago
One the one hand, yes. On the other hand, all of this sounds much more complex and fragile. This seems like an important point to me:
"Remarkably, we had only put very basic thought into optimization as the Rust version was written. Even with just basic optimization, Rust was able to outperform the hyper hand-tuned Go version."
- novok 7y agoA C app will tend to outperform a Java or Golang app by 3x, so it isn't too surprising.
- georgebarnett 7y agoCould you please provide a source for this? Java is very fast and 3X slower is a pretty wild claim.
- squarefoot 7y ago3x might be a bit too much today, but it's definitely slower than C. Also to be considered is the VM overhead, not just the executed code. Here are some benchmarks; I'll leave to the experts out there to confirm or dismiss them. https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/java.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- robocat 7y agoHowever the memory usage difference is astonishing for some of those benchmarks - using 1000x more memory is only acceptable for some situations.
- iainmerrick 7y agoThis may be overly cynical, but don’t you have it backwards? 1000x greater memory usage is acceptable for most applications. There are only a few applications for which it isn’t acceptable. Just look at all the massive apps built on Electron. People wouldn’t do that if it wasn’t effective.
- wool_gather 7y agoWouldn't you say there's a difference between "effective" and "getting away with it"? If non-technical users see that their daily computing lives are made more complicated (because of lowered performance) by having n Electron apps running at the same time, they may not understand the reasons, but they will certainly choose a different solution that has the features they need, where available.
- iainmerrick 7y agoWouldn't you say there's a difference between "effective" and "getting away with it"? I used to think that but now I’m not so sure. :(
- igouy 7y ago— default JVM allocation ~35 MB looks astonishing for tiny programs that don't allocate memory — memory usage is less different for tiny programs that do allocate memory: reverse-complement, k-nucleotide, binary-trees, mandelbrot, regex-redux
- squarefoot 7y agoAgreed, and ironically the most widely used Java platform (Android), despite its VM optimizations, is the one which would benefit the most from running only native code. I mean, those 1GB RAM 7 years old slow as molasses phones getting dust into drawers or being littered into landfills would scream if they didn't have to run everything behind a VM.
- yc12340 7y agoMake no mistake — Android isn't memory hungry because of Java alone. Android 4 used to comfortably fit in 1Gb of RAM, but Android 10 no longer can run on such devices. Both old and new versions use JVM, but newer Android has a lot of "helpful" system services, such as "Usage Statistics" service [1] and "Autofill Servide" [2]. Google's spyware is becoming more invasive and thus more memory-hungry. 1: https://developer.android.com/reference/android/app/usage/UsageStats https://developer.android.com/reference/android/app/usage/Us... 2: https://developer.android.com/reference/android/service/autofill/AutofillService https://developer.android.com/reference/android/service/auto...
- anarazel 7y agoReally depends on the domain. There's some things that are a lot easier to make scale up in a language with a great concurrent gc, because that makes writing some lock free data structures quite fundamentally easier (no complicated memory reclamation logic, trivial to avoid ABA problems).
- pkolaczk 7y agoGC makes it easier to write, but not necessarily better. Modern state-of-the-art Java GCs operate a global heap, so you often pay for what you do not use. In languages like Rust or C++ your can build small locally GCed heaps, where you can limit GC overhead to just a few particular structures that need GC, not everything. Therefore other structures like caches don't affect GC pause times. And the "hardness" of writing lockless structures is strongly offset by libraries, so unless you're doing something very exotic, it is rarely a real problem.
- BenFrantzDale 7y ago“GC makes it easier to write.” I disagree. GC means I don’t get deterministic destruction which means I can’t use RAII properly.
- pkolaczk 7y agoThe post was about writing lockless structures. With lockless RAII is of no use. See ABA problem. RAII is awesome in other places.
- kllrnohj 7y ago> 3x might be a bit too much today, but it's definitely slower than C. If anything the gap is increasing not shrinking. JVM is terrible at memory access patterns due to the design of the language, and designing for memory is increasingly critical for maximum performance on modern systems. All the clever JIT'ing in the world can't save you from the constant pointer chasing, poor cache locality, and poor prefetching. The gap won't shrink until Java has value types. Which is on the roadmap, yes, but still doesn't exist just yet. The problem with those benchmarks is if you look at the Java code you'll see it's highly non-idiomatic. Almost no classes or allocations. They almost all exclusively use primitives and raw arrays. Even then it still doesn't match the performance on average of the C (or similar) versions, but if you add the real-world structure you'd find in any substantial project that performance drops off.
- wool_gather 7y agoWhen you say "value types" in this context, you mean "copy-only types"?
- kllrnohj 7y agoI mean "value types" https://www.jesperdj.com/2015/10/04/project-valhalla-value-types/ https://www.jesperdj.com/2015/10/04/project-valhalla-value-t... & http://cr.openjdk.java.net/~jrose/values/values-0.html http://cr.openjdk.java.net/~jrose/values/values-0.html I don't know what you mean by "copy-only types." I'm not finding any reference to that terminology in the context of language design.
- wool_gather 7y agoAh, thanks for the link; I wasn't sure what it meant in the context of Java, since it's possible to get value semantics using a class. Sorry about the confusion. I meant for the quotes around "copy-only" to indicate that it wasn't really a standard term, but I marked "value types" the same way, so that didn't really work. By "copy-only" I meant something you couldn't have more than one reference to: every name (variable) to which you assign the data would have its own independent copy.
- marcosdumay 7y agoThose people have a really good claim to have the most optimized choice on each language. They've found Java to be 2 to 3 times slower than C and Rust (with much slower outliers). https://benchmarksgame-team.pages.debian.net/benchmarksgame/which-programs-are-fastest.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... On the real world, you won't get things as optimized in higher level languages, because optimized code looks completely unidiomatic. A 3x speedup from Java is a pretty normal claim.
- bcrosby95 7y agoSpeaking of, I wish there were an "idiomatic code benchmarks game". Some of us want to compare language speed for common use cases vs trying to squeeze every last piece of performance from it.
- totalperspectiv 7y agoCheck out this: https://github.com/frol/completely-unscientific-benchmarks https://github.com/frol/completely-unscientific-benchmarks
- tormeh 7y agoD, Nim and Crystal all do very well on all metrics. Author finds Rust pretty close but not as maintainable. Interesting that the top 3 (performance close to C++, but more maintainable) all are niche languages that haven't really broken into the mainstream.
- marcosdumay 7y agoRust won't get a maintainability prize for short programs with simple algorithms. It's Haskell-like features only help on large and complex programs.
- vnorilo 7y agoThey do help library writers, and therefore turn large and complex programs into shorter programs.
- gameswithgo 7y agoIt depends greatly on the problem domain. The difference might be near zero, or you might be able to get ~16x better performance (using say, AVX-512 intrinsics). Then again, is intrinsics really C? Not really, but you can do it. What if you have to abandon using classes when you want to, in order to get the memory layout you want in Java, are you still using Java?
- the_duke 7y agoVMs with JIT like the JVM are only ever really fast/competitive with C in small numerical micro-benchmarks where the code can be hyper-optimized. Most code will be considerably slower due to a lot of factors. Java in particular is a very pointer-heavy language, made up of pointers to pointers to pointers everywhere, which is really bad for our modern systems that often are much more memory latency than CPU constrained. A factor of 2-4x to languages like C++ or Rust for most code seems plausible (and even low) unless the limiting factor is external, like network or file system IO.
- thu2111 7y agoThis stuff is really hard to pin down though. I've been reading these sorts of debates forever. It's true that pointer chasing really hurts in some sorts of program and benchmark. For sure. No argument. That's why Project Valhalla exists. But it's also my view that modern C++ programming gets away with a lot of slow behaviours that people don't really investigate or talk about because they're smeared over the program and thus don't show up in profilers, whereas actually the JVM fixes them everywhere. C++ programs tend to rely much more heavily on copying large structures around than pointer-heavy programs. This isn't always or even mostly because "value types are fast". It's usually because C++ doesn't have good memory management so resource management and memory layout gets conflated, e.g. std::vector<BigObject>. You can't measure this because the overheads are spread out over the entire program and inlined everywhere, so don't really show up in profiling. For the same reasons C++ programs rely heavily on over-specialised generics where the specialisation isn't actually a perf win but rather a side effect of the desire for automatic resource management, which leads to notorious problems with code bloat and (especially) compile time bloat. Another source of normally obscured C++ performance issues is the heap. We know malloc is very slow because people so frequently roll their own allocators that the STL supports this behaviour out of the box. But malloc/new is also completely endemic all over C++ codebases. Custom allocators are rare and restricted to very hot paths in very well optimised programs. On the JVM allocation is always so fast it's nearly free, and if you're not actually saturating every core on the machine 100% of the time, allocation effectively is free because all the work is pushed to the spare cores doing GC. Yet another source of problems is cases where the C++ programmer doesn't or can't actually ensure all data is laid out in memory together because the needed layouts are dynamically changing. In this case a moving GC like in the JVM can yield big cache hit rate wins because the GC will move objects that refer to each other together, even if they were allocated far apart in time. This effect is measurable in modern JVMs where the GC can be disabled: https://shipilev.net/jvm/anatomy-quarks/11-moving-gc-locality/ https://shipilev.net/jvm/anatomy-quarks/11-moving-gc-localit... And finally some styles of C++ program involve a lot of virtual methods that aren't always used, because e.g. there is a base class that has multiple implementations but in any given run of the program only one base class is used (unit tests vs prod, selected by command line flag etc). JVM can devirtualise these calls and make them free, but C++ compilers usually don't. On the other hand all these things can be obscured by the fact that C++ these days tends only to be used in codebases where performance is considered important, so C++ devs write performance tuned code by default (or what they think is tuned at least). Whereas higher level languages get used for every kind of program, including the common kind where performance isn't that big of a deal.
- dotaheor 7y agoThis really depends on what job a program does and how well the C program is implemented.
- danesparza 7y agoI call utter bullshit especially when dealing with threads. I think you'll spend so much time debugging pointers, the stack and your memory allocations that switching to a more modern language could save you significant debugging time. But now I sound like a Geico (insurance) commercial. Sorry about that.
- _ph_ 7y agoThis statement is definitely wrong in this generic blank fashion. Also I would lay upon you the burden of proof for it :). Tight, low level code in Java and Go is roughly as fast as average C code. The Go compiler is know to be less good at optimizing code than e.g. GCC, but this in many cases creates little practical difference, while the Java JIT compilers have become excellent to a point where they often beat GCC, especially as they can use run time profiling for code optimization. So they can optimize the code for the actual task at hand. Where the languages differ in "speed" is their runtime environment. Java and Go are languages with garbage collection, which of course means that some amount of CPU is required to perform GC. But as the modern garbage collectors run in parallel with the program, this CPU effort often enough is no bottleneck. On the other side, manual memory management has different performance trade-offs, which in many cases can make it quite slow on its own.
- chubs 7y agoI found similarly when I ported an image resizing algorithm from Swift to Rust: I'm experienced in swift thus was able to write in an idiomatic way, and have little Rust experience thus I wrote it in a naive way; yet still the rust algorithm was twice(!) as fast. And swift doesn't even have a GC slowing things down!
- dgellow 7y agoARC, used by Swift, has its own cost.
- 1propionyl 7y agoTrue, but it's generally better than most full GC solutions (for processes running for relatively short times without the benefit of profile-guided optimization), and worse than languages with fully statically analyzable memory usage. Note: that parenthetical is a very big caveat, because properly profile-optimized JVM executables can often achieve exceptional performance/development cost tradeoffs. In addition however, ARC admits a substantial amount of memory-usage optimization given bytecode, which is now what developers provide to Apple on iOS. Not to mention potential optimizations by allowing Apple to serve last-minute compiled microarchitecture optimized binaries for each device (family). To satiate the pedants... ARC is more of less GC where calls into the GC mechanism are compiled in statically and where there are at worst deterministic bounds on potential "stop the world" conditions. While this may not be presently optimal because profile-guided approaches can deliver better performance by tuning allocation pool and collection time parameters, it's arguably a more consistent and statically analyzable approach that with improvement in compilers may yield better overall performance. It also provides tight bounds on "stop the world" situations, which also exist far less frequently on mobile platforms than in long running sever applications. Beyond those theoretical bounds, it's certainly much easier to handle when you have an OS that is loading and unloading applications according to some policy. This is extremely relevant as most sensible apps are not actually long running.
- ernst_klim 7y ago> but it's generally better than most full GC solutions I doubt that. It implies huge costs without giving any benefits of GC. A typical GC have compaction, nearly stack-like fast allocation [1], ability to allocate a bunch of objects at once (just bump the heap pointer once for a whole bunch). And both Perl and Swift do indeed perform abysmally, usually worse than both GC and manual languages [2]. > ARC is more of less GC Well, no. A typical contemporary GC is generational, often concurrent, allowing fast allocation. ARC is just a primitive allocator with ref/deref attached. [1] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.49.2537&rep=rep1&type=pdf http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.49.... [2] https://github.com/ixy-languages/ixy-languages https://github.com/ixy-languages/ixy-languages