Acton
Testing

Gas Profiling with Snapshots

Learn how to profile gas and fees of transaction chains with --snapshot and baseline comparison

Gas profiling helps you track performance regressions in tests by measuring gas and fee metrics for opcodes and full transaction chains.

What gets profiled

When profiling is enabled, Acton prints:

  • Opcode gas table (min/max/avg per opcode or message opcode name)
  • Chain gas & fees summary (per test)
  • Chain gas & fees details (per trace inside each test)

For chain-level metrics, Acton tracks:

  • transaction count
  • gas used
  • gas fee
  • forward fee
  • total fee

Quick Start

1. Create a baseline snapshot

acton test --snapshot gas-baseline.json

This runs tests and saves a JSON snapshot with opcode and trace-chain stats.

 GAS USAGE

───────────────────────────────────────────────
 Opcode            Min Gas   Max Gas   Avg Gas
───────────────────────────────────────────────
 IncreaseCounter      1536      1536      1536
 ResetCounter         1349      1349      1349
 0x00000999            680       680       680

 CHAIN GAS & FEES SUMMARY

──────────────────────────────────────────────────────────────────────────────────────────────────
 Test                    Traces   Tx   Gas Used   Gas Fee         Forward Fee       Total Fee
──────────────────────────────────────────────────────────────────────────────────────────────────
 test increase counter        4    4       2789   0.0011156 TON   0.002000284 TON   0.0011156 TON
 test reset counter           5    5       4138   0.0016552 TON   0.002266953 TON   0.0016552 TON
 test unknown message         5    5       2568   0.0010272 TON   0.002266953 TON   0.0010272 TON

2. Compare current run with baseline

acton test --baseline-snapshot gas-baseline.json

This prints comparison tables with diffs for opcode gas and chain metrics.

 GAS USAGE COMPARISON

Baseline: gas-baseline.json (3 opcodes, captured 2026-02-28 14:49:39 UTC)

────────────────────────────────────────────────────────
 Opcode            Baseline   Current   Diff   % Change
────────────────────────────────────────────────────────
 IncreaseCounter       1536      1398   -138      -9.0%
 ResetCounter          1349      1349     +0      +0.0%
 0x00000999             680       680     +0      +0.0%

 CHAIN GAS & FEES SUMMARY COMPARISON

Baseline: gas-baseline.json (14 traces, captured 2026-02-28 14:49:39 UTC)

──────────────────────────────────────────────────────────────────────────────────
 Test                    Traces   Tx   Gas Used   Gas Fee          Total Fee
──────────────────────────────────────────────────────────────────────────────────
 test increase counter        4    4       2789    0.0011156 TON    0.0011156 TON
                              4    4       2651    0.0010604 TON    0.0010604 TON
                                           -138   -0.0000552 TON   -0.0000552 TON
 test reset counter           5    5       4138    0.0016552 TON    0.0016552 TON
                              5    5       4000       0.0016 TON       0.0016 TON
                                           -138   -0.0000552 TON   -0.0000552 TON
 test unknown message         5    5       2568    0.0010272 TON    0.0010272 TON
 CHAIN GAS & FEES · test increase counter

────────────────────────────────────────────────────────────────────────────────────────────
 Trace             Tx Count   Gas Used   Gas Fee          Fwd Fee            Total Fee
────────────────────────────────────────────────────────────────────────────────────────────
 Trace 1                  1        309    0.0001236 TON    0.000539205 TON    0.0001236 TON
 Trace 2                  1        309    0.0001236 TON    0.000547738 TON    0.0001236 TON
 Trace 3                  1        635     0.000254 TON    0.000646672 TON     0.000254 TON
                          1        635     0.000254 TON    0.000629605 TON     0.000254 TON
                                                          -0.000017067 TON
 increase counter         1       1536    0.0006144 TON    0.000266669 TON    0.0006144 TON
                          1       1398    0.0005592 TON    0.000266669 TON    0.0005592 TON
                                  -138   -0.0000552 TON                      -0.0000552 TON

