What's with the people who still use the term C/C++?
C++ and C are separate languages. I'd be grateful for the author to reflect it in the Readme.
Further, Bragging about LoC is bad. LoC is a poor measure of both quality and functionality.
"C/C++ - a mythical language referred to by people who cannot or do not want to recognize the magnitude of differences between the facilities offered by C and C++" -- Stroustrup
> C++ and C are separate languages. I'd be grateful for the author to reflect it in the Readme.
I agree, but we could honestly be as granular as we want here. We could ask the author to delineate between C99 and C11, but it ultimately doesn't really matter. The point of referring to "C/C++" is to cast a blanket statement over the traditional compiled mainstays and use them as a point of reference. While they are indeed different, they're more alike then they are dissimilar. I think the author is perfectly justified here.
> Further, Bragging about LoC is bad. LoC is a poor measure of both quality and functionality.
Rust is a language that is extremely verbose, and properly formatted Rust code often uses more lines than necessary to improve readability (expanding match arms, removing inlined if-statements, etc.). Hell, if you look at the repo, it looks almost identical to a default Rust project: src is clearly exposed at the root, and everything else is pretty well organized into distinct folders. I disagree with the first part of your statement ("Bragging about LoC is bad") but agree with the second part ("LoC is a poor measure of both quality and functionality.")
Honestly, I think LoC-shaming originated in languages like Java and Python, where more lines of code almost guaranteed more complexity. Rust's focus on zero cost abstraction ultimately means that even massive programs can run with minimal overhead. I'm not here to parade Rust's achievements in front of you, but I figured it was worth pointing out at least here.
> Honestly, I think LoC-shaming originated in languages like Java and Python, where more lines of code almost guaranteed more complexity. Rust's focus on zero cost abstraction ultimately means that even massive programs can run with minimal overhead.
Zero-cost abstractions are meant to be zero physical cost, not zero mental cost. LoC still translate to mental overhead and "LoC shaming" is appropriate for any language, not just verbose like Java or Python.
Well... the only language with true zero-cost abstractions is Lisp (assuming you call it a language, which it strictly isn't, but let's not go there right now).
The reason Lisp is zero cost is because what you write as data structure (the program IS a data structure) can be interpreted however you decide it to be interpreted. You can design any kind of abstraction you like and then separately completely control how that code is translated to binary.
For example, when you write a function call like printf("%d", 7) in C (forgetting built in optimization for printf...), the resulting binary has no other choice than to call printf function, parse "%d" and then conditionally read in argument and create a string.
On the other hand if C was Lisp it could, at the time of compilation, translate this code to invocation of putc('7') so that during normal execution the parsing of "%d" would never happen.
In C this requires compiler support. In Lisp you are compiler -- you decide what code is going to be generated.
Well, yes. In that case every abstraction costs because at the very least you need to develop it and it costs.
I think there are two major contributors to cost of abstraction.
#1 is performance. Does it add stuff that is not strictly necessary but is just side effect of abstraction mechanism? Does it affect memory layout to be less than ideal? Does it prevent generated code to be ideal?
#2 is leaks. Leaks are cost. Leak is when the user of abstraction needs to be aware of more details than just the official abstraction. For example, regular expression is a leaky abstraction because, except for simple regexes, you need to know a lot about actual implementation of the regex so that you understand how to write so that it does not require infinite memory and finishes before heat death of the Universe.
Traditionally, "zero-cost" refers to #1 and I think this is very useful definition.
It is difficult to impossible to prevent #2. Using #1 as definition of zero-cost describes tools with which you can use to create your solution without hampering your performance (significantly). These tools do not need to be simple or even intuitive (and Rust is neither).
There aren't many pairs of mainstream languages that really interoperate well together. C and C++ do, which can blur the lines a bit. Not sure if this is what the author meant.
With rust growing in popularity and good interoperability, I suspect we'll see the rise of projects written in C/Rust and C++/Rust, and maybe even C/C++/Rust. The line will obviously be more clear because of dramatically different syntax, packaging, build system, etc.
> In my opinion, debuggers are under-appreciated and under-invested tools in a programmer's arsenal.
Oh yeah - microsoft's time travelling debugger is under appreciated, even with their quality tooling.
But, it's on the windows platform. So anything like this on Linux sounds like a very positive step forward.
> So anything like this on Linux sounds like a very positive step forward.
GDB has had reverse debugging since 2009 and there are other tools like rr and a few commercial ones. If anything I'd say that you calling it time travel debugging instead of reverse debugging demonstrates how insular the windows developer world is more than the windows platform being ignored.
Time travel debugging is actually the more common historical term for the technology along with replay debugging specifically for the record-replay based variants. Reverse debugging as a term is really more of a GDB-ism and even there the term only really started gaining steam when rr produced a reasonable backend with GDB reverse debugging commands as a front-end. Also, frankly, the original GDB reverse debugging backend was entirely non-viable since it resulted in something like a 10,000x slowdown [2] during execution which made it essentially useless for anything other than actual toy problems. This is entirely an artifact of the implementation rather than any technology reason as most of the early solutions listed in [1] were somewhere between no slowdown for hardware-based solutions and 2x-100x for software based solutions.
Completely agree. At my current job I spent a lot of time in improving the developer tooling - step through debugging, live REPL, tracing, waterfalls, profiling, memory dumps. People are still not willing to spend the time to learn them and improve their workflows unless literally forced to do so.
The prevalent attitude is simply laziness manifested as "why do I need all these fancy tools when print('I am here!') works just fine?"
"Lack of garbage collection was a problem but runtimes are more troublesome...Linux signal handling becomes very complicated...Runtimes also often force layout of data structures be tuned to the needs of the garbage collector..."
That sums up my experience using a lot of higher-level languages. The pitch is always that language X should replace C because it's just as fast in most practical cases but much easier and safer. But the reason I use C is because of the pain of complex runtimes, especially when interoperating with other languages.
And that's also why I'm interested in Rust. It's the first high-level language (I use the term loosely) that doesn't interfere with anything you're trying to do. It can even do dynamic dispatch on ordinary pointers to structures with a C memory layout, because it doesn't add a vtable pointer to structs (like C++ does).
"I don't know much about dlang -- it could have been the best of both worlds"
Yeah, I skipped over dlang, too. And I don't have a good reason for that, aside from a lack of time to really explore both. I hope dlang keeps growing and eventually I'll look into what it has to offer.
Whenever you port a big program to another language it is important to be conservative, in my view. You don't want to make so many structural changes in the way things work in the original codebase while porting things over. You risk things becoming very confusing and the port could fail. In future iterations you could definitely make things more idiomatic in the target language.
As far as Rust is concerned, it does not have traditional OO features. But by using the Deref/DerefMut trait specifically and traits in general I was able to recover and mimic a lot of OO behaviors present in rr in rd.
The rd code may not always be beautiful.
FYI,
Rust had a GC also Classes in it's initial versions but they were removed for some reason!!!
Note that implementing Deref/DerefMut to mimic OOP is considered a bad practice. They were originally meant solely for smart pointer types, although some have opinions™ about that. Either way, you may need to reshape the way you think about program design coming from OOP languages - I know you've probably heard that before, but its true :) There are usually better options. Learning from FP pattern helps, as Rust leans more towards FP than OO in my opinion, although it has elements of both. Separating data and implementation (behavior) at the syntax level is one instance of that design decision showing through, no inheritance is another.
Ah, sorry, I didn't realize they were quotes from the post. (You generally put quotes in quotation marks or blockquotes "> ..." to distinguish). I guess the advice applies to anyone struggling with rust coming from an OOP background :)
> Yeah, I skipped over dlang, too. And I don't have a good reason for that, aside from a lack of time to really explore both. I hope dlang keeps growing and eventually I'll look into what it has to offer.
If you decide to have a look at what we have to offer, feel free to join our forums. The following discord server (https://discord.gg/bMZk9Q4) is also where you can find a bunch of other D employees (Mainly me at the moment), maintainers, users etc.
From the blog "Just like llvm facilitated the rise of hundreds of new computer languages, I forsee a similar rise for debugging and debuggers in the coming years."
But the author provides no evidence to support the claim. Why would the status quo change?
33 comments
[ 18.4 ms ] story [ 69.5 ms ] thread> However, does that mean that like LLVM we are forever stuck with C/C++ for a foundational piece of debugging software like rr?
> No. The rd port of rr to Rust is my attempt to change that inevitability
C++ and C are separate languages. I'd be grateful for the author to reflect it in the Readme.
Further, Bragging about LoC is bad. LoC is a poor measure of both quality and functionality.
"C/C++ - a mythical language referred to by people who cannot or do not want to recognize the magnitude of differences between the facilities offered by C and C++" -- Stroustrup
I agree, but we could honestly be as granular as we want here. We could ask the author to delineate between C99 and C11, but it ultimately doesn't really matter. The point of referring to "C/C++" is to cast a blanket statement over the traditional compiled mainstays and use them as a point of reference. While they are indeed different, they're more alike then they are dissimilar. I think the author is perfectly justified here.
> Further, Bragging about LoC is bad. LoC is a poor measure of both quality and functionality.
Rust is a language that is extremely verbose, and properly formatted Rust code often uses more lines than necessary to improve readability (expanding match arms, removing inlined if-statements, etc.). Hell, if you look at the repo, it looks almost identical to a default Rust project: src is clearly exposed at the root, and everything else is pretty well organized into distinct folders. I disagree with the first part of your statement ("Bragging about LoC is bad") but agree with the second part ("LoC is a poor measure of both quality and functionality.")
Honestly, I think LoC-shaming originated in languages like Java and Python, where more lines of code almost guaranteed more complexity. Rust's focus on zero cost abstraction ultimately means that even massive programs can run with minimal overhead. I'm not here to parade Rust's achievements in front of you, but I figured it was worth pointing out at least here.
Zero-cost abstractions are meant to be zero physical cost, not zero mental cost. LoC still translate to mental overhead and "LoC shaming" is appropriate for any language, not just verbose like Java or Python.
Chandler Carruth “There Are No Zero-cost Abstractions”
You can watch and see what they really are. I bet this is true for Rust as-well.
The reason Lisp is zero cost is because what you write as data structure (the program IS a data structure) can be interpreted however you decide it to be interpreted. You can design any kind of abstraction you like and then separately completely control how that code is translated to binary.
For example, when you write a function call like printf("%d", 7) in C (forgetting built in optimization for printf...), the resulting binary has no other choice than to call printf function, parse "%d" and then conditionally read in argument and create a string.
On the other hand if C was Lisp it could, at the time of compilation, translate this code to invocation of putc('7') so that during normal execution the parsing of "%d" would never happen.
In C this requires compiler support. In Lisp you are compiler -- you decide what code is going to be generated.
I think there are two major contributors to cost of abstraction.
#1 is performance. Does it add stuff that is not strictly necessary but is just side effect of abstraction mechanism? Does it affect memory layout to be less than ideal? Does it prevent generated code to be ideal?
#2 is leaks. Leaks are cost. Leak is when the user of abstraction needs to be aware of more details than just the official abstraction. For example, regular expression is a leaky abstraction because, except for simple regexes, you need to know a lot about actual implementation of the regex so that you understand how to write so that it does not require infinite memory and finishes before heat death of the Universe.
Traditionally, "zero-cost" refers to #1 and I think this is very useful definition.
It is difficult to impossible to prevent #2. Using #1 as definition of zero-cost describes tools with which you can use to create your solution without hampering your performance (significantly). These tools do not need to be simple or even intuitive (and Rust is neither).
It is not a measure of quality but rather size of the project.
With rust growing in popularity and good interoperability, I suspect we'll see the rise of projects written in C/Rust and C++/Rust, and maybe even C/C++/Rust. The line will obviously be more clear because of dramatically different syntax, packaging, build system, etc.
Oh yeah - microsoft's time travelling debugger is under appreciated, even with their quality tooling. But, it's on the windows platform. So anything like this on Linux sounds like a very positive step forward.
GDB has had reverse debugging since 2009 and there are other tools like rr and a few commercial ones. If anything I'd say that you calling it time travel debugging instead of reverse debugging demonstrates how insular the windows developer world is more than the windows platform being ignored.
A great demonstration is in the video "Give Me 15 minutes and I'll change your view of GDB": https://www.youtube.com/watch?v=PorfLSr3DDI
[1] http://jakob.engbloms.se/archives/1564
[2] https://undo.io/resources/6-things-time-travel-debugging/
The prevalent attitude is simply laziness manifested as "why do I need all these fancy tools when print('I am here!') works just fine?"
"Lack of garbage collection was a problem but runtimes are more troublesome...Linux signal handling becomes very complicated...Runtimes also often force layout of data structures be tuned to the needs of the garbage collector..."
https://github.com/sidkshatriya/me/blob/master/002-why-rust....
That sums up my experience using a lot of higher-level languages. The pitch is always that language X should replace C because it's just as fast in most practical cases but much easier and safer. But the reason I use C is because of the pain of complex runtimes, especially when interoperating with other languages.
And that's also why I'm interested in Rust. It's the first high-level language (I use the term loosely) that doesn't interfere with anything you're trying to do. It can even do dynamic dispatch on ordinary pointers to structures with a C memory layout, because it doesn't add a vtable pointer to structs (like C++ does).
"I don't know much about dlang -- it could have been the best of both worlds"
Yeah, I skipped over dlang, too. And I don't have a good reason for that, aside from a lack of time to really explore both. I hope dlang keeps growing and eventually I'll look into what it has to offer.
"Lack of Object-Orientation was a concern"
Whenever you port a big program to another language it is important to be conservative, in my view. You don't want to make so many structural changes in the way things work in the original codebase while porting things over. You risk things becoming very confusing and the port could fail. In future iterations you could definitely make things more idiomatic in the target language.
As far as Rust is concerned, it does not have traditional OO features. But by using the Deref/DerefMut trait specifically and traits in general I was able to recover and mimic a lot of OO behaviors present in rr in rd.
The rd code may not always be beautiful.
FYI,
Rust had a GC also Classes in it's initial versions but they were removed for some reason!!!
Either be very conservative or just tear things up. I think the middle ground is the worst, where you can't decide whether it's a rewrite or a port.
These sentences direct copy paste from Author post, but I agree that Rust leans more towards to FP. The creator labeled Rust as Linear FP language.
If you decide to have a look at what we have to offer, feel free to join our forums. The following discord server (https://discord.gg/bMZk9Q4) is also where you can find a bunch of other D employees (Mainly me at the moment), maintainers, users etc.
But the author provides no evidence to support the claim. Why would the status quo change?