4 ms·
Any place you care about memory layout, AKA performance. O(n) doesn't matter if you cache miss all over the place. Some GC languages(like C#'s structs) have som
by vvanders 11y ago
Any place you care about memory layout, AKA performance. O(n) doesn't matter if you cache miss all over the place. Some GC languages(like C#'s structs) have some tools for this but as soon as you work with refs you've lost control.
To me that's any device with a battery(I'm looking at you smartphones), gamedev, and as you mentioned embedded systems.
There's also another class of programs that's not related to GC. C++(and C by subset) is the only way to write truly cross-platform code for all the modern OS's. If you want to target Android, iOS and Desktop C++ is the only supported path on all those platforms with the right performance guarantees(JS doesn't cut it perf-wise on mobile, yet). That's why you see DropBox and quite a few other shops using C++.
- pron 11y agoGC and control over memory layout are two completely orthogonal issues. You can have either one, neither, or both.
- vvanders 11y agoI don't know that they're completely orthogonal, GC by nature controls the allocation of objects which implicitly means that the layout in memory is controlled by the GC algorithm. For instance if you have a GC that compacts then by definition you cannot guarantee object relative layout. This object layout is critical in making sure that your traversal order is cache and pre-fetch friendly. AFAIK struts+arrays in C# are the only construct I've seen that lets you get close to explicitly control ordering of objects. In almost every other GC'd language you end up needing to use a giant byte array(hello emscripten!) in order to make those guarantees. If you work in that manner you're throwing away 90% of what makes the language useful and paying the cost of not working with the objects in their native form.
- pjmlp 11y ago> AFAIK struts+arrays in C# are the only construct I've seen that lets you get close to explicitly control ordering of objects. Check Mesa/Cedar, Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, D. All system programming languages with GC.
- vvanders 11y agoI knew I should have included the caveat of being widely available on many platforms with a rich library ecosystem :). I'm sure they fit the definition but I don't know that I'd want to use any in production aside from D. D is so similar to C++ I'd just rather use C++ instead since it's a bit more proven of a stack.
- pjmlp 11y agoExcept for D, those languages died because they were tied to OSes that didn't managed to jump into the mainstream, but they showed the way. The problem is to have an OS vendor that would care to bring those features back. So far I see it happening with Swift and C#, where Microsoft is slowly adding features from System C# used in project Midori. Will they kill C++? Surely not, but they might reduce the use cases one would use it for. For example, nowadays I don't write full stack applications in C++ any longer, I just use it for infrastructure code.
- vvanders 11y agoYup, that's totally fair. I'm a big fan of a solid C++ core + wrapper language that maps to the domain I'm in. Very common in the games space to see C# for all tooling/editor with the core engine in C++ for portability/performance.
- deleted 11y ago[deleted]
- pron 11y ago> For instance if you have a GC that compacts then by definition you cannot guarantee object relative layout. This object layout is critical in making sure that your traversal order is cache and pre-fetch friendly. You do that in GC and non-GC environments exactly the same way: by embedding your objects in arrays. > AFAIK struts+arrays in C# are the only construct I've seen that lets you get close to explicitly control ordering of objects. And Java's upcoming value types. > If you work in that manner you're throwing away 90% of what makes the language useful and paying the cost of not working with the objects in their native form. I disagree. Even without value types, working with byte buffers in Java may still be significantly less work than C++, depending on how much of your application requires this kind of work. And the GC saves you a lot of work when you deal with concurrent data structures. The main disadvantage (good) GCs have is their significant RAM overhead when good performance is required.
- vvanders 11y agoArrays work great for uniform objects(in languages that make guarantees about contiguity which Java doesn't). However once you have disparate types(which is very common) that falls apart. What happens if you have a string associated with an object that you don't want to cache miss on? I haven't seen a language that deals with that appropriately other than C/C++. Value types are nice in Java, when will we see them in production? We don't even have Java8 on Android yet so I probably won't be able to use them till ~4-5 years from now. Byte arrays may be less work but they still have problems, you'll pay the int->float cast costs for one, which can be non-trivial on some platforms. Also if you want to use Strings you end up allocating a new string on each access since Java doesn't have a nice way to wrap an immutable string(take a look at FlatBuffers if you want to see this in more detail). I think it's important to understand they we're talking about a specific set of areas that C++ excels in. There are certainly places where I think Java and other managed languages make sense but if I need to make performance guarantees I'd rather not shoe-horn in a GC'd language where proven stacks have been successful.
- pron 11y ago> What happens if you have a string associated with an object that you don't want to cache miss on? Then you embed the array of chars in the object, just like in C++. I don't see what having a GC has to do with it. As to embedding arrays in objects in Java, I think it's planned as part of the value-type project, but no prototype yet. I know John Rose (JVM architect) said that the two features they intend to address are arrays of structs and structs of arrays (but not buffers of structs of arrays). > you'll pay the int->float cast costs for one HotSpot should optimize it away (not sure about byte buffer usage, though). It sees an integer read and a cast to float, and reads directly into a floating-point register. > Java doesn't have a nice way to wrap an immutable string You mean mutable string? Well, there's the CharSequence interface that String and the mutable StringBuilder implement, but it's true that not many standard APIs accept a CharSequence. > I think it's important to understand they we're talking about a specific set of areas that C++ excels in. I agree. C/C++ is unparalleled for single-threaded traversals over encoded binary data (e.g. video encoding/decoding and other signal processing) and for performance-sensitive applications running in memory constrained environments . Managed runtimes even try to compete in those domains. In other cases, the extra performance you can squeeze out is too insignificant (and growing less significant with time) to justify the extra effort. And in some cases of growing importance (interesting multi-threading), C++ has to work really hard to even match GC-runtime environments. The real cost that is always paid is the significant RAM overhead. And BTW: Android isn't Java. It's compatibility with Java has always been very partial, and, of course, its development is not directed by the JCP.
- bassislife 11y ago> AFAIK struts+arrays in C# are the only construct I've seen or Go, especially with the value types. Now there is no automatic SoA/ AoS conversions but otherwise, you have full control over memory layout.
- fmstephe 11y agoGo supports this, I think. I am not quite sure what is meant by object relative layout. In Go: A struct is laid out as you declared it, with possible compiler added padding. A struct value field (not a pointer) in another struct is laid out contiguously in memory as you declared it. An array (or a slice) of values (no pointers) are laid out contiguously in memory. You can happily take pointers into any of these larger structures. If you had a data structure where you really wanted to control the layout, you can create a slab allocator as a big array of values, and take pointers into that array to allocate pieces of your data structure. I did this exact thing to write a red-black tree in Go. It is true that Go's GC isn't compacting. But it will be in the future (or it is planned to be). But, if I hadn't programmed in Go I would have agreed with your comment above.