Why are people using GC in this day and age for anything other than processing on fully-general graphs (where the tracing and auto collecting is genuinely helpful)? Literally everything else can be dealt with by using more flexible memory management strategies, that do not need a pre-allocated 10GB heap, and will not hog cpu in wasteful and unpredictable ways when memory utilization rises above a set percentage.
Because GCs offer the best balance between performance and productive, even when going with the reference counting algorithms path.
Except for the heroic efforts from the Rust community, linear types are far from general consumption for any kind of software development.
Plus, having GC does not preclude being able to stack allocate, keep data on manual memory segment, or even resort to manually manage memory in unsafe code blocks.
Examples of GC enabled languages with such features, Modula-3, Mesa/Cedar, Active Oberon, Nim, D, Eiffel, C#, F#, System C# (M#), Sing#, Swift, ParaSail, Chapel.
Eventually Java might get such capabilities if Panama and Valhalla actually end up being part of the official implementation.
Manual memory management is required for some critical code paths, but so is Assembly, both are niches, not something to spend 100% of our coding hours.
GC is an inherent part of many higher level languages/runtimes. Including Go, which is the main reference here, but also in .Net and Java runtimes. Yes, you could use a lower level language like C/C++, D, Rust etc to work around the issue in other ways, but that leaves a lot of productivity benefit higher level languages bring to the table.
I can't read the referenced twitch article from work so cannot comment. I'm also not sure of the practical loads and implementation details and am surprised that the Go GC was generally an issue to begin with.
I know I've purposely called GC for languages that use it for ETL jobs that run on shared servers to minimize memory usage before.
They are "obligate-GC" languages. You don't get a choice whether to rely on it.
It is fundamentally misleading to call C++ or Rust "lower-level" languages than Go or Java. (As it is, also, to say "C/C++".) Both Rust and C++ support much more powerful abstractions than either, making them markedly higher-level. That they also enable actually coding abstractions to manage resources (incidentally including memory resources) reduces neither their expressiveness nor the productivity of skilled programmers.
The point of Java and Go is that less-skilled programmers can use them to solve simpler problems more cheaply. Since most problems are simple, those languages have a secure place.
High-level and low-level are ill-defined and I prefer to stick to more precise language. Additionally, calling Rust high-level is inaccurate. It has high-level features, but the linear typing used by the borrowing system ultimately imposes cognitive overhead that does not exist in, say, OCaml. I think it’s also interesting to note that garbage collectors for Rust that function reasonably are still pretty experimental, with the most promising approach I’ve seen so far being withoutboats’s Shifgrethor (https://github.com/withoutboats/shifgrethor).
Haskell and Idris and the like (other languages with a type system in the calculus of constructions) inarguably support a higher level of abstraction than Rust does, and are also “GC-obligate” languages. So your example is something of a red herring. I could say the same about Kotlin and Swift and Scala, none of which really have a strong story for static memory safety like Rust has, though it’s being considered for Swift. The only language that is reasonably complete that I could think to compare it to is ATS, which is far more complex as a result.
> garbage collectors for Rust that function reasonably are still pretty experimental
You can also use something like https://github.com/artichoke/cactusref - which provides an equivalent of Rc<T> with nearly-seamless, timely detection and collection of deallocation cycles. This gives you the equivalent of full GC, but using a "zero-overhead" approach that integrates more cleanly with how Rust idiomatically works.
A cactusref is owned by a single thread so there's no STW issue, but you also can't share them mutably between threads like structures available in some GCed languages.
Lower-level meaning closer to the metal. Higher level would be further from the hardware, more abstracted. And in this context, it's more about the relativity to each other.
I wouldn't suggest that a given language favors more or less skilled programmers. There are plenty of skilled programmers that will choose a given language simply for the time to get things done. Not every problem needs absolute performance and memory scarcity, in fact I would suggest that most don't.
I've used some very low level languages as well as a bit of assembly in the past. All the same, JavaScript is the language I enjoy the most, simply because I can get things done in flexible ways, with many modules already written. There are times where you want absolute performance with minimal memory (embedded systems in particular, though even they're getting pretty powerful) and there are others where you can duct tape something together that only needs to run a couple times a day.
I've seen front end developers that couldn't handle conceptualizing SQL-style data storage... Likewise, I've seen backend developers unable to deal with breaking apart UI components or dealing with event based workflows or managing state outside a database context. I've seen systems developers create the most byzantine, overly complex and buggy systems you can imagine, that don't even work half the time. On the flip side, I've seen aircraft systems designed and built almost entirely in hardware... now some of that is truly impressive (and took years to design and develop, compared to weeks/months many developers will get).
Closer to when I was starting out, it was Visual Basic that was considered the proverbial whipping boy of "beginner" or "less skilled" languages. I've seen very good, and very bad implementations of a great many things in a great many languages over the past few decades. I'd say some of the worst of the worst code I've dealt with has come from the most arrogant people I've worked with. Generally, you aren't as smart or clever as you think you are. And I mean "you" in the colloquial sense. In the end, all anyone (or at least most people/users) really care about is it does the job, and is relatively easy to use.
There are other factors in engineering besides CPU. For many applications, CPU is the cheaper resource (e.g., compared to developer time / opportunity cost).