11---
2- title : Profiling and Optimizing Contracts
2+ title : Profiling Transactions
33sidebar_position : 2
4- tags : [contracts, profiling, optimization ]
5- description : Step-by-step guide to profiling Aztec transactions and optimizing contract performance for efficient proof generation .
4+ tags : [contracts, profiling]
5+ description : How to profile Aztec transactions and identify performance bottlenecks .
66---
77
8- This guide shows you how to profile your Aztec transactions to identify bottlenecks and optimize gas usage .
8+ This guide shows you how to profile Aztec transactions to understand gate counts and identify optimization opportunities .
99
1010## Prerequisites
1111
@@ -16,241 +16,113 @@ This guide shows you how to profile your Aztec transactions to identify bottlene
1616
1717## Profile with aztec-wallet
1818
19- ### Step 1: Import test accounts
19+ Use the ` profile ` command instead of ` send ` to get detailed gate counts:
2020
2121``` bash
22+ # Import test accounts
2223aztec-wallet import-test-accounts
23- ```
24-
25- ### Step 2: Deploy your contract
2624
27- ``` bash
25+ # Deploy your contract
2826aztec-wallet deploy MyContractArtifact \
2927 --from accounts:test0 \
30- --args < constructor_args > \
28+ --args [CONSTRUCTOR_ARGS] \
3129 -a mycontract
32- ```
33-
34- ### Step 3: Set up initial state
35-
36- ``` bash
37- aztec-wallet send setup_state \
38- -ca mycontract \
39- --args < setup_args> \
40- -f test0
41- ```
42-
43- ### Step 4: Profile a transaction
4430
45- Instead of ` send ` , use ` profile ` with the same parameters:
46-
47- ``` bash
48- aztec-wallet profile private_function \
31+ # Profile a function call
32+ aztec-wallet profile my_function \
4933 -ca mycontract \
50- --args < function_args > \
34+ --args [FUNCTION_ARGS] \
5135 -f accounts:test0
5236```
5337
54- ### Step 5: Analyze the output
38+ ### Reading the output
5539
56- ``` bash
57- Gate count per circuit:
58- SchnorrAccount:entrypoint Gates: 21,724 Acc: 21,724
59- private_kernel_init Gates: 45,351 Acc: 67,075
60- MyContract:private_function Gates: 31,559 Acc: 98,634
61- private_kernel_inner Gates: 78,452 Acc: 177,086
62- private_kernel_reset Gates: 91,444 Acc: 268,530
63- private_kernel_tail Gates: 31,201 Acc: 299,731
64-
65- Total gates: 299,731
66- ```
40+ The profile command outputs a per-circuit breakdown:
6741
68- The output shows:
42+ ``` text
43+ Per circuit breakdown:
6944
70- - Gate count per circuit component
71- - Accumulated gate count
72- - Total gates for the entire transaction
73-
74- ## Profile with aztec.js
45+ Function name Time Gates Subtotal
46+ --------------------------------------------------------------------------------
47+ - SchnorrAccount:entrypoint 12.34ms 21,724 21,724
48+ - private_kernel_init 23.45ms 45,351 67,075
49+ - MyContract:my_function 15.67ms 31,559 98,634
50+ - private_kernel_inner 34.56ms 78,452 177,086
7551
76- :::tip Profile Modes
77-
78- - ` gates ` : Shows gate counts per circuit
79- - ` execution-steps ` : Detailed execution trace
80- - ` full ` : Complete profiling information
81-
82- :::
83-
84- ### Step 1: Profile a transaction
85-
86- ``` javascript
87- const result = await contract .methods
88- .my_function (args)
89- .profile ({
90- from: address,
91- profileMode: ' gates' ,
92- skipProofGeneration: false
93- });
94-
95- console .log (' Gate count:' , result .gateCount );
96- ```
97-
98- ### Step 2: Profile deployment
99-
100- ``` javascript
101- const deploy = await Contract .deploy (args).profile ({ from: address, profileMode: ' full' });
52+ Total gates: 177,086 (Biggest circuit: private_kernel_inner -> 78,452)
10253```
10354
104- :::warning Experimental
105- Flamegraph generation is experimental and may not be available in all versions.
106- :::
55+ Key metrics:
10756
108- ## Generate flamegraphs (if available)
109-
110- ### Generate and view
111-
112- ``` bash
113- # Compile first
114- aztec compile
115-
116- # Generate flamegraph
117- aztec flamegraph target/contract.json function_name
118-
119- # Serve locally
120- SERVE=1 aztec flamegraph target/contract.json function_name
121- ```
57+ - ** Gates** : Circuit complexity for each function
58+ - ** Subtotal** : Accumulated gate count
59+ - ** Time** : Execution time per circuit
12260
123- :::info Reading Flamegraphs
124-
125- - ** Width** = Time in operation
126- - ** Height** = Call depth
127- - ** Wide sections** = Optimization targets
128-
129- :::
130-
131- ## Common optimizations
132-
133- :::info Key Metrics
134-
135- - ** Gate count** : Circuit complexity
136- - ** Kernel overhead** : Per-function cost
137- - ** Storage access** : Read/write operations
138-
139- :::
140-
141- :::tip Optimization Pattern
142- Batch operations to reduce kernel circuit overhead.
143- :::
61+ ## Profile with aztec.js
14462
145- ``` rust
146- // ❌ Multiple kernel invocations
147- for i in 0 .. 3 {
148- transfer_single (amounts [i ], recipients [i ]);
149- }
63+ ``` typescript
64+ const result = await contract .methods .my_function (args ).profile ({
65+ from: walletAddress ,
66+ profileMode: " full" ,
67+ skipProofGeneration: true ,
68+ });
15069
151- // ✅ Single kernel invocation
152- for i in 0 .. 3 {
153- let note = Note :: new (amounts [i ], recipients [i ]);
154- storage . notes. at (recipients [i ]). insert (note );
70+ // Access gate counts from execution steps
71+ for (const step of result .executionSteps ) {
72+ console .log (` ${step .functionName }: ${step .gateCount } gates ` );
15573}
156- ```
157-
158- :::tip Storage Optimization
159- Group storage reads to reduce overhead.
160- :::
16174
162- ``` rust
163- // Read once, use multiple times
164- let values = [storage . v1. get (), storage . v2. get (), storage . v3. get ()];
165- for v in values {
166- assert (v > 0 );
167- }
75+ // Access timing information
76+ console .log (" Total time:" , result .stats .timings .total , " ms" );
16877```
16978
170- ### Minimize note operations
171-
172- :::tip Note Aggregation
173- Combine multiple small notes into fewer larger ones to reduce proving overhead.
174- :::
79+ ### Profile modes
17580
176- ``` rust
177- // ❌ Many small notes = high overhead
178- for value in values {
179- storage . notes. insert (Note :: new (value , owner ));
180- }
81+ - ` gates ` : Gate counts per circuit
82+ - ` execution-steps ` : Detailed execution trace with bytecode and witnesses
83+ - ` full ` : Complete profiling information (gates + execution steps)
18184
182- // ✅ Single aggregated note = lower overhead
183- let total = values . reduce (| a , b | a + b );
184- storage . notes. insert (Note :: new (total , owner ));
185- ```
85+ Set ` skipProofGeneration: true ` for faster iteration when you only need gate counts.
18686
187- ## Profile different scenarios
87+ ## Generate flamegraphs with noir-profiler
18888
189- ### Profile with different inputs
89+ For deeper analysis of individual contract functions, use the Noir profiler to generate interactive flamegraphs. The profiler is installed automatically with Nargo (starting noirup v0.1.4).
19090
19191``` bash
192- # Small values
193- aztec-wallet profile function -ca mycontract --args 10 -f test0
194-
195- # Large values
196- aztec-wallet profile function -ca mycontract --args 1000000 -f test0
197- ```
198-
199- ### Profile execution modes
200-
201- ``` javascript
202- // Profile gates only
203- await contract .methods .function ().profile ({ profileMode: ' gates' });
204-
205- // Profile execution steps
206- await contract .methods .function ().profile ({ profileMode: ' execution-steps' });
207-
208- // Full profile
209- await contract .methods .function ().profile ({ profileMode: ' full' });
210- ```
92+ # Compile your contract first
93+ aztec compile
21194
212- ### Skip proof generation for faster iteration
95+ # Generate a gates flamegraph (requires bb backend)
96+ noir-profiler gates \
97+ --artifact-path ./target/my_contract-MyContract.json \
98+ --backend-path bb \
99+ --output ./target
213100
214- ``` javascript
215- await contract .methods .function ().profile ({
216- profileMode: ' gates' ,
217- skipProofGeneration: true // Faster but less accurate
218- });
101+ # Generate an ACIR opcodes flamegraph
102+ noir-profiler opcodes \
103+ --artifact-path ./target/my_contract-MyContract.json \
104+ --output ./target
219105```
220106
221- ## Interpret profiling results
222-
223- ### Gate count guidelines
224-
225- - ** < 50,000 gates** : Excellent performance
226- - ** 50,000 - 200,000 gates** : Acceptable for most use cases
227- - ** 200,000 - 500,000 gates** : May cause delays, consider optimizing
228- - ** > 500,000 gates** : Requires optimization for production
229-
230- ### Common optimization targets
231-
232- 1 . ** private_kernel_inner** - Reduce nested function calls
233- 2 . ** private_kernel_reset** - Minimize note nullifications
234- 3 . ** Contract functions** - Optimize computation logic
235- 4 . ** private_kernel_tail** - Reduce public function calls
236-
237- ## Best practices
107+ Open the generated ` .svg ` file in a browser for an interactive view where:
238108
239- ### Development workflow
109+ - ** Width** represents gate count or opcode count
110+ - ** Height** represents call stack depth
111+ - ** Wide sections** indicate optimization targets
240112
241- 1 . ** Profile early** - Establish baseline metrics
242- 2 . ** Profile often** - Check impact of changes
243- 3 . ** Profile realistically** - Use production-like data
244- 4 . ** Document findings** - Track optimization progress
113+ For detailed usage, see the [ Noir profiler documentation] ( https://noir-lang.org/docs/tooling/profiler ) .
245114
246- ### Optimization priorities
115+ ## Gate count guidelines
247116
248- 1 . ** User-facing functions** - Optimize most-used features first
249- 2 . ** Critical paths** - Focus on transaction bottlenecks
250- 3 . ** Batch operations** - Combine related operations
251- 4 . ** Cache calculations** - Store reusable results
117+ | Gate Count | Assessment |
118+ | ----------------- | --------------------- |
119+ | < 50,000 | Excellent |
120+ | 50,000 - 200,000 | Acceptable |
121+ | 200,000 - 500,000 | Consider optimizing |
122+ | > 500,000 | Requires optimization |
252123
253124## Next steps
254125
255- - Learn about [ gas optimization techniques] ( ../../../foundational-topics/transactions.md )
256- - Review [ benchmarking best practices] ( ../../how_to_test_contracts.md )
126+ - [ Writing efficient contracts] ( ./writing_efficient_contracts.md ) - optimization strategies and examples
127+ - [ Transaction lifecycle] ( ../../../foundational-topics/transactions.md )
128+ - [ Testing contracts] ( ../../how_to_test_contracts.md )
0 commit comments