Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce amount of code generated by ValueDebugFormat #8239

Merged
merged 2 commits into from
Jun 4, 2024

Conversation

bgw
Copy link
Member

@bgw bgw commented May 28, 2024

I noticed that ValueDebugFormat was pretty common near the top of cargo llvm-lines. It looked like this was probably due to the large number of await points inserted into the code. Each await point complicates the state machine that rustc must generate and pass to LLVM.

This reduces the number of await points from one per field to one per struct. There's a minor change in behavior as the child fields are awaited concurrently (join_all) instead of one-at-a-time.

Why?

Less code generated by macros and passed to LLVM should mean faster compiles and a smaller binary that we're shipping to the user. The total change here is pretty small though, so it's probably not worth benchmarking compile times.

Testing

cargo test -p turbo-tasks-macros-tests

cargo llvm-lines (sanity check)

cargo llvm-lines -p next-swc-napi

Before:

  Lines                  Copies               Function name
  -----                  ------               -------------
  1094257                31851                (TOTAL)
...
     1246 (0.1%,  2.2%)      1 (0.0%,  0.0%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}

After:

  Lines                  Copies               Function name
  -----                  ------               -------------
  1088974                31851                (TOTAL)
...
      462 (0.0%,  7.7%)      1 (0.0%,  0.3%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}

Binary size (next-swc, stripped arm64 linux tarball)

Before: 188180480 bytes
After: 187443200 bytes

Example Generated Code (After)
// =================================================
// Recursive expansion of the ValueDebugFormat macro
// =================================================

impl turbo_tasks::debug::ValueDebugFormat for ComponentsForJs {
    fn value_debug_format<'a>(
        &'a self,
        depth: usize,
    ) -> turbo_tasks::debug::ValueDebugFormatString<'a> {
        turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move {
            if depth == 0 {
                return Ok(stringify!(ComponentsForJs).to_string());
            }
            use turbo_tasks::debug::{internal::*, ValueDebugFormat};
            Ok(format!(
                "{:#?}",
                match self {
                    ComponentsForJs {
                        page,
                        layout,
                        error,
                        loading,
                        template,
                        not_found,
                        default,
                        route,
                        metadata,
                    } =>
                        FormattingStruct::new_named_async(
                            stringify!(ComponentsForJs),
                            vec![
                                AsyncFormattingField::new(
                                    stringify!(page),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        page.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(layout),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        layout.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(error),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        error.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(loading),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        loading.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(template),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        template.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(not_found),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        not_found.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(default),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        default.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(route),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        route.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(metadata),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        metadata.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                            ],
                        )
                        .await,
                }
            ))
        }))
    }
}

Copy link

vercel bot commented May 28, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
examples-nonmonorepo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 4, 2024 9:03pm
rust-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 4, 2024 9:03pm
8 Ignored Deployments
Name Status Preview Comments Updated (UTC)
examples-basic-web ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-designsystem-docs ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-gatsby-web ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-kitchensink-blog ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-native-web ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-svelte-web ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-tailwind-web ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm
examples-vite-web ⬜️ Ignored (Inspect) Visit Preview Jun 4, 2024 9:03pm

Copy link
Member Author

bgw commented May 28, 2024

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @bgw and the rest of your teammates on Graphite Graphite

Copy link
Contributor

github-actions bot commented May 28, 2024

⚠️ CI failed ⚠️

The following steps have failed in CI:

  • Turbopack Rust tests (mac/win, non-blocking)

See workflow summary for details

Copy link
Contributor

github-actions bot commented May 28, 2024

🟢 Turbopack Benchmark CI successful 🟢

Thanks

Copy link
Contributor

✅ This change can build next-swc

@bgw bgw marked this pull request as ready for review May 28, 2024 23:59
@bgw bgw requested a review from a team as a code owner May 28, 2024 23:59
@bgw bgw closed this May 29, 2024
@bgw bgw reopened this May 29, 2024
@bgw
Copy link
Member Author

bgw commented May 29, 2024

Whoops, accidental close...

Screenshot 2024-05-28 at 5 20 57 PM

