LLM Notice: This documentation site supports content negotiation for AI agents. Request any page with Accept: text/markdown or Accept: text/plain header to receive Markdown instead of HTML. Alternatively, append ?format=md to any URL. All markdown files are available at /md/ prefix paths. For all content in one file, visit /llms-full.txt
Skip to main content

Cadence Computation Profiling

This guide provides comprehensive instructions for using the computation profiling and reporting features in the Flow Emulator. These tools help Cadence developers analyze and optimize their smart contracts by understanding computational costs and identifying performance bottlenecks.

Overview

When developing smart contracts on Flow, understanding computational costs is essential for:

  • Performance Optimization: Identify slow operations and optimize your code
  • Cost Awareness: Understand how much computation your transactions and scripts consume
  • Bottleneck Identification: Pinpoint exactly where your code spends the most resources

The Flow Emulator provides two complementary tools for this purpose:

FeatureOutputBest For
Computation ReportingJSON report with detailed intensitiesQuick numerical analysis, CI/CD integration, automated testing
Computation Profilingpprof profileVisual analysis (e.g. flame graphs), deep-dive debugging, call stack exploration
note

Before getting started, make sure you have the Flow CLI installed.

Computation Reporting

Computation reporting provides a JSON-based view of computational costs for all executed transactions and scripts.

Enabling Computation Reporting

Start the emulator with the --computation-reporting flag:


_10
flow emulator --computation-reporting

info

For more accurate computation numbers that reflect real network conditions, consider using emulator fork testing. Forking allows you to profile against actual Mainnet or Testnet state without requiring a full emulator environment setup.

Viewing Computation Reports

Once enabled, access the computation report at:


_10
http://localhost:8080/emulator/computationReport

The report returns a JSON object with the following structure:


_30
{
_30
"scripts": {
_30
"<script-id>": {
_30
"path": "scripts/myScript.cdc",
_30
"computation": 1250,
_30
"intensities": {
_30
"Statement": 45,
_30
"FunctionInvocation": 12,
_30
"GetValue": 8
_30
},
_30
"memory": 2048,
_30
"source": "access(all) fun main(): Int { ... }",
_30
"arguments": ["0x1"]
_30
}
_30
},
_30
"transactions": {
_30
"<transaction-id>": {
_30
"path": "transactions/myTransaction.cdc",
_30
"computation": 3500,
_30
"intensities": {
_30
"Statement": 120,
_30
"EmitEvent": 5,
_30
"SetValue": 15
_30
},
_30
"memory": 8192,
_30
"source": "transaction { ... }",
_30
"arguments": ["100.0"]
_30
}
_30
}
_30
}

Report Fields

