Remix.run Logo
rafaelmn 5 hours ago

IMHO D just missed the mark with the GC in core. It was released in a time where a replacement for C++ was sorely needed, and it tried to position itself as that (obvious from the name).

But by including the GC/runtime it went into a category with C# and Java which are much better options if you're fine with shipping a runtime and GC. Eventually Go showed up to crowd out this space even further.

Meanwhile in the C/C++ replacement camp there was nothing credible until Rust showed up, and nowadays I think Zig is what D wanted to be with more momentum behind it.

Still kind of salty about the directions they took because we could have had a viable C++ alternative way earlier - I remember getting excited about the language a lifetime ago :D

arcadia_leak 5 hours ago | parent | next [-]

I'd rather say that the GC is the superpower of the language. It allows you to quickly prototype without focusing too much on performance, but it also allows you to come back to the exact same piece of code and rewrite it using malloc at any time. C# or Java don't have this, nor can they compile C code and seamlessly interoperate with it — but in D, this is effortless.

Furthermore, if you dig deeper, you'll find that D offers far greater control over its garbage collector than any other high-level language, to the point that you can eagerly free chunks of allocated memory, minimizing or eliminating garbage collector stops where it matters.

ceteia 2 hours ago | parent | next [-]

Do you know of any popular real-time (for some definition of real-time) applications written in D? Like, streaming music or video? C has FFmpeg [0]:

> FFmpeg is proudly written in the C programming language for the highest performance. Other fashionable languages like C++, C#, Rust, Go etc do not meet the needs of FFmpeg.

How does D perform in benchmarks against other programming languages?

[0] https://www.linkedin.com/posts/ffmpeg_ffmpeg-is-proudly-writ...

arcadia_leak 2 hours ago | parent | next [-]

D by definition meets the FFmpeg's criteria because it's also a C compiler. Because of that I never wondered how D performs in the benchmarks, as I know for sure that it can give me the performance of C where I need it.

ceteia 38 minutes ago | parent [-]

But then, to use D for performance, would I then have to master both D, C and their interaction? That doesn't seem great. It's like having to learn 2 languages and also how they interact.

nicwilson 2 hours ago | parent | prev [-]

Sociomantic (bought by Dunhumby, now defunct IIRC) had a realtime advertisement business built in D.

Weka have a realtime distributed filesystem written in D, used for ML/HPC workloads.

ceteia 32 minutes ago | parent [-]

> Weka have a realtime distributed filesystem written in D, used for ML/HPC workloads.

This https://github.com/weka ?

Most of the D repositories appear to have very little activity. The Go repositories seem to have more activity.

rafaelmn 5 hours ago | parent | prev [-]

> C# or Java don't have this, nor can they compile C code and seamlessly interoperate with it — but in D, this is effortless.

C# C interop is pretty smooth, Java is a different story. The fact that C# is becoming the GC language in game dev is proving my point.

>Furthermore, if you dig deeper, you'll find that D offers far greater control over its garbage collector than any other high-level language, to the point that you can eagerly free chunks of allocated memory, minimizing or eliminating garbage collector stops where it matters.

Yes, and the no-gc stuff was just attempts to backpedal on the wrong initial decision to fit into the use-cases they should have targeted from the start in my opinion.

Look D was an OK language but it had no corporate backing and there was no case where it was "the only good solution". If it was an actual C++ modernization attempt that stayed C compatible it would have seen much better adoption.

arcadia_leak 5 hours ago | parent | next [-]

> C# C interop is pretty smooth

True, but you still need to either generate or manually write the bindings. In D, you just import the C headers directly without depending on the bindings' maintainers.

> If it was an actual C++ modernization attempt that stayed C compatible it would have seen much better

Any D compiler is literally also a C compiler. I sincerely don't know how can one be more C compatible than that.

> Yes, and the no-gc stuff was just attempts to backpedal on the wrong initial decision

I think that it was more of an attempt to appease folks who won't use GC even with a gun to their head.

rafaelmn 4 hours ago | parent [-]

I'm not saying D didn't have nice features - but if D/C#/Java are valid options I'm never picking D - language benefits cannot outweigh the ecosystem/support behind those two. Go picked a niche with backend plumbing and got Google backing to push it through.

Meanwhile look at how popular Zig is getting 2 decades later. Why is that not D ? D also has comp-time and had it for over a decade I think ? Zig proves there's a need that D was in the perfect spot to fill if it did not make the GC decision - and we could have had 2 decades of software written in D instead of C++ :)

arcadia_leak 4 hours ago | parent [-]

