Skip to content

go/doc: repeated declaration indexing makes Examples quadratic #82675

Open

Description

@JakeNesler

Go version and environment

go1.28-devel_99291162c3 (2026-10-26), linux/amd64. Intel i9-13900K; GOMAXPROCS=1. Measurements recorded on 27 October 2026.

Also reproduced at 63313a0 on linux/arm64 (CIX P1 CP8180) on 28 October 2026.

What did you do?

Save this as examples.go, then run go run examples.go -n=1000 and go run examples.go -n=2000. Parsing is outside the measured operation.

Reproducer
package main

import (
	"flag"
	"fmt"
	"go/doc"
	"go/parser"
	"go/token"
	"strings"
	"testing"
)

func main() {
	n := flag.Int("n", 1000, "number of examples")
	flag.Parse()
	var src strings.Builder
	src.WriteString("package p_test\n")
	for i := 0; i < *n; i++ {
		fmt.Fprintf(&src, "func ExampleF%d() {}\n", i)
	}
	file, err := parser.ParseFile(token.NewFileSet(), "p_test.go", src.String(), 0)
	if err != nil {
		panic(err)
	}
	result := testing.Benchmark(func(b *testing.B) {
		b.ReportAllocs()
		for b.Loop() {
			if got := len(doc.Examples(file)); got != *n {
				b.Fatalf("got %d examples, want %d", got, *n)
			}
		}
	})
	fmt.Println(result, result.MemString())
}

What did you see happen?

Each playable example rebuilds the same top-level declaration and method indexes. Index construction takes O(E*D) work for E examples and D declarations, becoming quadratic when both grow together.

At 1,000 examples the measured operation took 68.412 ms and allocated 104.69 MiB; at 2,000 it took 319.380 ms and allocated 417.710 MiB.

What did you expect to see?

Examples from the same file should share its read-only declaration indexes.

CartoGopher tooling for source navigation; reproduction, implementation and testing with Codex.

Activity

  1. seankhliao commented on Oct 28, 2026

    @seankhliao
    Member

    given the low number of examples in a typical package I can hardly see this as a problem

  2. gopherbot commented on Oct 28, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/855661 mentions this issue: go/doc: reuse declaration indexes across examples

  3. thatnealpatel commented on Oct 28, 2026

    @thatnealpatel
    Member

    @nicholashusin Is this the elusive go doc bug we saw a few months ago?!

  4. nicholashusin commented on Oct 28, 2026

    @nicholashusin
    Member

    #78801 right?

    I think it's different. #78801 was already fixed and seems to be more so an infinite loop (judging from how it never finishes and eventually OOMs).

  5. JakeNesler commented on Oct 28, 2026

    @JakeNesler
    ContributorAuthor

    5. #78801 right?
    I think it's different. #78801 was already fixed and seems to be more so an infinite loop (judging from how it never finishes and eventually OOMs).

    I just tried it and they are indeed different 👍

  6. thatnealpatel commented on Oct 28, 2026

    @thatnealpatel
    Member

    I agree with @seankhliao

  7. JakeNesler commented on Oct 28, 2026

    @JakeNesler
    ContributorAuthor

    All good, I won’t be offended if it’s not as useful as I thought. I did try it on the Google Cloud SDK: example extraction went from 116 ms to 68 ms, and allocated memory from 68.5 MiB to 34.5 MiB. Overall it was small, but I still figured it was something :)

  8. JunyangShao commented on Oct 29, 2026

    @JunyangShao
    Contributor
  9. added
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Oct 29, 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

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions