@@ -62,12 +62,12 @@ func parseTurbostatOutput(output string) ([]map[string]string, error) {
6262 if len (headers ) == 0 {
6363 continue
6464 }
65- if len (fields ) != len (headers ) {
66- continue
65+ if len (fields ) > len (headers ) {
66+ return nil , fmt . Errorf ( "more turbostat row values than headers: %d values, %d headers" , len ( fields ), len ( headers ))
6767 }
68- row := make (map [string ]string , len (headers ))
69- for i , h := range headers {
70- row [h ] = fields [i ]
68+ row := make (map [string ]string , len (fields ))
69+ for i := range fields {
70+ row [headers [ i ]] = fields [i ] // this assumes any missing fields are at the end and will be empty string, which is consistent with turbostat output
7171 }
7272 if timeParsed && interval > 0 {
7373 row ["timestamp" ] = timestamp .Format ("15:04:05" )
@@ -219,9 +219,16 @@ func TurbostatPackageRowsByRegexMatch(turboStatScriptOutput string, fieldRegexs
219219 if len (rows ) == 0 {
220220 return nil , fmt .Errorf ("no rows found in turbostat output" )
221221 }
222+ // filter all rows down to only package rows
223+ rows , err = extractPackageRows (rows )
224+ if err != nil {
225+ return nil , fmt .Errorf ("unable to extract package rows: %w" , err )
226+ }
227+ if len (rows ) == 0 {
228+ return nil , fmt .Errorf ("no package rows found in turbostat output" )
229+ }
222230 // Build our list of matched field names from the first package row
223231 var matchedFields []string
224- foundPackageRow := false
225232 for _ , row := range rows {
226233 if _ , ok := row ["Package" ]; ! ok {
227234 if row ["CPU" ] == "0" {
@@ -230,10 +237,6 @@ func TurbostatPackageRowsByRegexMatch(turboStatScriptOutput string, fieldRegexs
230237 continue
231238 }
232239 }
233- if ! isPackageRow (row ) {
234- continue
235- }
236- foundPackageRow = true
237240 for field := range row {
238241 for _ , re := range fieldRegexs {
239242 if re .MatchString (field ) {
@@ -246,9 +249,6 @@ func TurbostatPackageRowsByRegexMatch(turboStatScriptOutput string, fieldRegexs
246249 }
247250 break // only need the first package row to discover fields
248251 }
249- if ! foundPackageRow {
250- return nil , fmt .Errorf ("no package rows found in turbostat output" )
251- }
252252 if len (matchedFields ) == 0 {
253253 return nil , fmt .Errorf ("no fields matched the provided regexes in turbostat output" )
254254 }
@@ -268,9 +268,6 @@ func TurbostatPackageRowsByRegexMatch(turboStatScriptOutput string, fieldRegexs
268268 continue
269269 }
270270 }
271- if ! isPackageRow (row ) {
272- continue
273- }
274271 rowValues := make ([]string , len (matchedFields )+ 1 )
275272 rowValues [0 ] = row ["timestamp" ]
276273 for i , field := range matchedFields {
@@ -322,6 +319,14 @@ func TurbostatPackageRows(turboStatScriptOutput string, fieldNames []string) ([]
322319 if len (rows ) == 0 {
323320 return nil , fmt .Errorf ("no package rows found in turbostat output" )
324321 }
322+ // filter all rows down to only package rows
323+ rows , err = extractPackageRows (rows )
324+ if err != nil {
325+ return nil , fmt .Errorf ("unable to extract package rows: %w" , err )
326+ }
327+ if len (rows ) == 0 {
328+ return nil , fmt .Errorf ("no package rows found in turbostat output" )
329+ }
325330 var packageRows [][][]string
326331 for _ , row := range rows {
327332 if _ , ok := row ["Package" ]; ! ok {
@@ -331,9 +336,6 @@ func TurbostatPackageRows(turboStatScriptOutput string, fieldNames []string) ([]
331336 continue
332337 }
333338 }
334- if ! isPackageRow (row ) {
335- continue
336- }
337339 rowValues := make ([]string , len (fieldNames )+ 1 )
338340 rowValues [0 ] = row ["timestamp" ]
339341 for i , fieldName := range fieldNames {
@@ -359,11 +361,18 @@ func TurbostatPackageRows(turboStatScriptOutput string, fieldNames []string) ([]
359361 return packageRows , nil
360362}
361363
362- func isPackageRow (row map [string ]string ) bool {
363- if val , ok := row ["Package" ]; ok && val != "-" {
364- return true
364+ func extractPackageRows (rows []map [string ]string ) ([]map [string ]string , error ) {
365+ var packageRows []map [string ]string
366+ for i , row := range rows {
367+ if val , ok := row ["Package" ]; ok && val != "-" && row ["Core" ] == "0" {
368+ if i > 0 && rows [i - 1 ]["Package" ] == val && rows [i - 1 ]["Core" ] == "0" {
369+ // This is the hyperthread associated with the package row, skip it
370+ continue
371+ }
372+ packageRows = append (packageRows , row )
373+ }
365374 }
366- return false
375+ return packageRows , nil
367376}
368377
369378// MaxTotalPackagePowerFromOutput calculates the maximum total package power from the turbostat output.
0 commit comments