# Feedback request: Performance improvements from reducing debug info

**URL:** <https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825>\
**Category:** Uncategorized\
**Created:** [November 5, 2024, 4:20pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825 "2024-11-05T16:20:29Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [November 5, 2024, 4:20pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/1 "2024-11-05T16:20:29Z")

</div>

There are many potential improvements we could make for build times. In the course of evaluating possibilities, we'd like to know how much impact debug information has on build time.

Could people provide feedback on the build time differences in their projects between the default `dev` profile configuration and with the following added?

```toml
[profile.dev]
debug = "line-tables-only"

```

Ideally, we'd love to get the performance delta for a couple of cases:

- A clean `cargo build` after `cargo clean`.
- After doing `cargo build`, using `touch` on your `lib.rs` or `main.rs`, and then doing `cargo build` again.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [November 5, 2024, 5:00pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/2 "2024-11-05T17:00:52Z")

</div>

I tried my Project Euler solutions with 340 binaries (for each I've solved) and 70 dependencies. This is potentially heavy as it involves lots of linking with debuginfo, but they're also pretty small.

- With the default profile, `cargo build` took 23.34s; after touching `lib.rs`, it took 11.17s.
- With "line-tables-only", `cargo build` took 20.84s; after touching `lib.rs`, it took 10.00s.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [November 5, 2024, 6:07pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/3 "2024-11-05T18:07:06Z")

</div>

For one of my projects, a clean default `dev` profile gives:

```
Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 12s

```

A clean `debug = "line-tables-only"` build:

```
Finished `dev` profile [unoptimized + debuginfo] target(s) in 5m 02s

```

With the default profile, after touching `main.rs`/`lib.rs`:

```
Finished `dev` profile [unoptimized + debuginfo] target(s) in 16.59s

```

With `debug = "line-tables-only"`, after touching `main.rs`/`lib.rs`:

```
Finished `dev` profile [unoptimized + debuginfo] target(s) in 14.21s

```

---

<div class="post-metadata">

**Author:** ![rikyborg](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rikyborg/32/12149_2.png) [@rikyborg](https://internals.rust-lang.org/u/rikyborg)\
**Post date:** [November 6, 2024, 7:45am UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/4 "2024-11-06T07:45:24Z")

</div>

- default profile:
  - `cargo clean` then `cargo build`: 7.36s
  - `touch main.rs` then `cargo build`: 1.09s

- with `debug = "line-tables-only"`:
  - `cargo clean` then `cargo build`: 6.62s
  - `touch main.rs` then `cargo build`: 0.86s

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [November 6, 2024, 4:15pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/5 "2024-11-06T16:15:44Z")

</div>

It would perhaps also worth including times for `split-debuginfo` which could presumably impact link times?

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [November 6, 2024, 4:42pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/6 "2024-11-06T16:42:11Z")

</div>

There are also other factors to consider such as the linker used and the OS

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [November 6, 2024, 4:43pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/7 "2024-11-06T16:43:28Z")

</div>

Better linkers can make this _better_, but it still takes time to do the work.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [November 6, 2024, 7:48pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/8 "2024-11-06T19:48:45Z")

</div>

I mean if commenters here posted those tidbits (os, linker, split debuginfo) it could provide more context in case there are discrepancies in their numbers.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [November 7, 2024, 11:24am UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/9 "2024-11-07T11:24:59Z")

</div>

Testing on Fedora 40 x86\_64.

### Default `dev` profile:

Post `cargo clean`: `cargo build 385.75s user 34.70s system 599% cpu 1:10.08 total`

After touching `main.rs`: `cargo build 3.91s user 1.23s system 99% cpu 5.151 total`

### With `debug = "line-tables-only"`

Post `cargo clean`: `cargo build 353.69s user 34.42s system 619% cpu 1:02.62 total`

After touching `main.rs`: `cargo build 2.86s user 1.02s system 99% cpu 3.881 total`

---

<div class="post-metadata">

**Author:** ![pacak](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pacak/32/11934_2.png) [@pacak](https://internals.rust-lang.org/u/pacak)\
**Post date:** [November 7, 2024, 9:45pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/10 "2024-11-07T21:45:38Z")

</div>

ubuntu + mold

Less chonky executable, default profile clean build followed by touch on `lib.rs` and one more build

```rust
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 57s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.16s

```

Same, but with `line-tables-only`

```rust
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 46s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.80s

```

More chonky executable, all 4 cases

```rust
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 22s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.68s

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 03s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.29s

```

---

<div class="post-metadata">

**Author:** ![davidlattimore](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/davidlattimore/32/5141_2.png) [@davidlattimore](https://internals.rust-lang.org/u/davidlattimore)\
**Post date:** [November 16, 2024, 4:02am UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/11 "2024-11-16T04:02:20Z")

</div>

Ubuntu-based with Wild as the linker

Smallish build (10MiB binary):

```rust
default cold: 22.49s
line-tables cold: 20.78s
debug=0 cold: 19.66s

default warm: 0.24s
line-tables warm: 0.20s
debug=0 warm: 0.18s

```

Larger build (several binaries around 450MiB each):

```rust
default cold: 4m 51s
line-tables cold: 3m 46s
debug=0 cold: 3m 16s

default warm: 4.48s
line-tables warm: 2.28s
debug=0 warm: 1.63s

```

I recently ran an informal survey about [whether people regularly use a debugger](https://mas.to/@davidlattimore/113484821980790635). Of the 89 responses, 18% say they sometimes or always use a debugger while 82% say they rarely or never use a debugger. This seems consistent with what I've observed from talking to rustaceans in person.

I'm definitely supportive of any change to reduce the debug info for a default build.

I think that line number information in backtraces is less important now that it used to be and the reason is `#[track_caller]`. Generally the line that I care about when I get a backtrace is the line that called unwrap, expect, panic etc and these days that line is reported whether or not you have line debug info. So personally, I set `debug=0`, but I can understand that's likely a step too far for the default - just changing to `line-tables` by default would be great.

---

<div class="post-metadata">

**Author:** ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)\
**Post date:** [December 20, 2024, 9:15pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/12 "2024-12-20T21:15:55Z")

</div>

Does `line-tables-only` debug information still provide enough detail that GDB's `bt` command (or equivalent in your favorite debugger) can print the values of function arguments? I would really miss that if it went away by default.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [May 20, 2025, 1:59pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/13 "2025-05-20T13:59:59Z")

</div>

If we decide to focus the `dev` profile on check/test iteration time, how do we do it without negatively impacting people using a debugger?

Challenges:

- profiles operate on the workspace level
- `dev` profile uses the `debug` target dir
- you cannot have a built-in profile inherit from another

Some tools we have for evolving this include:

- We could add a `build.profile` to override the default profile
- We could add workspace editions to evolve profiles
  - How do different editions at the workspace and package level mix?
  - What is the behavior like on publish/vendor?
  - How does a workspace edition interact with inheriting an edition?
  - Some things we do with editions may not be able to be warned about / migrated

- We can split `dev` / `debug` profiles
  - `debug` profile name is reserved

- We can add `cargo::` prefixed profiles that are the true built-in profiles and immutable, relaxing the constraints on root level profiles

## Example Solutions

### Change `dev` profile

`dev` has the following changes:

```diff
[profile.dev]
-opt-level = 0
+opt-level = 1
-debug = true
+debug = "line-tables-only"
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false

```

Benefits

- `cargo test` is sped up

Downsides

- Users have to go out of their way to setup debugging

### Split the `dev` / `debug` profiles + override the default profile

Changes:

- The current `dev` profile settings are mirrored over into `debug`.
- `dev` becomes the profile shown earlier, in the `dev` directory
- `dev` profile remains the default
- We add `build.profile` to allow a user or IDE to set `debug` as the default

Open question:

- Do we add a `--dev` flag or tell people to use `--profile dev`?

Benefits

- `cargo test` is sped up

Downsides

- Anyone doing a `cargo build` and looking in `target/debug` will be broken.
- Debugging requires a manual rebuild or to change the config

Variants:

- We split the profiles on the next edition (requires workspace editions)
- `debug` becomes the default profile (`build.profile`), maybe changing to `dev` on the next edition (requires workspace editions)
  - But artifact location changes on `cargo build --profile dev` from `target/debug` to `target/dev`

- We add `cargo::*` profiles so people can more easily make `dev` and `debug` whatever they want (e.g. `dev` inheriting from `cargo::debug`)

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [May 20, 2025, 3:33pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/14 "2025-05-20T15:33:40Z")

</div>

> [@zackw](#):
>
> Does `line-tables-only` debug information still provide enough detail that GDB's `bt` command (or equivalent in your favorite debugger) can print the values of function arguments?

No, only `-Cdebuginfo=2` emits the necessary information for that.

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [May 20, 2025, 3:36pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/15 "2025-05-20T15:36:13Z")

</div>

> [@epage](#):
>
> ```rust
> -opt-level = 0
> +opt-level = 1
> 
> ```

I think this will only be a net win when tests are taking a non-trivial amount of time already. If you only got a couple of tests or are only doing say `cargo run` for a web server that starts up instantly, it would likely only slow down things.

---

<div class="post-metadata">

**Author:** ![SciMind2460](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scimind2460/32/13125_2.png) [@SciMind2460](https://internals.rust-lang.org/u/SciMind2460)\
**Post date:** [May 20, 2025, 3:37pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/16 "2025-05-20T15:37:01Z")

</div>

My performances:

- normal `dev` profile: 14.30 secs
- with `line-tables-only`: 12.38 secs

I can't access `touch` as I am on windows ☹

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [May 20, 2025, 4:22pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/17 "2025-05-20T16:22:15Z")

</div>

> [@bjorn3](#):
>
> I think this will only be a net win when tests are taking a non-trivial amount of time already.

I wonder if it would be feasible to provide automatic tuning. Imagine if `cargo test` would:

- Measure both the compile time and the test run time, and remember this over multiple sessions.
- If historical run time is high relative to compile time, run an experiment (with a note to the user that this is happening): switch to `opt-level = 1`.
- Based on the results of the experiment, decide whether to keep it — and maybe suggest to the user to configure `[profile.dev]`.

The biggest problem with this would be that it triggers a rebuild of all dependencies, which is a potentially large interruption. This would be less of a problem if the default dev profile always compiled dependencies with more optimization, so only the workspace needs to be rebuilt.

Alternatively, you could ask Cargo to run the experiment explicitly and choose the best settings, as a single command, but this has the problem that it doesn't know what kind of edits you're going to be making and thus it can't reproduce the right incremental build cost (unless it saves copies of your edited source files)

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [May 20, 2025, 9:11pm UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/18 "2025-05-20T21:11:01Z")

</div>

> [@epage](#):
>
> you cannot have a built-in profile inherit from another

That seems like an artificial limitation to me. Is there any inherent reason such support couldn't be added?

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [May 21, 2025, 10:49am UTC](https://internals.rust-lang.org/t/feedback-request-performance-improvements-from-reducing-debug-info/21825/19 "2025-05-21T10:49:53Z")

</div>

Could cargo automatically make the distinction between outside-workspace dependencies (since those are unlikely to need recompiles) and apply a higher opt-level to those so that people don't have to set it via `[profile.dev.package."*"]` manually?
