11package parser
22
33import (
4- "fmt"
5- "sort"
6- "strings"
7-
84 "github.com/AlexsanderHamir/prof/internal"
95)
106
11- type LineObj struct {
12- FnName string
13- Flat float64
14- FlatPercentage float64
15- SumPercentage float64
16- Cum float64
17- CumPercentage float64
18- }
19-
207// TurnLinesIntoObjectsV2 turn profile data from a .pprof file into line objects.
218func TurnLinesIntoObjectsV2 (profilePath string ) ([]* LineObj , error ) {
229 profileData , err := extractProfileData (profilePath )
@@ -129,6 +116,7 @@ func OrganizeProfileByPackageV2(profilePath string, filter internal.FunctionFilt
129116 FlatPercentage : profileData .FlatPercentages [fn ],
130117 Cum : float64 (profileData .Cum [fn ]),
131118 CumPercentage : profileData .CumPercentages [fn ],
119+ SumPercentage : profileData .SumPercentages [fn ],
132120 }
133121
134122 packageGroups [packageName ].Functions = append (packageGroups [packageName ].Functions , funcInfo )
@@ -149,124 +137,3 @@ func OrganizeProfileByPackageV2(profilePath string, filter internal.FunctionFilt
149137 // Generate formatted output
150138 return formatPackageReport (sortedPackages ), nil
151139}
152-
153- // PackageGroup represents a group of functions from the same package
154- type PackageGroup struct {
155- Name string
156- Functions []* FunctionInfo
157- TotalFlat float64
158- TotalCum float64
159- FlatPercentage float64
160- CumPercentage float64
161- }
162-
163- // FunctionInfo represents a function with its performance metrics
164- type FunctionInfo struct {
165- Name string
166- FullName string
167- Flat float64
168- FlatPercentage float64
169- Cum float64
170- CumPercentage float64
171- }
172-
173- // extractPackageName extracts the package name from a full function path
174- func extractPackageName (fullPath string ) string {
175- // Handle cases like "github.com/user/pkg.(*Type).Method" => "github.com/user/pkg"
176- // or "sync/atomic.CompareAndSwapPointer" => "sync/atomic"
177-
178- // Split by dots
179- parts := strings .Split (fullPath , "." )
180- if len (parts ) < 2 {
181- return ""
182- }
183-
184- // Check if it's a standard library package (like "sync/atomic")
185- if ! strings .Contains (parts [0 ], "/" ) && len (parts ) >= 2 {
186- // Standard library package
187- if len (parts ) >= 3 && strings .Contains (parts [1 ], "/" ) {
188- return parts [0 ] + "." + parts [1 ]
189- }
190- return parts [0 ]
191- }
192-
193- // Check if it's a GitHub-style package
194- if strings .Contains (parts [0 ], "github.com" ) || strings .Contains (parts [0 ], "golang.org" ) {
195- // For GitHub packages, take up to the third part (github.com/user/pkg)
196- if len (parts ) >= 3 {
197- return strings .Join (parts [:3 ], "." )
198- }
199- return strings .Join (parts [:2 ], "." )
200- }
201-
202- // For other cases, take the first part
203- return parts [0 ]
204- }
205-
206- // sortPackagesByFlatPercentage sorts packages by their flat percentage in descending order
207- func sortPackagesByFlatPercentage (packageGroups map [string ]* PackageGroup ) []* PackageGroup {
208- var packages []* PackageGroup
209- for _ , pkg := range packageGroups {
210- packages = append (packages , pkg )
211- }
212-
213- sort .Slice (packages , func (i , j int ) bool {
214- return packages [i ].FlatPercentage > packages [j ].FlatPercentage
215- })
216-
217- return packages
218- }
219-
220- // formatPackageReport formats the package groups into a readable report
221- func formatPackageReport (packages []* PackageGroup ) string {
222- var result strings.Builder
223-
224- for i , pkg := range packages {
225- if i > 0 {
226- result .WriteString ("\n \n " )
227- }
228-
229- // Package header
230- result .WriteString (fmt .Sprintf ("#### **%s**\n " , pkg .Name ))
231-
232- // Sort functions by flat percentage (descending)
233- sort .Slice (pkg .Functions , func (i , j int ) bool {
234- return pkg .Functions [i ].FlatPercentage > pkg .Functions [j ].FlatPercentage
235- })
236-
237- // List functions
238- for _ , fn := range pkg .Functions {
239- if fn .Flat > 0 {
240- // Show only function name and percentage
241- result .WriteString (fmt .Sprintf ("- `%s` → %.2f%%\n " ,
242- fn .Name , fn .FlatPercentage ))
243- } else if fn .Cum > 0 {
244- // Function with only cumulative time
245- result .WriteString (fmt .Sprintf ("- `%s` → 0%% (cum %.2f%%)\n " ,
246- fn .Name , fn .CumPercentage ))
247- }
248- }
249-
250- // Package subtotal
251- result .WriteString (fmt .Sprintf ("\n **Subtotal (%s)**: ≈%.1f%%" ,
252- extractShortPackageName (pkg .Name ), pkg .FlatPercentage ))
253- }
254-
255- return result .String ()
256- }
257-
258- // extractShortPackageName extracts a shorter version of the package name for display
259- func extractShortPackageName (fullPackageName string ) string {
260- parts := strings .Split (fullPackageName , "." )
261- if len (parts ) == 0 {
262- return fullPackageName
263- }
264-
265- // For GitHub packages, show just the last part
266- if strings .Contains (fullPackageName , "github.com" ) {
267- return parts [len (parts )- 1 ]
268- }
269-
270- // For standard library, show the full name
271- return fullPackageName
272- }
0 commit comments