a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package analysis
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Memory-focused analysis benchmarks for low-resource devices (RPi)
|
|
// =============================================================================
|
|
|
|
// buildSyntheticGraphForMem creates a graph without b.Helper for standalone use.
|
|
func buildSyntheticGraphForMem(nodeCount int) *graph.Graph {
|
|
g := graph.New()
|
|
for i := range nodeCount {
|
|
g.AddNode(&graph.Node{
|
|
ID: fmt.Sprintf("pkg/file%d.go::Func%d", i/100, i),
|
|
Kind: graph.KindFunction,
|
|
Name: fmt.Sprintf("Func%d", i),
|
|
FilePath: fmt.Sprintf("pkg/file%d.go", i/100),
|
|
StartLine: (i % 100) + 1,
|
|
EndLine: (i % 100) + 10,
|
|
Language: "go",
|
|
})
|
|
}
|
|
for i := range nodeCount {
|
|
t1 := (i + 1) % nodeCount
|
|
t2 := (i + 7) % nodeCount
|
|
g.AddEdge(&graph.Edge{
|
|
From: fmt.Sprintf("pkg/file%d.go::Func%d", i/100, i),
|
|
To: fmt.Sprintf("pkg/file%d.go::Func%d", t1/100, t1),
|
|
Kind: graph.EdgeCalls,
|
|
})
|
|
g.AddEdge(&graph.Edge{
|
|
From: fmt.Sprintf("pkg/file%d.go::Func%d", i/100, i),
|
|
To: fmt.Sprintf("pkg/file%d.go::Func%d", t2/100, t2),
|
|
Kind: graph.EdgeCalls,
|
|
})
|
|
}
|
|
return g
|
|
}
|
|
|
|
// BenchmarkDetectCommunities_Memory measures heap allocation for community detection.
|
|
func BenchmarkDetectCommunities_Memory(b *testing.B) {
|
|
sizes := []struct {
|
|
name string
|
|
nodes int
|
|
}{
|
|
{"500_nodes", 500},
|
|
{"2K_nodes", 2_000},
|
|
{"5K_nodes", 5_000},
|
|
}
|
|
|
|
for _, sz := range sizes {
|
|
b.Run(sz.name, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
g := buildSyntheticGraphForMem(sz.nodes)
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
DetectCommunities(g)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkDiscoverProcesses_Memory measures heap allocation for process discovery.
|
|
func BenchmarkDiscoverProcesses_Memory(b *testing.B) {
|
|
sizes := []struct {
|
|
name string
|
|
nodes int
|
|
}{
|
|
{"500_nodes", 500},
|
|
{"2K_nodes", 2_000},
|
|
{"5K_nodes", 5_000},
|
|
}
|
|
|
|
for _, sz := range sizes {
|
|
b.Run(sz.name, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
g := buildSyntheticGraphForMem(sz.nodes)
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
DiscoverProcesses(g)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkAnalyzeImpact_Memory measures impact analysis memory usage.
|
|
func BenchmarkAnalyzeImpact_Memory(b *testing.B) {
|
|
sizes := []struct {
|
|
name string
|
|
nodes int
|
|
}{
|
|
{"500_nodes", 500},
|
|
{"2K_nodes", 2_000},
|
|
}
|
|
|
|
for _, sz := range sizes {
|
|
b.Run(sz.name, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
g := buildSyntheticGraphForMem(sz.nodes)
|
|
symbolIDs := []string{
|
|
"pkg/file0.go::Func0",
|
|
"pkg/file1.go::Func100",
|
|
}
|
|
b.ResetTimer()
|
|
for b.Loop() {
|
|
AnalyzeImpact(g, symbolIDs, nil, nil)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkAnalysis_HeapFootprint measures total heap consumed by each analysis pass.
|
|
func BenchmarkAnalysis_HeapFootprint(b *testing.B) {
|
|
g := buildSyntheticGraphForMem(3000)
|
|
|
|
analyses := []struct {
|
|
name string
|
|
fn func()
|
|
}{
|
|
{"DetectCommunities", func() { DetectCommunities(g) }},
|
|
{"DiscoverProcesses", func() { DiscoverProcesses(g) }},
|
|
{"AnalyzeImpact", func() { AnalyzeImpact(g, []string{"pkg/file0.go::Func0"}, nil, nil) }},
|
|
{"FindDeadCode", func() { FindDeadCode(g, nil, nil) }},
|
|
}
|
|
|
|
for _, a := range analyses {
|
|
b.Run(a.name, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
b.StopTimer()
|
|
runtime.GC()
|
|
var before runtime.MemStats
|
|
runtime.ReadMemStats(&before)
|
|
b.StartTimer()
|
|
|
|
a.fn()
|
|
|
|
b.StopTimer()
|
|
runtime.GC()
|
|
var after runtime.MemStats
|
|
runtime.ReadMemStats(&after)
|
|
b.ReportMetric(float64(after.TotalAlloc-before.TotalAlloc), "total-alloc-bytes")
|
|
b.StartTimer()
|
|
}
|
|
})
|
|
}
|
|
}
|