Skip to content

Commit

Permalink
Better profiling support (#36)
Browse files Browse the repository at this point in the history
* store profiling cost

* flamegraph function

* text_concat

* rename to stringify

* Fix

* cow

* output

* refactor

* update

Co-authored-by: Yan Chen <yan.chen@dfinity.org>
  • Loading branch information
chenyan2002 and chenyan-dfinity authored Sep 10, 2022
1 parent 3d4ef3f commit 97cf041
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 326 deletions.
39 changes: 15 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ic-repl"
version = "0.3.3"
version = "0.3.4"
authors = ["DFINITY Team"]
edition = "2018"

Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ ic-repl [--replica [local|ic|url] | --offline [--format [ascii|png]]] --config <
| <id> ( <exp>,* ) // function application
<var> :=
| <id> // variable name
| _ // previous eval of exp is bind to `_`
| _ // previous eval of exp is bind to `_`
<selector> :=
| ? // select opt value
| . <name> // select field name from record or variant value
Expand All @@ -48,7 +48,10 @@ We also provide some built-in functions:
* account(principal): convert principal to account id.
* neuron_account(principal, nonce): convert (principal, nonce) to account in the governance canister.
* file(path): load external file as a blob value.
* wasm_profiling(path): load Wasm module, instrument the code and store as a blob value.
* stringify(exp1, exp2, exp3, ...): Convert all expressions to string and concat. Only supports primitive types.
* output(path, content): Append text content to file path.
* wasm_profiling(path): load Wasm module, instrument the code and store as a blob value. Calling profiled canister binds the cost to variable `__cost_{id}` or `__cost__`.
* flamegraph(canister_id, title, filename): generate flamegraph for the last update call to canister_id, with title and write to `{filename}.svg`.

## Examples

Expand Down
39 changes: 21 additions & 18 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use super::error::pretty_parse;
use super::exp::{str_to_principal, Exp};
use super::exp::Exp;
use super::helper::{did_to_canister_info, fetch_metadata, MyHelper};
use super::token::{ParserError, Tokenizer};
use super::utils::{get_dfx_hsm_pin, resolve_path, str_to_principal};
use anyhow::{anyhow, Context};
use candid::{parser::configs::Configs, parser::value::IDLValue, Principal, TypeEnv};
use ic_agent::Agent;
use pretty_assertions::{assert_eq, assert_ne};
use std::ops::Range;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Instant;
use terminal_size::{terminal_size, Width};
Expand Down Expand Up @@ -60,8 +60,9 @@ impl Command {
helper.env.0.insert(id, IDLValue::Principal(canister_id));
}
Command::Let(id, val) => {
let is_call = val.is_call();
let v = val.eval(helper)?;
helper.env.0.insert(id, v);
bind_value(helper, id, v, is_call, false);
}
Command::Func { name, args, body } => {
helper.func_env.0.insert(name, (args, body));
Expand Down Expand Up @@ -92,11 +93,11 @@ impl Command {
}
Command::Config(conf) => helper.config = Configs::from_dhall(&conf)?,
Command::Show(val) => {
let is_call = val.is_call();
let time = Instant::now();
let v = val.eval(helper)?;
let duration = time.elapsed();
println!("{}", v);
helper.env.0.insert("_".to_string(), v);
bind_value(helper, "_".to_string(), v, is_call, true);
let width = if let Some((Width(w), _)) = terminal_size() {
w as usize
} else {
Expand Down Expand Up @@ -216,19 +217,21 @@ impl std::str::FromStr for Commands {
}
}

pub fn resolve_path(base: &Path, file: &str) -> PathBuf {
let file = PathBuf::from(shellexpand::tilde(file).into_owned());
if file.is_absolute() {
file
fn bind_value(helper: &mut MyHelper, id: String, v: IDLValue, is_call: bool, display: bool) {
if is_call {
let (v, cost) = crate::profiling::may_extract_profiling(v);
if let Some(cost) = cost {
let cost_id = format!("__cost_{}", id);
helper.env.0.insert(cost_id, IDLValue::Int64(cost));
}
if display {
println!("{}", v);
}
helper.env.0.insert(id, v);
} else {
base.join(file)
if display {
println!("{}", v);
}
helper.env.0.insert(id, v);
}
}

fn get_dfx_hsm_pin() -> Result<String, String> {
std::env::var("DFX_HSM_PIN").or_else(|_| {
rpassword::prompt_password("HSM PIN: ")
.context("No DFX_HSM_PIN environment variable and cannot read HSM PIN from tty")
.map_err(|e| e.to_string())
})
}
Loading

0 comments on commit 97cf041

Please sign in to comment.