> D/C#/Java are valid options I'm never picking D

This is perfectly fair.

> D was in the perfect spot to fill if it did not make the GC decision

I just find it hard to believe that the GC is the one big wart that pushed everyone away from the language. To me, the GC combined with the full power of a systems language are the killer features that made me stick to D. The language is not perfect and has bad parts too, but I really don't see the GC as one of them.

cardanome an hour ago | parent | prev | next [-]

> The fact that C# is becoming the GC language in game dev is proving my point.

That is just the Unity effect. Godot adopted C# because they get paid to do so by Microsoft.

C# allows for far lees control over the garbage collection compared to D. The decision to use C# is partly responsible for the bad reputation of Unity games as it causes a lot of stutters when people are not very careful about how to manage the memory.

The creator of the Mono runtime actually calls using C# his Multi-million dollar mistake and instead works on swift bindings for Godot: https://www.youtube.com/watch?v=tzt36EGKEZo

arcadia_leak 4 hours ago | parent | prev | next [-]

> The fact that C# is becoming the GC language in game dev is proving my point.

Respectfully, it doesn't prove your point. Unity is a commercial product that employed C# because they could sell it easily, not because it's the best language for game dev.

Godot supports C# because Microsoft sponsored the maintainers precisely on that condition.

xigoi 3 hours ago | parent | prev [-]

> The fact that C# is becoming the GC language in game dev is proving my point.

Popularity is not proof of anything. C# is popular because it’s made by Microsoft and rode the OOP hype.

optionalsquid 4 hours ago | parent | prev | next [-]

