6 ms·
When you're using a programming language that naturally steers you to write slow code you can't only blame the programmer. I was listening to someone say they
by cmovq 6mo ago
When you're using a programming language that naturally steers you to write slow code you can't only blame the programmer.
I was listening to someone say they write fast code in Java by avoiding allocations with a PoolAllocator that would "cache" small objects with poolAllocator.alloc(), poolAllocator.release(). So just manual memory management with extra steps. At that point why not use a better language for the task?
- ablob 6mo agoYou might have an application for which speed is not important most of the time. Only one or two processes might require allocation-free code. For such a case, why would you burden all of the other code with the additional complexity? Calling out to a different language then may come with baggage you'd rather avoid. A project might also grow into these requirements. I can easily imagine that something wasn't problematic for a long time but suddenly emerged as an issue over time. At that point you wouldn't want to migrate the whole codebase to a better language anymore.
- cogman10 6mo agoBad idea. I've made a pool allocator before, but that was for expensive network objects and expensive objects dealing with JNI. Doing it to avoid memory pressure generally means you simply have a bad algorithm that needs to be tweaked. It's very rarely the right solution.
- gf000 6mo agoNot sure why you are down voted. Depending on how its used it could actually be detrimental to performance. The JVM may optimize many short lived objects better than a pool of objects with less reasonably lifetimes.
- cogman10 6mo agoThis is the second time this week on HN that I've seen people suggesting object pools to solve memory pressure problems. I generally think it's because people aren't experienced with diagnosing and fixing memory pressure. It's one of the things I do pretty frequently for my day job. I'm fortunate enough to be the "performance" guy at work :). It'll always depend on what the real issue is, but generally speaking the problem to solve isn't reinventing garbage collection, but rather to eliminate the reason for the allocation. For example, a pretty common issue I've seen is copying a collection to do transformations. Switching to streams, combining transformation operations, or in an extreme case, I've found passing around a consumer object was the way to avoid a string of collection allocations. Even the case where small allocations end up killing performance, for example like the autoboxing example of the OP, often the solution is to either make something mutable that isn't, or to switch to primitives (Valhalla can't come soon enough). Heck, sometimes even an object cache is the right solution. I've had good success reducing the size of objects on the heap by creating things like `Map<String, String>` and then doing a `map.computeIfAbsent(str, Function.identity());` (Yes, I know about string interning, no I don't want these added to the global intern cache). Regardless, the first step is profiling (JFRs and heap dumps) to see where memory is spent and what is dominating the allocation rate. That's a first step that people often skip and jump straight to fixing what they think is broken.
- ivan_gammel 6mo agoTBH, I do not see how Java as a language steers anyone to use one those shotguns. E.g. the knowledge about algorithmic complexity is foundational, the StringBuilder is junior-level basic knowledge.
- deleted 6mo ago[deleted]
- nightpool 6mo agoHow would you handle validating numeric input in a hot path then? All of the solutions proposed in #5 are incomplete or broken, and it stems from the fact that Java's language design over-uses exceptions for error handling in places where an optional value would be much safer and faster.
- ivan_gammel 6mo agoNormally in 100% cases, with parseInt/parseDouble etc. Getting NumberFormatException so frequently on a hot path that it impacts performance means, that you aren’t solving the parsing number problem, you are solving a guessing type problem, which is out of scope for standard library and requires custom parser.
- nightpool 6mo agoOkay, but this contradicts your original statement that "Java doesn't steer anyone to use these [footguns]". Every language has a way to parse integers, and most developers do not need a custom parser. Only in Java does that suddenly become a performance footgun.
- ivan_gammel 6mo agoIt does not. If you need to parse a number, you use standard library and you will be fine. The described case with huge impact on hot path is the demonstration why using brains is important. The developer that will get into this mess is the one who will find the way to suffocate his code with performance bottlenecks in thousand other ways. It’s not a language or library problem.
- ekkeke 6mo agoThis point gets raised every single time managed languages and low latency development come up together. The trade off is running "fast" all of the time, even when you don't have to, vs running slow most of the time and tinkering when you need to go fast. I've spent a fair few years developing lowish (10-20us wire to wire) latency trading systems and the majority of the code does not need to go fast. It's just wasted effort, a debugging headache, and technical debt. So the natural trade off is a bit of pain to make the hot path fast through spans, unsafe code, pre-allocated object pools, etc and in return you get to use a safe and easy programming language everywhere else. In C# low latency dev is not even that painful, as there are a lot of tools available specifically for this purpose by the runtime.
- d_burfoot 6mo ago> So just manual memory management with extra steps This is actually the perfect situation: you are allowed to do it carefully and manually for 1% of code on the hot path, but you don't have to worry about it for the 99% of the code that's not.
- devnotes77 6mo ago[dead]
- laughing_man 6mo agoJava doesn't steer you into object pools. I wrote Java code for 20 years and never used a cache to avoid allocating objects, and never saw a colleague use one. The person you were talking to doesn't know what he's doing.
- cxr 6mo agoThe problem with comments like these is that guessing what "better language" a commentator has in mind is always an exercise left up to the reader. And that tends to be by design—it's great for potshots and punditry, because it means not having make a concrete commitment to anything that might similarly be confronted and torn apart in the replies—like if the "better language" alluded to is C (and it generally is)—the language where the standard library "steers" you towards quadratic string operations because the default/natural way to refer to a string's length is O(n).
- andai 6mo agoI decompiled Project Zomboid (written in Java) a while back, because I was curious about the performance issues I was having with the game. (Very laggy on my 10 year old laptop, while looking like The Sims 1.) I figured, best case scenario I find some easy bottlenecks and I can patch in a fix. Well, the whole thing was standard Java OOP, except they also had a bunch of functional programming stuff on top of that. I can relate to that -- I think they were university students when they started, and I definitely had an OOP and FP phase. But then they just... kept it, 10+ years later. So while it's true that you can write C in any language... those kind of folks don't tend to use Java in the first place ;) -- (Except Notch? Well, his code looks like C, not sure if it's actually fast! I really enjoyed his 4 kilobyte java games back in the day, I think he published the source for each one too.) EDIT: Found it! https://web.archive.org/web/20120317121029/http://www.mojang.com/notch/j4k/l4kd/ https://web.archive.org/web/20120317121029/http://www.mojang... Edit 2: This one has a download, still works! https://web.archive.org/web/20120301015921/http://www.mojang.com/notch/ld12/breaking/ https://web.archive.org/web/20120301015921/http://www.mojang...
- bigwheels 6mo agoWhat is the ending of your story!? Did you find and fix some bottlenecks?
- kykat 6mo agoI saw something like that being suggested when working with GIS data with many points as classes in Java, the object overhead for storing XYZ doubles is quite crazy. The optimization was to build a global double array and use "pointers" to get and set the number in the array. Even JavaScript is much better for this, much, much better.
- lern_too_spel 6mo agoYou're describing array of structs vs. struct of arrays. Even in JavaScript, you would have to manually do the latter.
- kykat 6mo agoV8 automatically optimizes objects with the same shape into efficient structs, making array of objects much more efficient than in Java. And the manually manager int array acts more like system memory, it's not continuous, so you could have point i 0 and 2 and the data would be: [1, 2, 3, x, x,x, 3, 2, 1] (3D points). So I am not describing a struct of arrays.
- spankalee 6mo agoHidden class optimizations just make JavaScript objects behave a little more like Java class instances, where the VM knows where to find each field, rather than having to look it up like a map. It doesn't make JS faster than Java, it makes it almost as fast in some cases.
- kykat 6mo agoI can only say what I observed in testing, and that's that having millions of instances of a class like Point3D{x, y, z} in JS uses significantly less memory than in Java (this was tested on Android, not sure if relevant). It was quite some time ago so I don't remember the details.
- 6mo ago
- wiseowise 6mo ago> At that point why not use a better language for the task? Such as?