Skip to content

rustdoc sidebar duplicate-anchor de-duplication appears to be quadratic #158174

Closed

Description

@bunch-suffice-ivy

I tried this with the Rust build-tree rustdoc binary, rustdoc 1.98.0-dev, 4008bbdf34b.

cat > rustdoc_sidebar_deref_repro.py <<'PY'
#!/usr/bin/env python3
import os
import shutil
import subprocess
import time
from pathlib import Path

N = int(os.environ.get("N", "1600"))
RUSTDOC = os.environ.get("RUSTDOC", "rustdoc")


def write_deref_chain(path: Path) -> None:
    with path.open("w", encoding="ascii") as f:
        f.write("pub struct S0;\n")
        for i in range(1, N + 1):
            f.write(f"pub struct S{i};\n")
        for i in range(1, N + 1):
            f.write(f"impl S{i} {{ pub fn foo(&self) {{}} }}\n")
        for i in range(N):
            j = i + 1
            f.write(
                f"impl std::ops::Deref for S{i} {{ "
                f"type Target = S{j}; "
                f"fn deref(&self) -> &S{j} {{ static V: S{j} = S{j}; &V }} "
                "}\n"
            )


src = Path(f"sidebar_deref_{N}.rs")
write_deref_chain(src)
out = Path(f"rustdoc_sidebar_{N}")
if out.exists():
    shutil.rmtree(out)

start = time.perf_counter()
subprocess.run([RUSTDOC, str(src), "--crate-name", "sidebarpoc", "-o", str(out)], check=True)
seconds = time.perf_counter() - start
print(f"deref_depth={N} elapsed={seconds:.3f}s source={src.stat().st_size}")
PY

RUSTDOC=/path/to/rustdoc N=1600 python3 rustdoc_sidebar_deref_repro.py

It creates legal Rust code with a deep Deref chain:

pub struct S0;
pub struct S1;
pub struct S2;
// ...

impl S1 { pub fn foo(&self) {} }
impl S2 { pub fn foo(&self) {} }
impl S3 { pub fn foo(&self) {} }
// ...

impl std::ops::Deref for S0 { type Target = S1; /* ... */ }
impl std::ops::Deref for S1 { type Target = S2; /* ... */ }
impl std::ops::Deref for S2 { type Target = S3; /* ... */ }
// ...

When rustdoc renders the page for S0, it recursively collects methods from the
Deref targets for the sidebar. Every target contributes a method named foo, so
the sidebar needs many links with the same base anchor method.foo.

With N=1600, I see rustdoc spend about 49 seconds generating the docs:

deref_depth=1600 elapsed=49.054s source=261063

Here are the timings I collected with the same rustdoc binary:

deref_depth  source_bytes  exit_status  elapsed_ms
100          15357         0            357
200          31457         0            524
400          63657         0            1396
800          128057        0            7333
1600         261063        0            49054

The total number of hash
lookups and temporary string constructions is approximately 1 + 2 + ... + N.

Activity

  1. added
    T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    on Jun 20, 2026
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jun 20, 2026
  3. added
    I-compiletimeIssue: Problems and improvements with respect to compile times.
    on Jun 20, 2026
  4. deleted a comment from ipezygj on Jun 21, 2026
  5. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 7, 2026
  6. GuillaumeGomez commented on Jul 7, 2026

    @GuillaumeGomez
    Member

    Maybe something you might be interested into @yotamofek ? :)

  7. yotamofek commented on Jul 10, 2026

    @yotamofek
    Contributor

    Sounds fun!
    I'll take a look next week 😬

  8. added a commit that references this issue on Sep 23, 2026
  9. added a commit that references this issue on Sep 24, 2026
  10. added a commit that references this issue on Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-compiletimeIssue: Problems and improvements with respect to compile times.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions