Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/blueshift-gg/quasar/llms.txt

Use this file to discover all available pages before exploring further.

Quasar provides two commands for inspecting the low-level behavior of your compiled program binary: quasar profile measures how many compute units (CUs) each function consumes and visualizes the results as a flamegraph, and quasar dump disassembles the sBPF bytecode for inspection or debugging. Both commands work against the .so binary in target/deploy/ by default, and both support auto-detection so you rarely need to pass a path explicitly.

quasar profile

quasar profile measures per-function compute-unit cost for your program. If no ELF path is given and no --diff flag is set, it automatically triggers a debug build first (equivalent to quasar build --debug), copies the binary to target/profile/, and then runs the profiler. The results are served as an interactive flamegraph on a local web server at 127.0.0.1:7777.
quasar profile
quasar profile --expand
quasar profile --watch
quasar profile --diff my-other-program
quasar profile --share
quasar profile target/profile/my_program.so

Flags

FlagDescription
ELFPath to a compiled .so (auto-detected from target/deploy/ if omitted)
--diff PROGRAMCompare CU cost against an on-chain program by name
--shareUpload the profile result and get a shareable link
--expandShow full terminal output with all functions
-w, --watchWatch src/ for changes and re-profile automatically
--diff and ELF are mutually exclusive. When using --diff, no local binary is required — the profiler fetches the on-chain program for comparison. --share is also mutually exclusive with --diff.

Auto-Build Behavior

When you run quasar profile without specifying an ELF path, the CLI performs a profile build: it compiles with debug symbols enabled (-C debuginfo=2), copies the resulting .so to target/profile/<name>.so, and then starts the profiler against that binary. You do not need to run quasar build --debug first. If you have already built with debug symbols and want to profile without rebuilding, pass the path explicitly:
quasar profile target/profile/my_program.so

Watch Mode

In watch mode, quasar profile --watch triggers a new debug build and re-profile automatically whenever a file in src/ changes. This gives you a continuously updated view of CU cost as you iterate on your program logic.
quasar profile --watch
# Then edit src/lib.rs — the flamegraph refreshes automatically

Comparing Against an On-Chain Program

Use --diff to compare your local program’s CU profile against an already-deployed program by name:
quasar profile --diff my-old-program
This is useful for validating that a refactor or optimization actually reduces compute usage before deploying an upgrade.

Typical Profiling Workflow

1

Build with debug symbols

quasar build --debug
Debug symbols are required for meaningful per-function attribution in the flamegraph. Without them, most CU cost appears attributed to generic frames.
2

Run the profiler

quasar profile
If you just ran quasar build --debug, pass the binary directly to skip the automatic rebuild:
quasar profile target/deploy/my_program.so
3

Inspect the flamegraph

Open http://127.0.0.1:7777 in your browser. Wider bars represent functions that consume more CUs. Click any frame to zoom in.Use --expand to also see a sorted function list in the terminal:
quasar profile --expand
4

Iterate with watch mode

quasar profile --watch
Edit your source and the flamegraph refreshes automatically after each save.
5

Compare before deploying an upgrade

quasar profile --diff my-program
Confirm that CU usage has decreased (or at worst stayed flat) before pushing the upgrade to mainnet.
Profile before every mainnet deployment. Even small logic changes can have outsized CU impacts due to the sBPF calling conventions and stack frame costs. Use --watch during optimization sprints so you see the effect of every change instantly.

quasar dump

quasar dump disassembles the sBPF bytecode of your compiled program using llvm-objdump from the Solana platform-tools. It requires platform-tools to be installed at ~/.cache/solana/*/platform-tools/llvm/bin/llvm-objdump. The newest installed version is used automatically.
quasar dump
quasar dump --function initialize
quasar dump --source
quasar dump -f entrypoint -S
quasar dump target/deploy/my_program.so

Flags

FlagDescription
ELFPath to a compiled .so (auto-detected from target/deploy/ or target/profile/ if omitted)
-f SYMBOL, --function SYMBOLDisassemble only this symbol (demangled name)
-S, --sourceInterleave Rust source lines with the sBPF instructions (requires a debug build)

Disassembling a Specific Function

To inspect only a single function, pass its demangled symbol name with --function. Symbol names are demangled automatically (C++ / Rust name mangling is reversed):
quasar dump --function initialize
quasar dump --function entrypoint
If the symbol is not found, quasar dump suggests trying a mangled or partial name such as entrypoint.

Interleaving Rust Source

With a debug build, pass -S / --source to annotate each sBPF instruction with the corresponding Rust source line. This makes it much easier to trace the generated code back to your program logic:
# First produce a debug build
quasar build --debug

# Then disassemble with source interleaved
quasar dump --function initialize --source
Source interleaving requires the binary to have been built with debug symbols (quasar build --debug). A release build without debug symbols produces empty source annotations.

Example Output

target/deploy/my_program.so:	file format elf64-bpf

Disassembly of section .text:

0000000000000000 <initialize>:
       0:	bf 16 00 00 00 00 00 00	r6 = r1
       8:	85 10 00 00 06 00 00 00	call 6
      10:	95 00 00 00 00 00 00 00	exit

  sBPF 3 instructions (target/deploy/my_program.so)
At the end of the output, quasar dump prints the total sBPF instruction count for the disassembled section.

quasar lint

quasar lint audits your program’s public surface — instructions, accounts, types, and errors — against a saved snapshot (quasar.lock.json) to catch breaking changes before they reach a deployed upgrade.
quasar lint
quasar lint --update-lock
quasar lint --no-diff
quasar lint --strict

Flags

FlagDescription
--update-lockWrite the current program surface to quasar.lock.json
--no-diffSkip comparison against quasar.lock.json even when it exists
--strictTreat warnings and info findings as failures

quasar.lock.json

The lock file records a snapshot of your program’s public interface: instruction discriminators, account layouts, and error codes. Once a lock file exists, every subsequent quasar build and quasar lint compares the current surface against it and flags:
  • Removed instructions or accounts (breaking change for existing clients)
  • Changed discriminators (data corruption risk)
  • New required accounts added to existing instructions
When you intentionally change the program surface (adding an instruction, for example), update the lock file:
quasar lint --update-lock
Then commit quasar.lock.json alongside your source changes so reviewers can see exactly what changed.
quasar build automatically runs quasar lint in non-strict mode as part of every build. Use quasar lint --strict as a pre-deploy gate in CI to treat any finding as a hard failure.

Build docs developers (and LLMs) love