How to read row groups

In comparison tables, changed chains are shown as baseline row, current row, and diff row.

2.1 Fail CI on drift

Use strict mode to return non-zero exit code when baseline and current profile differ:

acton test --baseline-snapshot gas-baseline.json --fail-on-diff

You can also enable it by default in Acton.toml:

[test]
fail-on-diff = true

3. Update baseline intentionally

If changes are expected, recreate baseline:

acton test --snapshot gas-baseline.json

Compare mode does not overwrite snapshot

If you pass both --snapshot and --baseline-snapshot, Acton runs in compare mode and does not rewrite the snapshot file.

Naming trace chains for readable reports

Chain reports are much easier to read when traces have explicit names.

Use SendResultList.giveName(...) after net.send(...):

import "@acton/emulation/network"

get fun `test transfer flow`() {
    // ...
    val txs = net.send(sender.address, msg);
    txs.giveName("transfer-wallet-to-wallet");
    expect(txs).toHaveAllSuccessfulTxs();
}

Without custom names, traces are shown as Trace 1, Trace 2, and so on.

How snapshot matching works

Baseline comparison is key-based rather than fuzzy.

  • Opcode rows are keyed by the resolved opcode label.
  • If ABI metadata resolves the opcode, the key is the message name such as IncreaseCounter.
  • Otherwise the key falls back to the raw hex opcode such as 0x00000999.

Trace-chain rows are keyed by a stable internal snapshot key:

<test-name>::trace#<1-based trace index>

That key comes from the test name plus the 1-based position of the trace in that test's execution order. trace_name is stored only for display. Renaming a trace with giveName(...) makes reports easier to read, but it does not change how baseline matching works.

Reading comparison output

In baseline comparison mode:

  • New opcodes/traces are shown as NEW
  • Higher usage is highlighted as regression
  • Lower usage is highlighted as improvement
  • Unchanged rows are dimmed

Stabilize test data first

For meaningful diffs, keep tests deterministic: fixed inputs, stable send order, and no random/time-dependent behavior unless explicitly controlled.

Snapshot file format

Gas snapshot is stored as JSON with this high-level structure:

{
  "timestamp": 1772290179,
  "opcodes": {
    "IncreaseCounter": {
      "min_gas": 1536,
      "max_gas": 1536,
      "avg_gas": 1536,
      "samples": 2,
      "all_values": [1536, 1536]
    }
  },
  "trace_chains": {
    "test reset counter::trace#3": {
      "test_name": "test reset counter",
      "trace_name": "Trace 3",
      "tx_count": 1,
      "total_gas_used": 635,
      "total_gas_fees": 254000,
      "total_forward_fees": 646672,
      "total_fees": 254000
    }
  }
}

Useful flags to combine with profiling

# Profile only selected tests
acton test --filter "transfer.*" --snapshot gas-baseline.json

# Profile one suite/file
acton test tests/wallet.test.tolk --baseline-snapshot gas-baseline.json

Troubleshooting

Baseline file is missing or invalid

Default behavior: Acton prints a warning and continues without baseline comparison.

With strict mode (--fail-on-diff or [test].fail-on-diff = true), Acton exits with error.

Snapshot is not created

Snapshot is written only when:

  • --snapshot is set
  • --baseline-snapshot is not set
  • profiling collected at least one opcode or trace-chain metric

Trace names changed but diff mapping is still stable

Trace comparison is matched by stable snapshot key (<test-name>::trace#<index>), while trace_name is used for display.

--fail-on-diff is stricter than the tables

The comparison tables mainly show aggregated numbers such as averages and fee totals. Strict drift detection compares the full snapshot content except for the top-level timestamp.

That means --fail-on-diff treats these as real drift:

  • opcode sample-count changes
  • min_gas / max_gas / avg_gas changes
  • differences in per-opcode all_values
  • per-trace tx_count or fee changes
  • changed trace_name for the same snapshot key

For stable CI baselines, keep both the execution order and the profiled test data deterministic.

Last updated on

On this page