FieldDescription
pathSource file path (set via #sourceFile pragma)
computationTotal computation units used
intensitiesCount of each operation type performed
memoryEstimated memory usage
sourceOriginal Cadence source code
argumentsArguments passed to the transaction/script

Understanding Computation Intensities

The intensities map shows how many times each operation type was performed. The keys are human-readable names like Statement, Loop, FunctionInvocation, GetValue, SetValue, EmitEvent, etc.

The total computation value is calculated by multiplying each intensity by its corresponding weight (defined by the network) and summing the results. When optimizing, look for operations with high counts - reducing these will lower your total computation cost.

Computation Profiling (pprof)

Computation profiling generates pprof-compatible profiles that can be visualized as flame graphs, providing a powerful way to understand your code's execution patterns.

Installing pprof

To visualize computation profiles, you'll need the pprof tool. See the pprof installation guide for instructions.

Enabling Computation Profiling

Start the emulator with the --computation-profiling flag:


_10
flow emulator --computation-profiling

Note: You can enable both --computation-reporting and --computation-profiling simultaneously if you need both types of analysis.

Downloading the Profile

After executing transactions and scripts, download the profile from:


_10
http://localhost:8080/emulator/computationProfile

This downloads a profile.pprof file containing the aggregated computation profile.

Using curl:


_10
curl -o profile.pprof http://localhost:8080/emulator/computationProfile

Viewing Profiles with pprof

Open the profile in an interactive web interface:


_10
pprof -http=:8081 profile.pprof

Then navigate to http://localhost:8081 in your browser.

Available Views

The pprof web interface provides several visualization options:

ViewDescription
Flame GraphVisual representation of call stacks with computation costs
GraphDirected graph showing call relationships
TopList of functions sorted by computation usage
SourceSource code annotated with computation costs
PeekCallers and callees of selected functions

Viewing Source Code in pprof

To see Cadence source code annotated with computation costs:

  1. Download all deployed contracts:


    _10
    curl -o contracts.zip http://localhost:8080/emulator/allContracts

  2. Extract the ZIP file into a contracts folder:


    _10
    mkdir -p contracts
    _10
    unzip contracts.zip -d contracts

  3. Run pprof with the source path:


    _10
    pprof -source_path=contracts -http=:8081 profile.pprof

Now when you view the "Source" tab in pprof, you'll see your Cadence code with line-by-line computation annotations.

Resetting Computation Profiles

To clear the accumulated profile data (useful between test runs):


_10
curl -X PUT http://localhost:8080/emulator/computationProfile/reset

Using Source File Pragmas

The #sourceFile pragma improves computation report readability by associating your code with meaningful file paths. Without it, reports show generic identifiers.

Note: The #sourceFile pragma currently only affects Computation Reporting (JSON reports). It does not change filenames in Computation Profiling (pprof profiles).

Usage

Add the pragma at the beginning of your transaction or script:


_10
#sourceFile("transactions/transfer_tokens.cdc")
_10
_10
transaction(amount: UFix64, recipient: Address) {
_10
prepare(signer: auth(Storage) &Account) {
_10
// Transfer logic
_10
}
_10
}

For scripts:


_10
#sourceFile("scripts/get_balance.cdc")
_10
_10
access(all) fun main(address: Address): UFix64 {
_10
return getAccount(address).balance
_10
}

Benefits

  • Computation reports show file paths instead of generic IDs
  • Easier to correlate computation costs with source files
  • Useful for tracking costs across multiple files in a project

Practical Examples

Profiling a Simple Transaction

Let's profile a simple NFT minting transaction.

1. Start the emulator with profiling enabled:


_10
flow emulator --computation-profiling --computation-reporting

2. Create a transaction file (transactions/mint_nft.cdc):


_14
#sourceFile("transactions/mint_nft.cdc")
_14
_14
import NonFungibleToken from 0xf8d6e0586b0a20c7
_14
import ExampleNFT from 0xf8d6e0586b0a20c7
_14
_14
transaction {
_14
prepare(signer: auth(Storage) &Account) {
_14
let collection = signer.storage.borrow<&ExampleNFT.Collection>(
_14
from: ExampleNFT.CollectionStoragePath
_14
) ?? panic("Could not borrow collection")
_14
_14
collection.deposit(token: <- ExampleNFT.mintNFT())
_14
}
_14
}

3. Execute the transaction:


_10
flow transactions send transactions/mint_nft.cdc

4. View the computation report:


_10
curl http://localhost:8080/emulator/computationReport | jq

5. Analyze with pprof:


_10
curl -o profile.pprof http://localhost:8080/emulator/computationProfile
_10
pprof -http=:8081 profile.pprof

Identifying Performance Bottlenecks

Consider a script that iterates over a large collection:


_21
#sourceFile("scripts/find_expensive.cdc")
_21
_21
access(all) fun main(address: Address): [UInt64] {
_21
let account = getAccount(address)
_21
let collection = account.capabilities.borrow<&{NonFungibleToken.Collection}>(
_21
/public/NFTCollection
_21
) ?? panic("Could not borrow collection")
_21
_21
let ids = collection.getIDs()
_21
var result: [UInt64] = []
_21
_21
// Potentially expensive loop
_21
for id in ids {
_21
let nft = collection.borrowNFT(id)
_21
if nft != nil {
_21
result.append(id)
_21
}
_21
}
_21
_21
return result
_21
}

After profiling, you might see high values for:

  • Loop: Many iterations
  • FunctionInvocation: Repeated borrowNFT calls
  • GetValue: Multiple storage reads

Optimization strategies:

  • Use pagination to limit iterations per call
  • Cache results when possible
  • Consider restructuring data for more efficient access

Comparing Computation Costs

You can compare two implementation approaches by downloading and comparing profiles:

1. Reset the profile:


_10
curl -X PUT http://localhost:8080/emulator/computationProfile/reset

2. Run implementation A and save the profile:


_10
flow transactions send approach_a.cdc
_10
curl -o profile_a.pprof http://localhost:8080/emulator/computationProfile

3. Reset and test implementation B:


_10
curl -X PUT http://localhost:8080/emulator/computationProfile/reset
_10
flow transactions send approach_b.cdc
_10
curl -o profile_b.pprof http://localhost:8080/emulator/computationProfile

4. Compare using pprof:


_10
# View profile A
_10
pprof -top profile_a.pprof
_10
_10
# View profile B
_10
pprof -top profile_b.pprof

The -top view shows total computation, making it easy to compare the two approaches.

API Reference

EndpointMethodDescription
/emulator/computationReportGETView computation report (JSON)
/emulator/computationProfileGETDownload pprof profile
/emulator/computationProfile/resetPUTReset computation profile
/emulator/allContractsGETDownload all deployed contracts (ZIP)

Example API Calls


_11
# Get computation report
_11
curl http://localhost:8080/emulator/computationReport
_11
_11
# Download pprof profile
_11
curl -o profile.pprof http://localhost:8080/emulator/computationProfile
_11
_11
# Reset computation profile
_11
curl -X PUT http://localhost:8080/emulator/computationProfile/reset
_11
_11
# Download all contracts
_11
curl -o contracts.zip http://localhost:8080/emulator/allContracts

Troubleshooting

Profile endpoint returns 404

Problem: Accessing /emulator/computationProfile returns a 404 error.

Solution: Make sure you started the emulator with --computation-profiling:


_10
flow emulator --computation-profiling

Empty profile

Problem: The downloaded profile is empty or has no useful data.

Solution: Make sure you've executed at least one transaction or script after starting the emulator. The profile only contains data for executed code.

Source code not showing in pprof

Problem: The pprof source view doesn't display your Cadence code.

Solution:

  1. Download the contracts ZIP: curl -o contracts.zip http://localhost:8080/emulator/allContracts
  2. Extract to a contracts folder in your working directory
  3. Run pprof with the source path: pprof -source_path=contracts -http=:8081 profile.pprof

High memory usage

Problem: The emulator uses increasing memory over time.

Solution: Periodically reset computation profiles to free accumulated data:


_10
curl -X PUT http://localhost:8080/emulator/computationProfile/reset

Computation reports not showing file paths

Problem: The path field in computation reports is empty.

Solution: Add the #sourceFile pragma to your transactions and scripts:


_10
#sourceFile("path/to/your/file.cdc")

Code Coverage Reporting

The emulator also supports Cadence code coverage reporting, which complements computation profiling:


_10
flow emulator --coverage-reporting

View coverage at: http://localhost:8080/emulator/codeCoverage

Learn more in the Flow Emulator documentation.

Debugger

For step-through debugging of Cadence code, use the #debug() pragma:


_10
#debug()
_10
_10
transaction {
_10
prepare(signer: &Account) {
_10
// Execution pauses here for debugging
_10
}
_10
}

This works with VSCode and Flow CLI debugging tools.