bgw added 2 commits June 4, 2024 14:00
While the code generated for unit structs would *technically* work, it
accidentally created a variable binding the value to the struct name.
That struct name is naturally CamelCase, which would then create
compiler warnings inside the macro about `snake_case`.

I don't think this was directly caused by my PR, but empty structs are
now treated as unit structs, and unit structs were broken, so this
surfaced the issue.
@bgw bgw force-pushed the bgw/smaller-value-debug-format branch from 649143c to 4c1ca5a Compare June 4, 2024 21:01
@bgw bgw merged commit 67b2a85 into main Jun 4, 2024
52 of 53 checks passed
Copy link
Member Author

bgw commented Jun 4, 2024

Merge activity

  • Jun 4, 5:09 PM EDT: @bgw merged this pull request with Graphite.

@bgw bgw deleted the bgw/smaller-value-debug-format branch June 4, 2024 21:09
kdy1 added a commit to vercel/next.js that referenced this pull request Jun 5, 2024
# Turbopack

* vercel/turborepo#8272 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.8` -->
* vercel/turborepo#8262 <!-- Alexander Lyon - add
crate to calculate prehashes -->
* vercel/turborepo#8174 <!-- Tobias Koppers - use
prehash to avoid rehashing the key in the task cache -->
* vercel/turborepo#7674 <!-- Alexander Lyon - [turbo
trace] add ability to filter by value and occurences -->
* vercel/turborepo#8287 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.10` -->
* vercel/turborepo#8037 <!-- Alexander Lyon - create
turbo-static for compile time graph analysis -->
* vercel/turborepo#8293 <!-- Will Binns-Smith - Sync
Cargo.lock with Next.js -->
* vercel/turborepo#8239 <!-- Benjamin Woodruff -
Reduce amount of code generated by ValueDebugFormat -->
* vercel/turborepo#8304 <!-- Benjamin Woodruff -
Minor optimizations to the codegen of TaskFnInputFunction -->
* vercel/turborepo#8221 <!-- Donny/강동윤 - perf:
Introduce `RcStr` -->


### What?

I tried using `Arc<String>` in
vercel/turborepo#7772, but a team member suggested
creating a new type so we can replace underlying implementation easily
in the future.

### Why?

To reduce memory usage.

### How?

Closes PACK-2776
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Jul 25, 2024
…#8239)

I noticed that `ValueDebugFormat` was pretty common near the top of
`cargo llvm-lines`. It looked like this was probably due to the large
number of await points inserted into the code. Each await point
complicates the state machine that rustc must generate and pass to LLVM.

This reduces the number of await points from one per field to one per
struct. There's a minor change in behavior as the child fields are
awaited concurrently (`join_all`) instead of one-at-a-time.

## Why?

Less code generated by macros and passed to LLVM should mean faster
compiles and a smaller binary that we're shipping to the user. The total
change here is pretty small though, so it's probably not worth
benchmarking compile times.

## Testing

```
cargo test -p turbo-tasks-macros-tests
```

## cargo llvm-lines (sanity check)

```
cargo llvm-lines -p next-swc-napi
```

