Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ properties:
cpu_ref_cycles:
type: [integer, "null"]
description: number of reference cycles executed
execution_time_millis:
type: integer
description: execution time in milliseconds
required:
- data
- events
Expand All @@ -51,6 +54,4 @@ required:
- tx_index
- txid
- vm_error
- cpu_instructions
- cpu_cycles
- cpu_ref_cycles
- execution_time_millis
17 changes: 14 additions & 3 deletions stackslib/src/net/api/blockreplay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

use std::time::{Duration, Instant};

use clarity::vm::costs::ExecutionCost;
use clarity::vm::Value;
use regex::{Captures, Regex};
Expand Down Expand Up @@ -261,6 +263,8 @@ where
for (i, tx) in transactions.iter().enumerate() {
let tx_len = tx.tx_len();

let start = Instant::now();

let mut profiler: Option<BlockReplayProfiler> = None;
let mut profiler_result = BlockReplayProfilerResult::default();

Expand All @@ -285,7 +289,7 @@ where

let err = match tx_result {
TransactionResult::Success(tx_result) => {
txs_receipts.push((tx_result.receipt, profiler_result));
txs_receipts.push((tx_result.receipt, start.elapsed(), profiler_result));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

computing execution_time_millis sounds like a profiler feature. Why not assigning this responsibility to BlockReplayProfiler to centralize all this kind of data collection? It could be available for both linux and not linux build.

Ok(())
}
TransactionResult::ProcessingError(e) => {
Expand Down Expand Up @@ -318,8 +322,12 @@ where
let mut rpc_replayed_block =
RPCReplayedBlock::from_block(&replayed_block, block_fees, tenure_id, parent_block_id);

for (receipt, profiler_result) in &txs_receipts {
let transaction = RPCReplayedBlockTransaction::from_receipt(receipt, &profiler_result);
for (receipt, execution_duration, profiler_result) in &txs_receipts {
let transaction = RPCReplayedBlockTransaction::from_receipt(
receipt,
execution_duration,
&profiler_result,
);
rpc_replayed_block.transactions.push(transaction);
}

Expand Down Expand Up @@ -394,11 +402,13 @@ pub struct RPCReplayedBlockTransaction {
pub cpu_instructions: Option<u64>,
pub cpu_cycles: Option<u64>,
pub cpu_ref_cycles: Option<u64>,
pub execution_time_millis: u64,
}

impl RPCReplayedBlockTransaction {
pub fn from_receipt(
receipt: &StacksTransactionReceipt,
execution_duration: &Duration,
profiler_result: &BlockReplayProfilerResult,
) -> Self {
let events = if receipt.post_condition_aborted {
Expand Down Expand Up @@ -437,6 +447,7 @@ impl RPCReplayedBlockTransaction {
cpu_instructions: profiler_result.cpu_instructions,
cpu_cycles: profiler_result.cpu_cycles,
cpu_ref_cycles: profiler_result.cpu_ref_cycles,
execution_time_millis: execution_duration.as_millis() as u64,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be worth it to use nanos resolutions instead? I know this is a raw profiling, but just to avoid 0 in case a tx takes less then 1ms.

Comment on lines 447 to +450
Copy link
Copy Markdown
Contributor

@federico-stacks federico-stacks May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest organizing the response under a profiler field, aggregating all the current profiling-related fields beneath it. This would allow us to simply mark the parent field as nullable, while also making the structure cleaner, easier to evolve and piloted by the RPC request profiler parameter.

Additionally, this approach would integrate nicely with the refactoring proposed in #7205 (comment).

}
}
}
Expand Down
Loading