Skip to content

perf: cache packages.Load results to eliminate redundant package loading #60

Description

@pageton

Summary

packages.Load is called without any caching in three functions. Each call invokes the Go build system (go list) and takes 100–500ms. For large codebases, this causes the CLI to spend more time loading packages than generating code.

loadNamedType (utils.go:98-112)

Called 4 times at package init for allowedInterfaces, then again per-field via Field.Type() (generator.go:456). If 20 fields reference models.User, the same package is loaded 20 times.

loadNamedStructType (utils.go:115-150)

Called per anonymous embedding of an external type (generator.go:791). Same package loaded repeatedly for different structs.

getCurrentPackagePath (utils.go:84-95)

Called once per input file (generator.go:261). Processing 20 files in the same package triggers 20 identical loads.

Proposed Fix

Add a package-level cache keyed by (modRoot, pkgPath):

var pkgCache sync.Map // map[pkgCacheKey]*packages.Package

type pkgCacheKey struct {
    modRoot string
    pkgPath string
}

All three functions check the cache before calling packages.Load. Since the CLI is single-threaded during processing, even a simple map[string]*packages.Package with no synchronization would work (or sync.Map if concurrency is ever added).

Expected Impact

On a project with 50 structs across 20 files:

  • Before: 100+ packages.Load calls → potentially minutes
  • After: 1 call per unique package path → seconds

Diagnosis

Run with GODEBUG=gocacheverify=1 or add timing around packages.Load calls to confirm this dominates CLI runtime.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions