# How to Use the Profiler to Analyze and Optimize Nelson Code Performance

> Optimize Nelson code performance using the profiler. Learn how to profile code, view statistics, and identify bottlenecks with simple commands.

- Repository: [The Nelson Programming Language/nelson](https://github.com/nelson-lang/nelson)
- Tags: performance
- Published: 2026-03-08

---

**Use the `profile` builtin to start the Nelson profiler with `profile on`, run your code, then call `profile off` followed by `profile('info')` or `profile('show')` to view execution statistics and identify bottlenecks.**

The Nelson interpreter (nelson-lang/nelson) ships with a built-in **profiler** that records function call counts and execution times at the line level. This tool helps you pinpoint hotspots in computationally intensive scripts and measure the impact of optimizations. The profiler is implemented as a singleton `Profiler` class and controlled through the `profile` builtin command.

## How the Nelson Profiler Works

The profiler architecture consists of three integrated layers that automatically capture timing data without requiring manual instrumentation of your code.

### The `profile` Builtin Command

The entry point for users is the **`profile`** builtin, implemented in [`modules/profiler/builtin/cpp/profileBuiltin.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/builtin/cpp/profileBuiltin.cpp). This function parses subcommands (`on`, `off`, `show`, `info`, `status`) and forwards them to the singleton instance. When you execute `profile on`, the builtin calls `Profiler::getInstance()->on()`, which clears previous data and activates the timing hooks.

### The Profiler Singleton and Timing Hooks

At the core is the **`Profiler`** singleton defined in [`modules/profiler/src/include/Profiler.hpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/src/include/Profiler.hpp) and implemented in [`modules/profiler/src/cpp/Profiler.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/src/cpp/Profiler.cpp). This class maintains a hash map (`profileMap`) where keys are generated from the current call stack using `Profiler::hash()`.

During execution, the Nelson evaluator automatically invokes:
- **`Profiler::tic()`** – Returns a high-resolution timestamp when entering a function or line (lines 74–81 in [`Profiler.cpp`](https://github.com/nelson-lang/nelson/blob/main/Profiler.cpp)).
- **`Profiler::toc(tic, stack)`** – Calculates elapsed nanoseconds and updates the corresponding entry in `profileMap` (lines 83–105).

### Data Aggregation and Reporting

When you request results via `profile('info')`, the profiler:
1. Walks `profileMap` to collapse duplicate entries
2. Sorts data according to the specified criterion (`SORT_BY_TOTALTIME`, `SORT_BY_LINE`, etc.)
3. Returns a struct array with fields: `FunctionName`, `Filename`, `LinePosition`, `NumCalls`, `TotalTime`, `PerCall`

The `profile('show', sortOption, nbLines)` command formats this data into a console table, while `profsave` generates a browsable HTML report.

## Step-by-Step Workflow to Profile Nelson Code

Follow this sequence to accurately measure performance characteristics of your Nelson scripts.

### 1. Activate the Profiler

Clear any previous session and start timing:

```matlab
profile on

```

This executes `Profiler::on()` which resets the internal hash map and sets the active flag.

### 2. Execute the Target Code

Run the functions or scripts you want to analyze. The evaluator automatically wraps each call with `tic`/`toc` pairs:

```matlab
for k = 1:1000
    computeIntensiveTask(k);
end

```

### 3. Stop Data Collection

Halt the profiler to freeze the statistics:

```matlab
profile off

```

This calls `Profiler::off()`, stopping the timing hooks while preserving the collected data in `profileMap`.

### 4. Analyze the Results

Retrieve structured data for programmatic analysis:

```matlab
p = profile('info');
disp(p(1))  % Display the hottest function

```

Or view a formatted table sorted by total execution time:

```matlab
profile('show', 'totaltime', 10)

```

Available sort options include: `"totaltime"`, `"line"`, `"percalls"`, `"filename"`, `"function"`, `"nbcalls"`, and `"nfl"` (name-file-line).

### 5. Export for External Review

Generate an HTML report with per-file breakdowns:

```matlab
p = profile('info');
profsave(p, '/tmp/myProfileReport')

```

Open [`index.html`](https://github.com/nelson-lang/nelson/blob/main/index.html) in the specified directory to browse the results.

## Practical Code Examples

### Basic Profiling Session

This complete example demonstrates profiling a custom function:

```matlab
% Define a function with uneven workload
function result = unevenWork(n)
    result = 0;
    for i = 1:n
        if mod(i, 2) == 0
            pause(0.001);  % Simulate even-numbered delay
        end
        result = result + i;
    end
end

% Profile the execution
profile on
for k = 1:100
    unevenWork(k);
end
profile off

% Display top 5 time consumers
profile('show', 'totaltime', 5)

```

### Programmatic Analysis of Profile Data

Extract specific metrics for automated optimization testing:

```matlab
p = profile('info');

% Find the function with maximum total time
[~, idx] = max([p.TotalTime]);
fprintf('Bottleneck: %s in %s\n', p(idx).FunctionName, p(idx).Filename);

% Calculate average calls per function
avgCalls = mean([p.NumCalls]);
fprintf('Average call count: %.1f\n', avgCalls);

```

### Advanced C++ Integration

For builtin developers extending Nelson, manually instrument critical sections:

```cpp
#include "Profiler.hpp"

void optimizedAlgorithm(Evaluator* eval, const ArrayOf& input)
{
    // Access the singleton
    Nelson::Profiler* pr = Nelson::Profiler::getInstance();
    
    // Ensure profiling is active
    if (pr->isActive()) {
        uint64_t tic = pr->tic();
        
        // ... perform algorithm work ...
        
        // Build stack info (normally provided by evaluator)
        std::vector<StackEntry> stack = eval->getCallStack();
        pr->toc(tic, stack);
    }
}

```

## Key Implementation Files

Understanding the source structure helps when interpreting profiler behavior or contributing improvements.

| File Path | Purpose |
|-----------|---------|
| [`modules/profiler/builtin/cpp/profileBuiltin.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/builtin/cpp/profileBuiltin.cpp) | Implements the `profile` command dispatcher, handling subcommands like `on`, `off`, `show`, and `info`. |
| [`modules/profiler/src/cpp/Profiler.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/src/cpp/Profiler.cpp) | Core singleton implementation containing `on()`, `off()`, `tic()`, `toc()`, `info()`, `show()`, and `save()` methods. |
| [`modules/profiler/src/include/Profiler.hpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/src/include/Profiler.hpp) | Header defining the `Profiler` class, `ProfileEntry` struct, and `Profile_Sort_Type` enumeration. |
| [`modules/profiler/help/en_US/xml/profile.xml`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/help/en_US/xml/profile.xml) | Official documentation defining syntax, parameters, and usage examples for the builtin. |
| `modules/profiler/tests/script_to_profile.m` | Test fixture used by the test suite to validate profiler accuracy. |

## Summary

- **Activate profiling** with `profile on` to begin collecting timing data; the Nelson evaluator automatically instruments function calls and script lines.
- **Control overhead** by limiting profiled sections with `profile off` when measurement is complete, preserving data in the singleton `Profiler` instance.
- **Analyze results** using `profile('info')` for structured data or `profile('show', sortOption, n)` for formatted console output sorted by time, calls, or location.
- **Export reports** via `profsave` to generate HTML files with per-function breakdowns for external review.
- **Extend functionality** by referencing [`modules/profiler/src/cpp/Profiler.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/src/cpp/Profiler.cpp) and [`Profiler.hpp`](https://github.com/nelson-lang/nelson/blob/main/Profiler.hpp) to understand the `tic`/`toc` timing hooks and hash-based aggregation mechanism.

## Frequently Asked Questions

### How do I reset the profiler data between different code sections?

Call `profile on` again while the profiler is already running. According to the implementation in [`modules/profiler/src/cpp/Profiler.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/profiler/src/cpp/Profiler.cpp) (lines 44–56), the `on()` method automatically invokes `clear()`, which resets the `profileMap` hash map and deletes all previous `ProfileEntry` records. This ensures that subsequent measurements are not contaminated by earlier runs.

### What is the difference between `profile('info')` and `profile('show')`?

`profile('info')` returns a struct array containing raw profiling data (`FunctionName`, `Filename`, `LinePosition`, `NumCalls`, `TotalTime`, `PerCall`) that you can manipulate programmatically, as implemented in `Profiler::info()`. In contrast, `profile('show', sortOption, nbLines)` calls `Profiler::show()`, which formats this data into a human-readable console table with headers and limited row counts, suitable for quick inspection during interactive sessions.

### Can I profile individual lines within a function, or only whole functions?

The Nelson profiler captures data at the **line level** inside scripts and functions. When the evaluator executes code with profiling enabled, it invokes `Profiler::tic()` before and `Profiler::toc()` after each line or function call, recording the specific line position (`LinePosition`) in the `ProfileEntry`. This granularity allows you to identify specific bottlenecks within large functions, not just which functions are slow overall.

### How do I export profiling results for sharing with team members?

Use the **`profsave`** builtin function to generate a self-contained HTML report. After collecting data with `p = profile('info')`, execute `profsave(p, 'destinationFolder')`. This invokes the `Profiler::save()` method (starting at line 85 in [`Profiler.cpp`](https://github.com/nelson-lang/nelson/blob/main/Profiler.cpp)), which writes an [`index.html`](https://github.com/nelson-lang/nelson/blob/main/index.html) file plus per-file detail pages that can be opened in any web browser without requiring Nelson to be installed.