My (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm.

Do you want GC? Great! Do not want GC? Well, you can turn it off, and lose access to most things. Do you want a borrow-checker? Great, D does that as well, though less wholeheartedly than Rust. Do you want a safer C/memory safety? There's the SafeD mode. And probably more that I forget.

I wonder if all these different (often incompatible) ways of using D ends up fragmenting the D ecosystem, and in turn make it that much harder for it to gain critical mass

cardanome an hour ago | parent | next [-]

> My (likely unfair) impression of D is that it feels a bit rudderless

The more positive phrasing would be that it is a very pragmatic language. And I really like this.

Currently opinionated langues are really in vogue. Yes they are easier to market but I have personally very soured on this approach now that I am a bit older.

There is not one right way to program. It is fun to use on opinionated language until you hit a problem that it doesn't cover very well and suddenly you are in a world of pain. I like languages that give me escape hatches. That allow me to program they way I want to.

DeathArrow 4 hours ago | parent | prev [-]

>My (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm.

My (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm.

Nim kind of does that, too.

cb321 3 hours ago | parent [-]

This can very clearly be said about C++ as well, which may have started out as C With Classes but became very kitchen sinky. Most things that get used accrete a lot of features over time, though.

FWIW, I think "standing out" due to paradigm commitment is mostly downstream of "xyz-purity => fewer ways to do things => have to think/work more within the constraints given". This then begs various other important questions, of course.. E.g., do said constraints actually buy users things of value overcoming their costs, and if so for what user subpopulations? Most adoption is just hype-driven, though. Not claiming you said otherwise, but I also don't think the kind of standing out you're talking about correlates so well to marketing. E.g., browsers marketed Javascript (which few praised for its PLang properties in early versions).

gorgonical 3 hours ago | parent | prev | next [-]

Re: the point about Zig: Especially considering I used and played a lot with D's BetterC model when I was a student, I wonder as a language designer what Walter thinks about the development and rise in popularity of Zig. Of course, thinking "strategically" about a language's adoption comes off as Machiavellian in a crowd of tinkers/engineers, but I can't help but wonder.

pron 3 hours ago | parent | prev | next [-]

> GC/runtime

1. Runtime: A runtime is any code that is not a direct result of compiling the program's code (i.e. it is used across different programs) that is linked, either statically or dynamically, into the executable. I remember that when I learnt C in the eighties, the book said that C isn't just a language but a rich runtime. Rust also has a rich runtime. It's true that you can write Rust in a mode without a runtime, but then you can barely even use strings, and most Rust programs use the runtime. What's different about Java (in the way it's most commonly used) isn't that it has a runtime, but that it relies on a JIT compiler included in the runtime. A JIT has pros and cons, but they're not a general feature of "a runtime".

2. GC: A garbage collector is any mechanism that automatically reuses a heap object's memory after it becomes unreachable. The two classic GC designs, reference counting and tracing, date back to the sixties, and have evolved in different ways. E.g. in the eighties and nineties there were GC designs where the compiler could either infer a non-escaping object's lifetime and statically insert a `free` or have the language track lifetimes ("regions", 1994) and have the compiler statically insert a `free` based on information annotated in the language. On the other hand, in the eighties Andrew Appel famously showed that moving tracing collectors "can be faster than stack allocation". So different GCs employ different combination of static inference and dynamic information on object reachability to optimise for different things, such as footprint or throughput. There are tradeoffs between having a GC or not, and they also exist between Rust (GC) and Zig (no GC), e.g. around arenas, but most tradeoffs are among the different GC algorithms. Java, Go, and Rust use very different GCs with different tradeoffs.

So the problem with using the terms "runtime" and "GC" colloquially as they're used today is not so much that it differs from the literature, but that it misses what the actual tradeoffs are. We can talk about the pros and cons of linking a runtime statically or dynamically, we can talk about the pros and cons of AOT vs. JIT compilation, and we can talk about the pros and cost of a refcounting/"static" GC algorithm vs a moving tracing algorithm, but talking in general about having a GC/runtime or not, even if these things mean something specific in the colloquial usage, is not very useful because it doesn't express the most relevant properties.

ceteia 3 hours ago | parent [-]

Does Rust really require reference counting? I thought Rust programs only used reference counting when types like Rc and Arc are used.

Swift seems to require reference counting significantly more than Rust.

brabel 3 hours ago | parent [-]

Op saying Rust has a kind of GC is absurd. Rust keeps track of the lifetime of variables and drops them at the end of their lifecycle. If you really want to call that a GC you should at least make a huge distinction that it works at compile time: the generated code will have drop calls inserted without any overhead at runtime. But no one calls that a GC.

You see OP is trying to murk the waters when they claim C has a runtime. While there is a tiny amount of truth to that, in the sense that there’s some code you don’t write present at runtime, if that’s how you define runtime the term loses all meaning since even Assemblers insert code you don’t have to write yourself, like keeping track of offsets and so on. Languages like Java and D have a runtime that include lots of things you don’t call yourself, like GC obviously, but also many stdlib functions that are needed and you can’t remove because it may be used internally. That’s a huge difference from inserting some code like Rust and C do. To be fair, D does let you remove the runtime or even replace it. But it’s not easy by any means.

pron 2 hours ago | parent [-]

> If you really want to call that a GC you should at least make a huge distinction that it works at compile time: the generated code will have drop calls inserted without any overhead at runtime. But no one calls that a GC.

Except for the memory management literature, because it's interested in the actual tradeoffs of memory management. A compiler inferring lifetimes, either automatically for some objects or for most objects based on language annotations, has been part of GC research for decades now.

The distinction of working at compile time or runtime is far from huge. Working at compile time reduces the work associated with modifying the counters in a refcounting GC in many situations, but the bigger differences are between optimising for footprint or for throughput. When you mathematically model the amount of CPU spent on memory management and the heap size as functions of the allocation rate and live set size (residency), the big differences are not whether calling `free` is determined statically or not.

So you can call that GC (as is done in academic memory management research) or not (as is done in colloquial use), but that's not where the main distinction is. A refcounting algorithm, like that found in Rust's (and C++'s) runtime is such a classic GC that not calling it a GC is just confusing.

ceteia 24 minutes ago | parent [-]

> A refcounting algorithm, like that found in Rust's (and C++'s) runtime is such a classic GC that not calling it a GC is just confusing.

But is it not easy to opt out of in C, C++, Zig and Rust, by simply not using the types that use reference counting?

And how does your performance analysis consider techniques like arenas and allocating at startup only?

Dwedit 3 hours ago | parent | prev | next [-]

Zig got too much in to avoiding "hidden behavior" that destructors and operator overloading were banned. Operator overloading is indeed a mess, but destructors are too useful. The only compromise for destructors was adding the "defer" feature. (Was there ever a corresponding "error if you don't defer" feature?)

fuhsnn 5 hours ago | parent | prev [-]

FIl-C, the new memory-safe C/C++ compiler actually achieved that through introducing a GC, with that in mind I'd say D was kind of a misunderstood prodigy in retrospect.

rafaelmn 5 hours ago | parent [-]

There's two classes of programs - stuff written in C for historic reasons that could have been written in higher level language but rewrite is too expensive - fill c. Stuff where you need low level - Rust/C++/Zig

brabel 2 hours ago | parent [-]

FillC works fine with all C code no matter how low level. There’s a small performance overhead but for almost every scenario it’s an acceptable overhead!