package app import ( "context" "flag" "math/rand" "net/http" "net/url" "os" "path/filepath" "testing" "github.com/weaveworks/scope/render" "github.com/weaveworks/scope/render/detailed" "github.com/weaveworks/scope/report" "github.com/weaveworks/scope/test/fixture" ) var ( benchReportPath = flag.String("bench-report-path", "", "report file, or dir with files, to use for benchmarking (relative to this package)") ) func readReportFiles(b *testing.B, path string) []report.Report { reports := []report.Report{} if err := filepath.Walk(path, func(p string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } rpt, err := report.MakeFromFile(context.Background(), p) if err != nil { return err } reports = append(reports, *rpt) return nil }); err != nil { b.Fatal(err) } return reports } func BenchmarkReportUnmarshal(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { readReportFiles(b, *benchReportPath) } } func upgradeReports(reports []report.Report) []report.Report { upgraded := make([]report.Report, len(reports)) for i, r := range reports { upgraded[i] = r.Upgrade() } return upgraded } func BenchmarkReportUpgrade(b *testing.B) { reports := readReportFiles(b, *benchReportPath) b.ResetTimer() for i := 0; i < b.N; i++ { upgradeReports(reports) } } func BenchmarkReportMerge(b *testing.B) { reports := upgradeReports(readReportFiles(b, *benchReportPath)) rand.Shuffle(len(reports), func(i, j int) { reports[i], reports[j] = reports[j], reports[i] }) merger := NewFastMerger() b.ResetTimer() for i := 0; i < b.N; i++ { merger.Merge(reports) } } func getReport(b *testing.B) report.Report { r := fixture.Report if *benchReportPath != "" { r = NewFastMerger().Merge(upgradeReports(readReportFiles(b, *benchReportPath))) } return r } func benchmarkRender(b *testing.B, f func(report.Report)) { r := getReport(b) r.UnsafeRemovePartMergedNodes(context.Background()) b.ResetTimer() for i := 0; i < b.N; i++ { b.StopTimer() render.ResetCache() b.StartTimer() f(r) } } func renderForTopology(b *testing.B, topologyID string, report report.Report) report.Nodes { renderer, filter, err := topologyRegistry.RendererForTopology(topologyID, url.Values{}, report) if err != nil { b.Fatal(err) } return render.Render(context.Background(), report, renderer, filter).Nodes } func benchmarkRenderTopology(b *testing.B, topologyID string) { benchmarkRender(b, func(report report.Report) { renderForTopology(b, topologyID, report) }) } func BenchmarkRenderList(b *testing.B) { benchmarkRender(b, func(report report.Report) { topologyRegistry.renderTopologies(context.Background(), report, &http.Request{Form: url.Values{}}) }) } func BenchmarkRenderHosts(b *testing.B) { benchmarkRenderTopology(b, "hosts") } func BenchmarkRenderControllers(b *testing.B) { benchmarkRenderTopology(b, "kube-controllers") } func BenchmarkRenderPods(b *testing.B) { benchmarkRenderTopology(b, "pods") } func BenchmarkRenderContainers(b *testing.B) { benchmarkRenderTopology(b, "containers") } func BenchmarkRenderProcesses(b *testing.B) { benchmarkRenderTopology(b, "processes") } func BenchmarkRenderProcessNames(b *testing.B) { benchmarkRenderTopology(b, "processes-by-name") } func benchmarkSummarizeTopology(b *testing.B, topologyID string) { ctx := context.Background() r := getReport(b) rc := detailed.RenderContext{Report: r} nodes := renderForTopology(b, topologyID, r) b.ResetTimer() for i := 0; i < b.N; i++ { detailed.Summaries(ctx, rc, nodes) } } func BenchmarkSummarizeHosts(b *testing.B) { benchmarkSummarizeTopology(b, "hosts") } func BenchmarkSummarizeControllers(b *testing.B) { benchmarkSummarizeTopology(b, "kube-controllers") } func BenchmarkSummarizePods(b *testing.B) { benchmarkSummarizeTopology(b, "pods") } func BenchmarkSummarizeContainers(b *testing.B) { benchmarkSummarizeTopology(b, "containers") } func BenchmarkSummarizeProcesses(b *testing.B) { benchmarkSummarizeTopology(b, "processes") } func BenchmarkSummarizeProcessNames(b *testing.B) { benchmarkSummarizeTopology(b, "processes-by-name") }