Files
gosec/internal/ssautil/package_analysis_cache.go
T
Cosmin Cojocar caf93d07f1 Improve taint analyzer performance with shared SSA cache, parallel analyzer execution, and CI regression guard (#1530)
* Improve taint analyzer performance with shared SSA cache, parallel analyzer execution, and CI regression guard

* Added a shared per-package SSA analysis cache with lazy,
concurrency-safe call graph reuse across analyzers.
* Updated taint analyzers to consume the shared cache instead of
recomputing expensive artifacts per rule run.
* Parallelized analyzer execution at package level while preserving
deterministic issue aggregation.
* Added a package-level taint benchmark to measure real end-to-end taint
analyzer pass performance.
* Introduced a CI benchmark regression guard with configurable
thresholds for ns/op, B/op, and allocs/op.
* Documented the performance guard workflow, local run command, and
baseline update process in the README.

Signed-off-by: Cosmin Cojocar <cosmin@cojocar.ch>

* Fix script

Signed-off-by: Cosmin Cojocar <cosmin@cojocar.ch>

---------

Signed-off-by: Cosmin Cojocar <cosmin@cojocar.ch>
2026-02-19 16:50:41 +01:00

41 lines
1.0 KiB
Go

package ssautil
import (
"sync"
"golang.org/x/tools/go/analysis/passes/buildssa"
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/cha"
)
// PackageAnalysisCache stores expensive SSA-derived artifacts that can be
// shared by multiple analyzers running on the same package.
type PackageAnalysisCache struct {
ssa *buildssa.SSA
callGraphOnce sync.Once
callGraph *callgraph.Graph
}
// NewPackageAnalysisCache builds a cache object for a package-level SSA result.
func NewPackageAnalysisCache(ssaResult *buildssa.SSA) *PackageAnalysisCache {
return &PackageAnalysisCache{ssa: ssaResult}
}
// CallGraph returns a lazily initialized CHA call graph for the package.
// It is safe for concurrent use by multiple analyzers.
func (c *PackageAnalysisCache) CallGraph() *callgraph.Graph {
if c == nil {
return nil
}
c.callGraphOnce.Do(func() {
if c.ssa == nil || len(c.ssa.SrcFuncs) == 0 || c.ssa.SrcFuncs[0] == nil {
return
}
c.callGraph = cha.CallGraph(c.ssa.SrcFuncs[0].Prog)
})
return c.callGraph
}