[HN Gopher] Speeding up the Rust edit-build-run cycle
       ___________________________________________________________________
        
       Speeding up the Rust edit-build-run cycle
        
       Author : tempaccount420
       Score  : 83 points
       Date   : 2024-11-14 19:30 UTC (3 hours ago)
        
 (HTM) web link (davidlattimore.github.io)
 (TXT) w3m dump (davidlattimore.github.io)
        
       | renewiltord wrote:
       | Good set of tips. Thank you.
        
         | Comma2976 wrote:
         | It was my pleasure.
        
       | omani wrote:
       | thanks
        
         | Comma2976 wrote:
         | You're welcome
        
       | nuudlman wrote:
       | Not linking debug info must be some kind of sick joke. What is
       | the point of a debug build without symbols?
        
         | 0x457 wrote:
         | Enable them when you need to debug. This is for speeding up
         | "edit-build-run" workflows.
        
           | nuudlman wrote:
           | It's a lot faster to add a log point in a debugger than to
           | add a print statement and recompile. Especially with cargo
           | check, I really don't see the point of non-debuggable builds
           | (outside of embedded, but the size of debuginfo already makes
           | that a non-starter).
        
         | RichardLake wrote:
         | Doesn't rust have overflow checks in debug and skips them in
         | release?
        
           | 0x457 wrote:
           | Rust has compiled time overflow checks enabled by default in
           | any profile. Runtime overflow checks are disabled by default
           | in release profile.
        
         | vbezhenar wrote:
         | 1. Skipping some optimizations to build faster.
         | 
         | 2. Conditionally compiling some code like logging (not sure if
         | matters for typical Rust projects, but for embedded C projects
         | it's typical).
         | 
         | 3. Conditionally compiling assertions to catch more bugs.
         | 
         | I'm using logs, because debugger breaks hardware. Very rarely
         | do I need to reach debugger. Even when hard exception occurs,
         | usually enough info is logged to find out the root cause of the
         | bug.
        
           | vlovich123 wrote:
           | > because debugger breaks hardware
           | 
           | What? Seems like you're talking about embedded but I've done
           | a lot of embedded projects in my time and I've never had a
           | debugger that breaks the HW.
        
             | viraptor wrote:
             | Depends what you're working on. Stopped in an unfortunate
             | place? That one element didn't get turned off and burned
             | out. Or the motor didn't stop. Or the crucial interrupts
             | got missed and your state is now reset. Or...
        
               | bippihippi1 wrote:
               | are there debugging tools specifically for situations
               | like that? do you just write code to test manually? How
               | do you ensure dev builds don't break stuff like that even
               | without considering debugging?
        
               | rcxdude wrote:
               | The most useful tool is a full tracing system (basically
               | a stream of run instructions you can use to trace the
               | execution of the code without interrupting it), but
               | unfortunately they're quite expensive and proprietery,
               | and require extra connections to the systems that do
               | support them, so they're not particularly commonly used.
               | Most people just use some kind of home-grown
               | logging/tracing system that tracks the particular state
               | they're interested in, possibly logged into a ringbuffer
               | which can be dumped when triggered by some event.
        
             | bsder wrote:
             | On embedded, debuggers almost never work until you get to
             | really expensive ones.
             | 
             | In addition, debuggers tend to obscure the failure because
             | they turn on all the hardware which tends to make bugs go
             | away if they are related to power modes.
             | 
             | One of my "best" debuggers for embedded was putting an
             | interactive interpreter over a serial interface on an
             | interrupt so I could query the state of things when a
             | device woke up even if it was hung--effectively a run time
             | injectable "printf".
             | 
             | Crude, but it could trace down obscure bugs that were rare
             | because the device would stay in the failure mode.
             | 
             | The bigeest problem was maintaining the database of code so
             | that we knew _exactly_ what build was on a device. We had
             | to hash and track _the universe_.
        
       | ryangs wrote:
       | >Debug information tends to be large and linking it slows down
       | linking quite considerably. If you're like many developers and
       | you generally use println for debugging and rarely or never use
       | an actual debugger, then this is wasted time.
       | 
       | Interesting. Is this true? In my work (java/kotlin, primarily in
       | app code on a server, occasional postgres or frontend js/react
       | stuff), I'm almost always reaching for a debugger as an
       | enormously more powerful tool than println debugging. My tests
       | are essentially the println, and if they fail for any interesting
       | reason I'll want the debugger.
        
         | Aurornis wrote:
         | println debugging is where everyone starts. Some people never
         | graduate to knowing how to use a debugger.
         | 
         | Debugging through log data still has a place, of course.
         | However, trying to do all of your debugging through println is
         | so much harder, even though it feels easier than learning to
         | use a debugger.
        
           | 0x457 wrote:
           | To be fair, if your code is multithreaded and sensitive to
           | pauses, it becomes harder to debug with a debugger.
           | 
           | Ultimately, if you have a good logging setup and kinda know
           | where the issue is a quick log message could be faster than
           | debugging if all you want to do is look a variable value.
        
             | pjmlp wrote:
             | That is where OS tracing like DTrace and ETW come into
             | play, which can then be loaded into a debugging session.
        
           | stouset wrote:
           | I am comfortable using a debugger, but println debugging is
           | easy, fast, and disproportionately effective for most of my
           | debugging in practice.
           | 
           | I reach for a "real" debugger when necessary, but that's less
           | than 5% of the time.
        
         | bluGill wrote:
         | Depends on the developer. in the Practice of Programming
         | https://en.m.wikipedia.org/wiki/The_Practice_of_Programming by
         | Brian W. Kernighan and Rob Pike they say they use debuggers
         | only to get a stack trace from a core dump and use printf for
         | everything else. You can disagree but those are known very good
         | programmers.
        
           | dgfitz wrote:
           | What if the program doesn't crash? It just black-boxes the
           | data incorrectly? I can find that error infinitely faster
           | with a debugger.
        
             | bluGill wrote:
             | They use printf. Which they claim is faster.
        
               | dgfitz wrote:
               | I'm not against printf at all, my lifetime commit history
               | is evidence of that. Do you also think that in the case
               | of a coredump not existing, that printf is faster?
               | Sincere question. I'm having an internal argument with
               | myself about it at the moment and some outside
               | perspective would be most welcome.
        
               | ehaliewicz2 wrote:
               | printf isn't faster if you want to single step through
               | code to find math precision errors.
               | 
               | I've had to do that on a system that didn't support
               | debugging. It was hell.
        
             | grey-area wrote:
             | Your existing logs will tell you roughly where and you just
             | insert some more log lines to check the state of the data.
             | 
             | Depends how fast your build/run cycle is and how many
             | different prcocesses/threads whether a debugger will be
             | faster/easier but a lot of it just comes down to
             | preference. Most time spent debugging for me at least is
             | spent thinking about the probable cause then choosing what
             | state to look at.
        
             | dietr1ch wrote:
             | Printf debugging excels on environments where there's
             | already good logging. Here I just need to pinpoint where in
             | my logs things have already gone wrong and work my way
             | backwards a bit.
             | 
             | You could do the same with a debugger setting up a
             | breakpoint, but the logs can better surface key
             | application-level decisions made in the process to get to
             | the current bad state.
             | 
             | On a debugger I need to wind back on all functions, which
             | it might get awful as some of them might be likely correct
             | library calls that you need to skip over when going back in
             | time, but that will take a huge portion of the functions
             | called before the breakpoint. I don't think it's impossible
             | to do with a debugger, but logging sort of bypasses the
             | process of telling the debugger what's relevant so it can
             | hide the rest, and it might already be in your codebase,
             | but there's no equivalent annotations already there in the
             | code to help the debugger understand what's important.
             | 
             | To me printf helps surfacing the relevant application-level
             | process to get to a broken state, and debuggers help
             | understand hairy situations where things have gone wrong at
             | a lower level, say missing fields or memory corruption, but
             | these days with safer languages lower level issues should
             | be way less frequent.
             | 
             | ---
             | 
             | On a side-note, it doesn't help debuggers that going back
             | in time was really hard with variable-length instructions.
             | I might be wrong here, but it took a while until `rr` came
             | out.
             | 
             | I do think that complexities like that resulted in spending
             | too much time dealing with hairy details instead of
             | improving the UI for debugging.
        
           | canucker2016 wrote:
           | But what source code debuggers did they have available?
           | 
           | Other than gdb, I can't name any Unix C source code
           | debuggers. I believe they were working on Unix before GDB was
           | created (wikipedia says gdb was created in 1986 -
           | https://en.wikipedia.org/wiki/Gdb).
           | 
           | Plan 9 has acid, but from the man page and english manual,
           | the debugger is closer to cli/tui than gui.
           | 
           | see https://9fans.github.io/plan9port/man/man1/acid.html and
           | https://plan9.io/sys/doc/acid.html
        
         | fiedzia wrote:
         | Debugging in Rust is substantially less common for me (and
         | probably not only for me) because it is less often needed and
         | more difficult - many things that are accessible in interpreted
         | world don't exist in native binary.
         | 
         | I do care about usable tracebacks in error reports though.
        
         | Animats wrote:
         | The only time I use a debugger with Rust is when unsafe code in
         | some library crate messes up. My own code has no "unsafe". I
         | have debug symbols on and a panic catcher that displays a
         | backtrace in a popup window. That covers most cases.
         | 
         | Rust development is mostly fixing compile errors, anyway. Once
         | it compiles, it often works the first time. What matters is
         | compile time for error compiles, which is pretty good.
         | 
         | Incremental compile time for my metaverse client is 1 minute 8
         | seconds in release mode. That's OK. Takes longer to test a new
         | version.
        
         | toast0 wrote:
         | I trained in the cout school of debugging. I can use a
         | debugger, and sometimes do, but it's really hard to use a
         | debugger effectively when you're also dealing with concurrency
         | and network clients. Maybe one day, I'll learn how to use one
         | of the time traveling debuggers and then I can record the
         | problem and then step through it to debug it.
        
         | dgunay wrote:
         | I use the debugger fairly regularly, though for me I'm on a
         | stack where friction is minimal. In Go w/ VS Code, you can just
         | write a test, set your breakpoints, hit "debug test", and
         | you're in there in probably less than 20 seconds.
         | 
         | I am like you though, I don't typically resort to it
         | immediately if I think I can figure out the problem with a
         | quick log. And the times where I've not had access to a
         | debugger with good UX, this tipping point can get pushed quite
         | far out.
        
         | jesse__ wrote:
         | I came here to write exactly this .. if I was drinking
         | something I would have spit it everywhere laughing when I read
         | it.
         | 
         | I guess 'many developers' here probably refers to web
         | developers who don't use the debugger, cause it's mostly
         | useless/perpetually broken in JS land ..? I rely heavily on the
         | debugger; can't imagine how people work without one.
        
           | bippihippi1 wrote:
           | when you write async JS code the debugger essentially adds no
           | value over printing
        
         | eminence32 wrote:
         | In my experience Java debuggers are exceptionally powerful,
         | much more so than what I've seen from C/C++/Rust debuggers.
         | 
         | If I'm debugging some complicated TomEE application that might
         | take 2 minutes to start up, then I'm absolutely reaching to an
         | IntelliJ debugger as one of my first tools.
         | 
         | If I'm debugging some small command line application in Rust
         | that will take 100ms to exhibit the failure mode, there's a
         | very good chance that adding a println debug statement is what
         | I'll try first
        
           | freeone3000 wrote:
           | CLion adds the power of IntelliJ debuggers to Rust. It works
           | _exceptionally_ well.
        
       | Aurornis wrote:
       | > If you're like many developers and you generally use println
       | for debugging and rarely or never use an actual debugger
       | 
       | You lost me here.
       | 
       | Using a debugger to step through the code is a huge timesaver.
       | 
       | Inserting println statements, compiling, running, inserting more
       | println, and repeating is very inefficient.
       | 
       | If you learn to use a debugger, set breakpoints, and step through
       | code examining values while you go then the 8 seconds spent
       | compiling isn't an issue.
        
         | Ar-Curunir wrote:
         | Just ignore that part then? You don't have to stop reading the
         | rest of the (very good) article lol.
        
         | sunshowers wrote:
         | Step through debuggers and tracers are two different dimensions
         | of debugging, and not directly comparable.
        
         | fmbb wrote:
         | > Inserting println statements, compiling, running, inserting
         | more println, and repeating is very inefficient.
         | 
         | That all depends on how long it takes to compile and run.
         | 
         | > If you learn to use a debugger, set breakpoints, and step
         | through code examining values while you go then the 8 seconds
         | spent compiling isn't an issue.
         | 
         | Meh, it's fine.
         | 
         | You still have to set new ones and re-run your code to trigger
         | the reproduction iteratively if you don't know where anything
         | is wrong.
         | 
         | Clicking "add logging break point here" and adding a print
         | statement is really not very different. In my experience the
         | hard part is know where you want to look. Stepping through all
         | your code line by line and looking at all values every step is
         | not a quick way to do anything. You have to divide and conquer
         | your debugging smartly, like a binary search all over your call
         | sites in the huge tree-walk that is your program.
        
           | forrestthewoods wrote:
           | Stepping through code and adding breakpoints is a spectacular
           | way to figure out where to put log statements. Modern code is
           | so abstract that it's nigh impossible to figure out what the
           | fuck function even gets called just from looking at code.
        
         | saurik wrote:
         | Engh... I used to rely on a debugger a lot 25 years ago when I
         | was learning to program, and was extremely good at making it
         | work and using its quirks; but, I was building overly-
         | simplistic software, and it feels so rare of a thing to be
         | useful anymore. The serious code I now find myself actually
         | ever needing to debug, with multiple threads written in
         | multiple languages all linked together--code which is often
         | performance sensitive and even often involves networked
         | services / inter-process communication--just isn't compatible
         | with interactive debugging.
         | 
         | So like, sure: if I have some trivial one-off analysis tool I
         | am building for which I am running into some issue I could
         | figure out how to debug it, but even then I am going to have to
         | figure out yet another debugging environment for yet another
         | language, and also of course surmount the hassle of a ton of
         | ensuring that sufficient debugging information is available and
         | I'm running a build that is somehow not optimized enough for
         | debugging and yet also not so slow that I'm gouging my eyes
         | out, I _could_ use a debugger, but I 'd rather sit and stare at
         | the code longer than start arguing with a debugger.
        
         | bluGill wrote:
         | Is it really saving time or are you not thinking enough about
         | what is wrong until you stumble on an answer? I can't answer
         | for you but I find that the forced wait for build also forces
         | me to think and so I find the problem faster. It feels slower
         | though but the clock is the real measure.
        
           | unclad5968 wrote:
           | It's one click to set the breakpoint in the ide or one line
           | if you're using gdb from the command line. I'm not sure how
           | printf debugging could be quicker even if you didn't have to
           | rebuild. Having done both, I'd take the debugger any day.
        
           | ehaliewicz2 wrote:
           | I find this line of argument odd. A debugger helps you
           | understand what your code is _actually_ doing, while your
           | brain is flawed and makes flawed assumptions. Regardless of
           | who you are, it 's unlikely you will be manually evaluating
           | code in your head as accurately as gdb (or whatever debugger
           | you use).
           | 
           | I think a lot of linux/mac folks tend to printf debug, while
           | windows folks tend to use a debugger, and I suspect it is a
           | culture based choice that is justified post hoc..
           | 
           | However, few things have been better for my code than
           | stepping through anything complex at least once before I move
           | on (I used to almost exclusively use printf debugging).
        
         | cmontella wrote:
         | Trace debugging can be inefficient, but it's also highly
         | effective, portable between all languages, and requires no
         | additional tooling. Hard to beat that combo.
        
       | tel wrote:
       | Just my lack of experience here, but I'm trying to verify I'm
       | successfully using sold. The mold linker claims it leaves
       | metadata in the .comment section, but on mach-o does that exist?
       | Is there a similar evaluation command using objdump as the mold
       | readelf command?
        
       | James_K wrote:
       | Surely it would be better to use a debugger and avoid recompiling
       | your code for the added print statements than to strip out the
       | debug information to decrease build times.
        
         | evrimoztamur wrote:
         | I build wasm as a target and this is sadly not an option, I
         | have to rebuild for each little bit. I will be trying a
         | different linker and see how it goes though!
        
       | khuey wrote:
       | split-debuginfo = "unpacked" (-gsplit-dwarf for C/C++) is the
       | way. Your tools (debuggers, profilers, etc) _probably_ support it
       | by now.
        
       | sendomatic wrote:
       | There are a lot of different t views on debugging with a debugger
       | vs print statements and what works better. This often seems to be
       | based on user preference and familiarity. One thing that I
       | haven't seen mentioned is for issues with dependencies. Setting
       | up a path dep in rust or fetching the code in whatever language
       | you're using for your project usually takes more time than simply
       | adding some breakpoints in the library code.
        
       | zerd wrote:
       | This post is from February, any interesting changes/improvements
       | since then? Progress on "wild"?
        
       ___________________________________________________________________
       (page generated 2024-11-14 23:01 UTC)