Documentation
¶
Overview ¶
Command fasteasyjson is a CLI-compatible drop-in for github.com/mailru/easyjson's easyjson command: same flags, same GOFILE/-pkg go:generate behavior, same generated output. It differs in how it gets there.
bootstrap.Generator.Run (the original) writes a randomly-named temp launcher file next to the target on every invocation, to `go run` the actual generator. The compiler embeds a source file's on-disk path into the debug info of the binary it produces, so a randomly-suffixed launcher name makes that one compile+link action permanently un-cacheable: GOCACHE grows by one fresh, never-reused entry per file, on every single run, forever, even when nothing changed. Multiplied across every annotated file in a repo, on every CI run, that is what makes easyjson slow to run repeatedly against a persisted build cache. (Confirmed by elimination: an overlay-based fix that stopped writing to the target file at all still showed the same unbounded growth, until the launcher's name was also made deterministic - only then did it stop.) The original also writes the target *_easyjson.go file itself twice per invocation - a compile stub, then the final output - which is a separate correctness concern (a crashed run can leave a bare stub committed in place of working code) more than the performance one above.
fasteasyjson gives the launcher a deterministic name (a hash of its group's target paths) instead of a random one, and serves each file's compile stub to the generator process through `go run -overlay=...` instead of writing it to the real path, and batches as many files as possible into as few overlays/`go run` invocations as possible, instead of one per file - all without changing the generated output. Every file with no `internal/` import constraint is batched into a single group regardless of how many distinct packages it spans (a launcher can import any number of non-`internal/` packages from anywhere on disk); files that do need an `internal/` package are grouped by their specific `internal/` ancestor directory, since a launcher can only reach such a package from somewhere under that package's parent-of-`internal` directory. The real file is written at most once, and only if its content actually changed (add -check to skip writing entirely and just report staleness, exit 1 if anything is out of date - a fast, non-destructive check for CI, see the mailru/easyjson issue this was built to avoid: repeated full-repo runs of the original generator with a persisted GOCACHE across CI jobs).