Scalene Python Profiler

repository·master·Indexed 12 days ago

https://github.com/plasma-umass/scalene

A high-resolution, low-overhead CPU, GPU, and memory profiler for Python. Scalene provides line-level granularity, identifies memory leaks, profiles async await time, and offers AI-powered code optimization suggestions via providers like OpenAI, Azure, and Amazon Bedrock. It supports standalone HTML reports, CLI output, and integration with Jupyter Notebooks via %scrun and %%scalene magics.

Tokens
38.4K
Snippets
145
Records
200
Agent score
95%

What's inside Scalene

  1. Understand Scalene's profiling capabilities

    master

    Scalene is a high-performance Python profiler that uses sampling to minimize overhead (typically 10-20%). It provides line-level and function-level granularity for several metrics:

    • CPU Profiling: Separates time spent in Python from native code (C/C++ libraries) and identifies system time (I/O bottlenecks).
    • GPU Profiling: Reports GPU time (currently limited to NVIDIA-based systems).
    • Memory Profiling: Tracks memory usage per line, identifies likely memory leaks, separates Python vs. native memory consumption, and profiles copying volume (MB/s) to detect inefficient data conversions.
    • Async Profiling: Attributes await time to specific lines, including mean and peak concurrency of coroutines.
    • Stack Views: When --stacks is enabled (default), it provides stitched Python + native call stacks, memory-weighted flame charts, and a wall-clock timeline.
  2. Understand the Profile Output Pipeline

    master

    Scalene uses three distinct renderers for profile output. If you are extending Scalene or debugging output discrepancies, note that these are separate systems:

    • JSON output: Handled by scalene_json.py:output_profiles() via output_profile_line().
    • CLI viewer: Handled by scalene_parseargs.py:_display_profile_cli(). This is used when running scalene view --cli and is completely separate from the HTML/GUI output logic.
    • HTML/GUI output: Handled by scalene_output.py:output_profiles() (used by scalene view --html).
    • GUI (Browser): Uses scalene-gui.ts:makeProfileLine() which embeds Vega-Lite charts via vegaEmbed().
    • Standalone HTML: Generated by scalene_utility.py:generate_html(standalone=True), which embeds all assets inline.
  3. Scalene Profiling Capabilities Overview

    master

    Scalene is a high-performance profiler that provides detailed insights across several dimensions:

    • CPU Profiling: Separates time spent in Python from time in native code (C/C++ libraries) and identifies system/IO bottlenecks.
    • GPU Profiling: Reports GPU time (currently limited to NVIDIA systems).
    • Memory Profiling: Provides per-line memory usage, identifies memory leaks, separates Python vs. native memory consumption, and tracks "copy volume" (megabytes copied per second).
    • Granularity: Performs profiling at both the function level and the specific line level.
    • Reduced Profiles: Can use --reduced-profile to only report lines consuming >1% CPU or performing >100 allocations.
  4. Understand Scalene profile output metrics

    master

    Scalene profiles provide several key metrics to help triangulate performance issues:

    • Time Python: Time spent in Python code.
    • native: Time spent in non-Python code (e.g., C/C++ libraries).
    • system: Time spent in the system (e.g., I/O).
    • GPU: Time spent on the GPU (if an NVIDIA GPU is present).
    • Memory Python: Memory allocation on the Python side.
    • net: Net memory allocation in MB (positive for allocation, negative for reclamation).
    • timeline / %: Visualized memory consumption per line over runtime and its percentage of total activity.
    • Copy (MB/s): The rate of megabytes being copied per second.
  5. How async and stack views work in Scalene

    master

    Scalene provides specialized views for asynchronous code and deep stack analysis:

    Async Profiling

    Async profiling is enabled by default. It attributes wall-clock await time to the line where a coroutine is suspended. In the GUI, this is visualized as a clockwise pie wedge per line; larger wedges indicate more time spent suspended on that await. To disable this, use the --no-async flag.

    Stack Views

    By default, Scalene captures stitched Python + native (C/C++) stacks using the --stacks flag. These are presented in three ways in the GUI:

    • Call stacks: A flame chart of top stitched stacks. Python frames are clickable to jump to source; native frames are demangled and shown alongside Python frames.
    • Memory stacks: A memory-weighted flame chart where frame width is proportional to MB allocated along that call path.
    • Timeline: An icicle/time-series view laid out by wall-clock time, featuring tracks for GC, I/O, and GIL activity. Coroutines appear as [await] task_name frames.
  6. Enable AI-powered optimization suggestions

    master

    Scalene can suggest code optimizations using AI providers like Amazon Bedrock, Microsoft Azure, OpenAI, or local models via Ollama.

    To use this feature:

    1. Run your profile.
    2. In the web GUI, locate the "AI Optimization Options" box.
    3. Select your provider and enter required credentials.
    4. Click the lightning bolt (⚡) next to a specific line or the explosion (💥) for a code region to generate a suggestion.
    5. Click a suggestion to copy it to your clipboard.
  7. Understand the Chart Rendering Flow

    master

    The Scalene GUI follows a specific asynchronous rendering lifecycle for charts:

    1. Placeholder Creation: makeProfileLine() generates the HTML string containing <span id="chart_name${index}"> placeholders.
    2. Spec Collection: Chart specifications are collected and pushed into arrays (e.g., cpu_bars, gpu_pies, await_pies) during the profile loop.
    3. DOM Insertion: The HTML containing the placeholders is inserted into the DOM.
    4. Asynchronous Rendering: Once the DOM is ready, embedCharts(array, "prefix") is called, which invokes vegaEmbed() for every specification in the array.

    Note for Testers: Because SVGs render asynchronously, Selenium tests must implement explicit waits to verify the presence and content of SVG elements.

  8. Implement Pie Charts and Rotating Pies

    master

    When implementing pie charts in the Scalene GUI, follow these best practices:

    • Complete Circles: Always provide two data values (the filled value and the remaining value) to ensure a complete circle. Using a single value with scale: { domain: [0, 100] } results in partial arcs with gaps.
    • Rotating Pies: To create a continuous effect where each row's wedge starts where the previous one ended, use the theta encoding with a dynamic range:
      • Set scale: { range: [startAngle, startAngle + 2*PI] }.
      • Track the cumulative angle in TypeScript:
        pieAngles.await += (pct / 100) * 2 * Math.PI;
    • State Management: Reset the angle state per table. The line profile and function profile tables must use separate pieAngles objects.
    pieAngles.await += (pct / 100) * 2 * Math.PI;
  9. Background profiling with `--off`

    master

    You can start a process with profiling disabled and then enable/disable it remotely using the PID. This is useful for controlling profiling during specific phases of a long-running process.

    # 1. Start the program with profiling OFF
    scalene run --off prog.py
    
    # 2. Resume profiling for a specific PID
    python3 -m scalene.profile --on --pid <PID>
    
    # 3. Suspend profiling for a specific PID
    python3 -m scalene.profile --off --pid <PID>
  10. Profile a program with Scalene

    master

    To profile a Python program, run Scalene from the command line. By default, the profiling results are saved to scalene-profile.json.

    To pass arguments to your actual program (the code you are profiling) rather than to Scalene itself, use the -- separator. Everything following the -- will be passed directly to your script.

    scalene my_script.py -- --my_arg value
  11. Pass arguments to your program through Scalene

    master

    When using scalene run, you can pass arguments to your target script by using the --- separator. Everything following the separator is passed directly to your program.

    scalene run your_prog.py --- --arg1 --arg2