Before:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1094257                31851                (TOTAL)
...
     1246 (0.1%,  2.2%)      1 (0.0%,  0.0%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

After:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1088974                31851                (TOTAL)
...
      462 (0.0%,  7.7%)      1 (0.0%,  0.3%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

## Binary size (next-swc, stripped arm64 linux tarball)

Before: `188180480 bytes`
After: `187443200 bytes`

<details>
<summary><strong>Example Generated Code (After)</strong>
</summary>

```rust
// =================================================
// Recursive expansion of the ValueDebugFormat macro
// =================================================

impl turbo_tasks::debug::ValueDebugFormat for ComponentsForJs {
    fn value_debug_format<'a>(
        &'a self,
        depth: usize,
    ) -> turbo_tasks::debug::ValueDebugFormatString<'a> {
        turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move {
            if depth == 0 {
                return Ok(stringify!(ComponentsForJs).to_string());
            }
            use turbo_tasks::debug::{internal::*, ValueDebugFormat};
            Ok(format!(
                "{:#?}",
                match self {
                    ComponentsForJs {
                        page,
                        layout,
                        error,
                        loading,
                        template,
                        not_found,
                        default,
                        route,
                        metadata,
                    } =>
                        FormattingStruct::new_named_async(
                            stringify!(ComponentsForJs),
                            vec![
                                AsyncFormattingField::new(
                                    stringify!(page),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        page.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(layout),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        layout.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(error),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        error.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(loading),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        loading.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(template),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        template.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(not_found),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        not_found.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(default),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        default.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(route),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        route.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(metadata),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        metadata.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                            ],
                        )
                        .await,
                }
            ))
        }))
    }
}
```
</details>
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Jul 29, 2024
…#8239)

I noticed that `ValueDebugFormat` was pretty common near the top of
`cargo llvm-lines`. It looked like this was probably due to the large
number of await points inserted into the code. Each await point
complicates the state machine that rustc must generate and pass to LLVM.

This reduces the number of await points from one per field to one per
struct. There's a minor change in behavior as the child fields are
awaited concurrently (`join_all`) instead of one-at-a-time.

## Why?

Less code generated by macros and passed to LLVM should mean faster
compiles and a smaller binary that we're shipping to the user. The total
change here is pretty small though, so it's probably not worth
benchmarking compile times.

## Testing

```
cargo test -p turbo-tasks-macros-tests
```

## cargo llvm-lines (sanity check)

```
cargo llvm-lines -p next-swc-napi
```

Before:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1094257                31851                (TOTAL)
...
     1246 (0.1%,  2.2%)      1 (0.0%,  0.0%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

After:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1088974                31851                (TOTAL)
...
      462 (0.0%,  7.7%)      1 (0.0%,  0.3%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

## Binary size (next-swc, stripped arm64 linux tarball)

Before: `188180480 bytes`
After: `187443200 bytes`

<details>
<summary><strong>Example Generated Code (After)</strong>
</summary>

```rust
// =================================================
// Recursive expansion of the ValueDebugFormat macro
// =================================================

impl turbo_tasks::debug::ValueDebugFormat for ComponentsForJs {
    fn value_debug_format<'a>(
        &'a self,
        depth: usize,
    ) -> turbo_tasks::debug::ValueDebugFormatString<'a> {
        turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move {
            if depth == 0 {
                return Ok(stringify!(ComponentsForJs).to_string());
            }
            use turbo_tasks::debug::{internal::*, ValueDebugFormat};
            Ok(format!(
                "{:#?}",
                match self {
                    ComponentsForJs {
                        page,
                        layout,
                        error,
                        loading,
                        template,
                        not_found,
                        default,
                        route,
                        metadata,
                    } =>
                        FormattingStruct::new_named_async(
                            stringify!(ComponentsForJs),
                            vec![
                                AsyncFormattingField::new(
                                    stringify!(page),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        page.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(layout),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        layout.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(error),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        error.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(loading),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        loading.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(template),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        template.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(not_found),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        not_found.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(default),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        default.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(route),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        route.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(metadata),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        metadata.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                            ],
                        )
                        .await,
                }
            ))
        }))
    }
}
```
</details>
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Jul 29, 2024
…#8239)

I noticed that `ValueDebugFormat` was pretty common near the top of
`cargo llvm-lines`. It looked like this was probably due to the large
number of await points inserted into the code. Each await point
complicates the state machine that rustc must generate and pass to LLVM.

This reduces the number of await points from one per field to one per
struct. There's a minor change in behavior as the child fields are
awaited concurrently (`join_all`) instead of one-at-a-time.

## Why?

Less code generated by macros and passed to LLVM should mean faster
compiles and a smaller binary that we're shipping to the user. The total
change here is pretty small though, so it's probably not worth
benchmarking compile times.

## Testing

```
cargo test -p turbo-tasks-macros-tests
```

## cargo llvm-lines (sanity check)

```
cargo llvm-lines -p next-swc-napi
```

Before:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1094257                31851                (TOTAL)
...
     1246 (0.1%,  2.2%)      1 (0.0%,  0.0%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

After:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1088974                31851                (TOTAL)
...
      462 (0.0%,  7.7%)      1 (0.0%,  0.3%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

## Binary size (next-swc, stripped arm64 linux tarball)

Before: `188180480 bytes`
After: `187443200 bytes`

<details>
<summary><strong>Example Generated Code (After)</strong>
</summary>

```rust
// =================================================
// Recursive expansion of the ValueDebugFormat macro
// =================================================

impl turbo_tasks::debug::ValueDebugFormat for ComponentsForJs {
    fn value_debug_format<'a>(
        &'a self,
        depth: usize,
    ) -> turbo_tasks::debug::ValueDebugFormatString<'a> {
        turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move {
            if depth == 0 {
                return Ok(stringify!(ComponentsForJs).to_string());
            }
            use turbo_tasks::debug::{internal::*, ValueDebugFormat};
            Ok(format!(
                "{:#?}",
                match self {
                    ComponentsForJs {
                        page,
                        layout,
                        error,
                        loading,
                        template,
                        not_found,
                        default,
                        route,
                        metadata,
                    } =>
                        FormattingStruct::new_named_async(
                            stringify!(ComponentsForJs),
                            vec![
                                AsyncFormattingField::new(
                                    stringify!(page),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        page.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(layout),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        layout.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(error),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        error.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(loading),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        loading.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(template),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        template.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(not_found),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        not_found.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(default),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        default.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(route),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        route.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(metadata),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        metadata.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                            ],
                        )
                        .await,
                }
            ))
        }))
    }
}
```
</details>
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 1, 2024
…#8239)

I noticed that `ValueDebugFormat` was pretty common near the top of
`cargo llvm-lines`. It looked like this was probably due to the large
number of await points inserted into the code. Each await point
complicates the state machine that rustc must generate and pass to LLVM.

This reduces the number of await points from one per field to one per
struct. There's a minor change in behavior as the child fields are
awaited concurrently (`join_all`) instead of one-at-a-time.

## Why?

Less code generated by macros and passed to LLVM should mean faster
compiles and a smaller binary that we're shipping to the user. The total
change here is pretty small though, so it's probably not worth
benchmarking compile times.

## Testing

```
cargo test -p turbo-tasks-macros-tests
```

## cargo llvm-lines (sanity check)

```
cargo llvm-lines -p next-swc-napi
```

Before:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1094257                31851                (TOTAL)
...
     1246 (0.1%,  2.2%)      1 (0.0%,  0.0%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

After:

```
  Lines                  Copies               Function name
  -----                  ------               -------------
  1088974                31851                (TOTAL)
...
      462 (0.0%,  7.7%)      1 (0.0%,  0.3%)  <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```

## Binary size (next-swc, stripped arm64 linux tarball)

Before: `188180480 bytes`
After: `187443200 bytes`

<details>
<summary><strong>Example Generated Code (After)</strong>
</summary>

```rust
// =================================================
// Recursive expansion of the ValueDebugFormat macro
// =================================================

impl turbo_tasks::debug::ValueDebugFormat for ComponentsForJs {
    fn value_debug_format<'a>(
        &'a self,
        depth: usize,
    ) -> turbo_tasks::debug::ValueDebugFormatString<'a> {
        turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move {
            if depth == 0 {
                return Ok(stringify!(ComponentsForJs).to_string());
            }
            use turbo_tasks::debug::{internal::*, ValueDebugFormat};
            Ok(format!(
                "{:#?}",
                match self {
                    ComponentsForJs {
                        page,
                        layout,
                        error,
                        loading,
                        template,
                        not_found,
                        default,
                        route,
                        metadata,
                    } =>
                        FormattingStruct::new_named_async(
                            stringify!(ComponentsForJs),
                            vec![
                                AsyncFormattingField::new(
                                    stringify!(page),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        page.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(layout),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        layout.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(error),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        error.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(loading),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        loading.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(template),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        template.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(not_found),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        not_found.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(default),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        default.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(route),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        route.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                                AsyncFormattingField::new(
                                    stringify!(metadata),
                                    turbo_tasks::macro_helpers::value_debug_format_field(
                                        metadata.value_debug_format(depth.saturating_sub(1))
                                    ),
                                ),
                            ],
                        )
                        .await,
                }
            ))
        }))
    }
}
```
</details>
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 14, 2024
# Turbopack

* vercel/turborepo#8272 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.8` -->
* vercel/turborepo#8262 <!-- Alexander Lyon - add
crate to calculate prehashes -->
* vercel/turborepo#8174 <!-- Tobias Koppers - use
prehash to avoid rehashing the key in the task cache -->
* vercel/turborepo#7674 <!-- Alexander Lyon - [turbo
trace] add ability to filter by value and occurences -->
* vercel/turborepo#8287 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.10` -->
* vercel/turborepo#8037 <!-- Alexander Lyon - create
turbo-static for compile time graph analysis -->
* vercel/turborepo#8293 <!-- Will Binns-Smith - Sync
Cargo.lock with Next.js -->
* vercel/turborepo#8239 <!-- Benjamin Woodruff -
Reduce amount of code generated by ValueDebugFormat -->
* vercel/turborepo#8304 <!-- Benjamin Woodruff -
Minor optimizations to the codegen of TaskFnInputFunction -->
* vercel/turborepo#8221 <!-- Donny/강동윤 - perf:
Introduce `RcStr` -->


### What?

I tried using `Arc<String>` in
vercel/turborepo#7772, but a team member suggested
creating a new type so we can replace underlying implementation easily
in the future.

### Why?

To reduce memory usage.

### How?

Closes PACK-2776
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 15, 2024
* vercel/turborepo#8272 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.8` -->
* vercel/turborepo#8262 <!-- Alexander Lyon - add
crate to calculate prehashes -->
* vercel/turborepo#8174 <!-- Tobias Koppers - use
prehash to avoid rehashing the key in the task cache -->
* vercel/turborepo#7674 <!-- Alexander Lyon - [turbo
trace] add ability to filter by value and occurences -->
* vercel/turborepo#8287 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.10` -->
* vercel/turborepo#8037 <!-- Alexander Lyon - create
turbo-static for compile time graph analysis -->
* vercel/turborepo#8293 <!-- Will Binns-Smith - Sync
Cargo.lock with Next.js -->
* vercel/turborepo#8239 <!-- Benjamin Woodruff -
Reduce amount of code generated by ValueDebugFormat -->
* vercel/turborepo#8304 <!-- Benjamin Woodruff -
Minor optimizations to the codegen of TaskFnInputFunction -->
* vercel/turborepo#8221 <!-- Donny/강동윤 - perf:
Introduce `RcStr` -->

I tried using `Arc<String>` in
vercel/turborepo#7772, but a team member suggested
creating a new type so we can replace underlying implementation easily
in the future.

To reduce memory usage.

Closes PACK-2776
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 16, 2024
* vercel/turborepo#8272 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.8` -->
* vercel/turborepo#8262 <!-- Alexander Lyon - add
crate to calculate prehashes -->
* vercel/turborepo#8174 <!-- Tobias Koppers - use
prehash to avoid rehashing the key in the task cache -->
* vercel/turborepo#7674 <!-- Alexander Lyon - [turbo
trace] add ability to filter by value and occurences -->
* vercel/turborepo#8287 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.10` -->
* vercel/turborepo#8037 <!-- Alexander Lyon - create
turbo-static for compile time graph analysis -->
* vercel/turborepo#8293 <!-- Will Binns-Smith - Sync
Cargo.lock with Next.js -->
* vercel/turborepo#8239 <!-- Benjamin Woodruff -
Reduce amount of code generated by ValueDebugFormat -->
* vercel/turborepo#8304 <!-- Benjamin Woodruff -
Minor optimizations to the codegen of TaskFnInputFunction -->
* vercel/turborepo#8221 <!-- Donny/강동윤 - perf:
Introduce `RcStr` -->

I tried using `Arc<String>` in
vercel/turborepo#7772, but a team member suggested
creating a new type so we can replace underlying implementation easily
in the future.

To reduce memory usage.

Closes PACK-2776
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants