@@ -13,6 +13,7 @@ import (
1313 "github.com/AlexsanderHamir/prof/engine/collector"
1414
1515 "github.com/AlexsanderHamir/prof/engine/tools/benchstats"
16+ "github.com/AlexsanderHamir/prof/engine/tools/qcachegrind"
1617 "github.com/AlexsanderHamir/prof/engine/tracker"
1718 "github.com/AlexsanderHamir/prof/internal"
1819 "github.com/spf13/cobra"
@@ -40,8 +41,10 @@ const (
4041 minTagsForComparison = 2
4142
4243 // 3 occurrences requires a const
43- base = "base"
44- current = "current"
44+ baseTagFlag = "base"
45+ currentTagFlag = "current"
46+ benchNameFlag = "bench-name"
47+ tagFlag = "tag"
4548)
4649
4750// CreateRootCmd creates and returns the root cobra command.
@@ -69,30 +72,53 @@ func createToolsCmd() *cobra.Command {
6972 }
7073
7174 cmd .AddCommand (createBenchStatCmd ())
75+ cmd .AddCommand (createQCacheGrindCmd ())
76+
77+ return cmd
78+ }
79+
80+ func createQCacheGrindCmd () * cobra.Command {
81+ profilesFlag := "profiles"
82+ shortExplanation := "runs benchstat on txt collected data."
83+
84+ cmd := & cobra.Command {
85+ Use : "qcachegrind" ,
86+ Short : shortExplanation ,
87+ Example : "prof tools qcachegrind --tag `current` --profiles `cpu` --bench-name `BenchmarkGenPool`" ,
88+ RunE : func (_ * cobra.Command , _ []string ) error {
89+ return qcachegrind .RunQcacheGrind (tag , benchmarkName , profiles [0 ])
90+ },
91+ }
92+
93+ cmd .Flags ().StringVar (& benchmarkName , benchNameFlag , "" , "Name of the benchmark" )
94+ cmd .Flags ().StringSliceVar (& profiles , profilesFlag , []string {}, `Profiles to use (e.g., "cpu,memory,mutex")` )
95+ cmd .Flags ().StringVar (& tag , tagFlag , "" , "The tag is used to organize the results" )
96+
97+ _ = cmd .MarkFlagRequired (benchNameFlag )
98+ _ = cmd .MarkFlagRequired (profilesFlag )
99+ _ = cmd .MarkFlagRequired (tagFlag )
72100
73101 return cmd
74102}
75103
76104func createBenchStatCmd () * cobra.Command {
77- baseTagFlag := base
78- currentFlag := current
79- benchNameFlag := "bench-name"
80105 shortExplanation := "runs benchstat on txt collected data."
81106
82107 cmd := & cobra.Command {
83- Use : "benchstat" ,
84- Short : shortExplanation ,
108+ Use : "benchstat" ,
109+ Short : shortExplanation ,
110+ Example : "prof tools benchstat --base `baseline` --current `current` --bench-name `BenchmarkGenPool`" ,
85111 RunE : func (_ * cobra.Command , _ []string ) error {
86112 return benchstats .RunBenchStats (Baseline , Current , benchmarkName )
87113 },
88114 }
89115
90116 cmd .Flags ().StringVar (& Baseline , baseTagFlag , "" , "Name of the baseline tag" )
91- cmd .Flags ().StringVar (& Current , currentFlag , "" , "Name of the current tag" )
117+ cmd .Flags ().StringVar (& Current , currentTagFlag , "" , "Name of the current tag" )
92118 cmd .Flags ().StringVar (& benchmarkName , benchNameFlag , "" , "Name of the benchmark" )
93119
94120 _ = cmd .MarkFlagRequired (baseTagFlag )
95- _ = cmd .MarkFlagRequired (currentFlag )
121+ _ = cmd .MarkFlagRequired (currentTagFlag )
96122 _ = cmd .MarkFlagRequired (benchNameFlag )
97123
98124 return cmd
@@ -109,7 +135,6 @@ func createProfManual() *cobra.Command {
109135 },
110136 }
111137
112- tagFlag := "tag"
113138 manualCmd .Flags ().StringVar (& tag , tagFlag , "" , "The tag is used to organize the results" )
114139 _ = manualCmd .MarkFlagRequired (tagFlag )
115140
@@ -119,7 +144,6 @@ func createProfManual() *cobra.Command {
119144func createProfAuto () * cobra.Command {
120145 benchFlag := "benchmarks"
121146 profileFlag := "profiles"
122- tagFlag := "tag"
123147 countFlag := "count"
124148 example := fmt .Sprintf (`prof %s --%s "BenchmarkGenPool" --%s "cpu,memory" --%s 10 --%s "tag1"` , internal .AUTOCMD , benchFlag , profileFlag , countFlag , tagFlag )
125149
@@ -159,14 +183,11 @@ func createTrackCmd() *cobra.Command {
159183}
160184
161185func createTrackAutoCmd () * cobra.Command {
162- baseTagFlag := "base"
163- currentFlag := "current"
164- benchNameFlag := "bench-name"
165186 profileTypeFlag := "profile-type"
166187 outputFormatFlag := "output-format"
167188 failFlag := "fail-on-regression"
168189 thresholdFlag := "regression-threshold"
169- example := fmt .Sprintf (`prof track auto --%s "tag1" --%s "tag2" --%s "cpu" --%s "BenchmarkGenPool" --%s "summary"` , baseTagFlag , currentFlag , profileTypeFlag , benchNameFlag , outputFormatFlag )
190+ example := fmt .Sprintf (`prof track auto --%s "tag1" --%s "tag2" --%s "cpu" --%s "BenchmarkGenPool" --%s "summary"` , baseTagFlag , currentTagFlag , profileTypeFlag , benchNameFlag , outputFormatFlag )
170191 longExplanation := fmt .Sprintf ("This command only works if the %s command was used to collect and organize the benchmark and profile data, as it expects a specific directory structure generated by that process." , internal .AUTOCMD )
171192 shortExplanation := "If prof auto was used to collect the data, track auto can be used to analyze it, you just have to pass the tag name."
172193
@@ -190,28 +211,26 @@ func createTrackAutoCmd() *cobra.Command {
190211 }
191212
192213 cmd .Flags ().StringVar (& Baseline , baseTagFlag , "" , "Name of the baseline tag" )
193- cmd .Flags ().StringVar (& Current , currentFlag , "" , "Name of the current tag" )
214+ cmd .Flags ().StringVar (& Current , currentTagFlag , "" , "Name of the current tag" )
194215 cmd .Flags ().StringVar (& benchmarkName , benchNameFlag , "" , "Name of the benchmark" )
195216 cmd .Flags ().StringVar (& profileType , profileTypeFlag , "" , "Profile type (cpu, memory, mutex, block)" )
196217 cmd .Flags ().StringVar (& outputFormat , outputFormatFlag , "detailed" , `Output format: "summary" or "detailed"` )
197218 cmd .Flags ().BoolVar (& failOnRegression , failFlag , false , "Exit with non-zero code if regression exceeds threshold" )
198219 cmd .Flags ().Float64Var (& regressionThreshold , thresholdFlag , 0.0 , "Fail when worst flat regression exceeds this percent (e.g., 5.0)" )
199220
200221 _ = cmd .MarkFlagRequired (baseTagFlag )
201- _ = cmd .MarkFlagRequired (currentFlag )
222+ _ = cmd .MarkFlagRequired (currentTagFlag )
202223 _ = cmd .MarkFlagRequired (benchNameFlag )
203224 _ = cmd .MarkFlagRequired (profileTypeFlag )
204225
205226 return cmd
206227}
207228
208229func createTrackManualCmd () * cobra.Command {
209- baseFlag := "base"
210- currentFlag := "current"
211230 outputFormatFlag := "output-format"
212231 failFlag := "fail-on-regression"
213232 thresholdFlag := "regression-threshold"
214- example := fmt .Sprintf (`prof track %s --%s "path/to/profile_file.txt" --%s "path/to/profile_file.txt" --%s "summary"` , internal .TrackManualCMD , baseFlag , currentFlag , outputFormatFlag )
233+ example := fmt .Sprintf (`prof track %s --%s "path/to/profile_file.txt" --%s "path/to/profile_file.txt" --%s "summary"` , internal .TrackManualCMD , baseTagFlag , currentTagFlag , outputFormatFlag )
215234
216235 cmd := & cobra.Command {
217236 Use : internal .TrackManualCMD ,
@@ -232,14 +251,14 @@ func createTrackManualCmd() *cobra.Command {
232251 Example : example ,
233252 }
234253
235- cmd .Flags ().StringVar (& Baseline , baseFlag , "" , "Name of the baseline tag" )
236- cmd .Flags ().StringVar (& Current , currentFlag , "" , "Name of the current tag" )
254+ cmd .Flags ().StringVar (& Baseline , baseTagFlag , "" , "Name of the baseline tag" )
255+ cmd .Flags ().StringVar (& Current , currentTagFlag , "" , "Name of the current tag" )
237256 cmd .Flags ().StringVar (& outputFormat , outputFormatFlag , "" , "Output format choice choice" )
238257 cmd .Flags ().BoolVar (& failOnRegression , failFlag , false , "Exit with non-zero code if regression exceeds threshold" )
239258 cmd .Flags ().Float64Var (& regressionThreshold , thresholdFlag , 0.0 , "Fail when worst flat regression exceeds this percent (e.g., 5.0)" )
240259
241- _ = cmd .MarkFlagRequired (baseFlag )
242- _ = cmd .MarkFlagRequired (currentFlag )
260+ _ = cmd .MarkFlagRequired (baseTagFlag )
261+ _ = cmd .MarkFlagRequired (currentTagFlag )
243262 _ = cmd .MarkFlagRequired (outputFormatFlag )
244263
245264 return cmd
0 commit comments