Flame Charts: The Time-Aware Sibling of Flame Graphs

A deep dive into the time-aware visualization that complements traditional flame graphs in performance profiling.

Flame Charts: The Time-Aware Sibling of Flame Graphs
May 28, 2025

Following our journey through flame graphs and icicle graphs, we now explore flame charts, a complementary visualization that reintroduces what flame graphs deliberately left behind: the dimension of time. While flame graphs excel at highlighting which functions consume resources, flame charts go a step further by also showing when those resources are consumed.

Try It Now

Before we dive into the details, here's the exciting news: flame charts are now available as an alpha feature in Polar Signals Cloud! Here's how to get started:

Step 1: Enable the Feature Navigate to the Preferences in the visualization section and enable flame charts (currently in alpha).

Step 2: Select Flame Chart Visualization In your profiling view, select "Flame Chart" from the visualization type dropdown:

Flame Chart Visualization Selection
Flame Chart Visualization Selection

For complete setup instructions including agent configuration, see our detailed flame charts documentation.

Now, let's dive into what makes flame charts stand out.

Understanding the Distinction

Remember when we discussed how flame graphs sort samples alphabetically to maximize merging? This design choice, while brilliant for identifying bottlenecks, deliberately discards temporal information. Flame charts restore this temporal dimension, providing a complementary view that reveals performance patterns over time.

Key Differences

AspectFlame GraphsFlame Charts
X-axisAlphabetically/Cumulative value sorted samplesTime (chronological order)
Primary UseIdentifying hotspotsUnderstanding execution flow
MergingAggressive merging of identical stacksTemporal order prioritized over merging
WidthProportional to total time spentProportional to wall clock time

Anatomy of a Flame Chart

Like flame graphs, flame charts use stacked rectangles to represent function calls. However, the interpretation differs quite a bit, below image gives a high-level idea on how a flame chart is laid out:

Anatomy of a Flame Chart
Anatomy of a Flame Chart

Reading a Flame Chart

Prerequisite

To generate meaningful flame charts, you must filter your profiling data to show samples from a single CPU core or thread. This is essential because flame charts display execution over time on a single timeline, threads or vCPUs can't execute two things simultaneously, so filtering by these dimensions ensures each moment in time corresponds to exactly one function in the call stack. Note: Hyperthreading is considered as a separate vCPU in both Parca and Polar Signals Cloud.

When querying profiling data for flame chart visualization, ensure you group by any label that guarantees non-overlapping samples, such as thread_id or cpu. For more information on configuring these labels, see the profiling agent documentation.

Interpreting the Flame Chart

Unlike flamegraphs, which aggregate similar function calls into a single stack, flame charts preserve every individual function call in its temporal context. This means you'll see the same function appearing multiple times across the timeline, each instance representing a separate invocation.

Three key points guide flame chart interpretation:

  1. Timeline Guide: The top of the flame chart displays a timeline ruler showing timestamps. This provides the temporal reference for all stacks below, allowing you to pinpoint exactly when each function executed.

  2. Stack Duration: Each stack rectangle starts at the precise timeline position where execution begins and extends horizontally to where it ends. The width directly represents the function's execution duration.

  3. Timeline Gaps: Empty spaces along the timeline indicate periods when the thread wasn't executing on the CPU core, typically due to I/O wait, blocking operations, or CPU scheduling.

An Example

Consider a food delivery app processing multiple orders:

func OrderProcessorMain() {
    for {
        orders := pollNewOrders()

        if len(orders) > 0 {
            processOrders(orders)
        } else {
          // No new orders, sleep for 100ms
          time.Sleep(100 * time.Millisecond)
        }
    }
}

func processOrders(orders []Order) error {
    for _, order := range orders {
        err := processOrder(order)
        if err != nil {
            // Log error and continue with next order
            continue
        }
    }
    return nil
}

func processOrder(order Order) error {
    // Check if restaurant is open and has items
    available, err := checkRestaurant(order.RestaurantID, order.Items)
    if err != nil || !available {
        return err
    }

    // Find and assign nearest available driver
    driver, err := assignDriver(order.RestaurantLocation)
    if err != nil {
        return err
    }

    // Send push notification to customer
    notifyCustomer(order.CustomerID, driver.ID)

    return nil
}

The corresponding flame chart showing the polling loop with order processing:

Corresponding Flame Chart
Corresponding Flame Chart

Key observations from the flame chart:

  • 1st iteration (0-350ms): Processes 2 orders
  • 2nd iteration (350-380ms): No new orders, goes to sleep for 100ms
  • 3rd iteration (480-510ms): No new orders, sleeps again for 100ms
  • 4th iteration (610-850ms): Processes 1 order
  • 5th iteration (850-880ms): No new orders, sleeps for 100ms
  • 6th iteration (980-1010ms): No new orders

This example perfectly demonstrates the power of flame charts: iterations 2 and 5 start immediately after order processing (no gap), while iterations 3, 4, and 6 show 100ms gaps after no-order polls. These timing patterns make control flow decisions visible, something impossible to see in traditional flame graphs. Where flame graphs would merge all pollNewOrders calls into one stack, flame charts preserve each instance in time, revealing the application's actual behavior and rhythm.

Conclusion

With flame charts now in alpha on Polar Signals Cloud, you have both dimensions of performance analysis at your fingertips, what's consuming resources and when it's happening, a powerful combination for understanding your application's true behavior. Are you now ready to see your application's execution timeline? Start your 14-day free trial and discover what your flame graphs have been hiding!

Discuss:
Sign up for the latest Polar Signals news