diff --git a/cmd/flamegraph/flamegraph_renderers.go b/cmd/flamegraph/flamegraph_renderers.go index 024d77e3..ac4d4b15 100644 --- a/cmd/flamegraph/flamegraph_renderers.go +++ b/cmd/flamegraph/flamegraph_renderers.go @@ -198,3 +198,32 @@ func renderFlameGraph(header string, tableValues table.TableValues, field string out += "\n" return } + +func callStackFrequencyTableHTMLRenderer(tableValues table.TableValues, targetName string) string { + out := ` +` + out += renderFlameGraph("Native", tableValues, "Native Stacks") + out += renderFlameGraph("Java", tableValues, "Java Stacks") + return out +} diff --git a/cmd/flamegraph/flamegraph_tables.go b/cmd/flamegraph/flamegraph_tables.go index 054e6874..5fb655c0 100644 --- a/cmd/flamegraph/flamegraph_tables.go +++ b/cmd/flamegraph/flamegraph_tables.go @@ -282,32 +282,3 @@ func mergeSystemFolded(perfFp string, perfDwarf string) (merged string, err erro merged = mergedStacks.dumpFolded() return } - -func callStackFrequencyTableHTMLRenderer(tableValues table.TableValues, targetName string) string { - out := ` -` - out += renderFlameGraph("Native", tableValues, "Native Stacks") - out += renderFlameGraph("Java", tableValues, "Java Stacks") - return out -} diff --git a/internal/report/render_html.go b/internal/report/render_html.go index 5cc948a3..a8c825f2 100644 --- a/internal/report/render_html.go +++ b/internal/report/render_html.go @@ -339,8 +339,8 @@ func createHtmlReportMultiTarget(allTargetsTableValues [][]table.TableValues, ta // loop through the targets that have values for this table for targetIndex, targetTableValues := range tableValues { targetName := tableTargets[targetIndex] - // if the table has rows and no custom renderer, print the table for the target normally - if targetTableValues.HasRows && getCustomHTMLMultiTargetRenderer(targetTableValues.Name) == nil { + // render the table for this target if it has a custom renderer + if shouldRenderTablePerTarget(targetTableValues) { // print the table name only one time per table if targetIndex == 0 { fmt.Fprintf(&sb, "

%[1]s

\n", html.EscapeString(targetTableValues.Name)) @@ -357,7 +357,7 @@ func createHtmlReportMultiTarget(allTargetsTableValues [][]table.TableValues, ta } else { sb.WriteString(DefaultHTMLTableRendererFunc(targetTableValues)) } - } else { // if the table has no rows or a custom renderer, add the table to the list to render as a multi-target table + } else { // if the table doesn't have a custom renderer, add it to the list to render as a multi-target table oneTableValuesForAllTargets = append(oneTableValuesForAllTargets, targetTableValues) } } @@ -384,6 +384,19 @@ func createHtmlReportMultiTarget(allTargetsTableValues [][]table.TableValues, ta return } +// shouldRenderTablePerTarget determines if a table should be rendered individually per target +// rather than as a combined multi-target comparison table. +// Renders per-target if: +// - The table has multiple rows (HasRows=true), OR +// - The table has a custom single-target renderer +// +// Unless a specific multi-target renderer exists for the table. +func shouldRenderTablePerTarget(tableValues table.TableValues) bool { + hasCustomRenderer := getCustomHTMLRenderer(tableValues.Name) != nil + hasMultiTargetRenderer := getCustomHTMLMultiTargetRenderer(tableValues.Name) != nil + return (tableValues.HasRows || hasCustomRenderer) && !hasMultiTargetRenderer +} + // findTableIndex func findTableIndex(tableValues []table.TableValues, tableName string) int { for i, tableValue := range tableValues {