mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 03:21:44 +03:00
profiling graphs: fall back to demo data (#3746)
When running the profiling run-graph and flamegraph demo scenes, if a profile file is not found in the directory served over http, fall back to generating demo data.
This commit is contained in:
parent
15084feaa6
commit
106bb0a044
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -2290,6 +2290,14 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enso-profiler-demo-data"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"enso-profiler",
|
||||
"futures 0.3.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enso-profiler-enso-data"
|
||||
version = "0.1.0"
|
||||
@ -2654,8 +2662,8 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"enso-debug-api",
|
||||
"enso-frp",
|
||||
"enso-profiler",
|
||||
"enso-profiler-data",
|
||||
"enso-profiler-demo-data",
|
||||
"enso-profiler-enso-data",
|
||||
"enso-profiler-flame-graph",
|
||||
"enso-web",
|
||||
@ -2680,8 +2688,8 @@ name = "ensogl-example-render-profile-flamegraph"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"enso-frp",
|
||||
"enso-profiler",
|
||||
"enso-profiler-data",
|
||||
"enso-profiler-demo-data",
|
||||
"enso-profiler-flame-graph",
|
||||
"enso-web",
|
||||
"ensogl-core",
|
||||
|
@ -13,6 +13,7 @@ members = [
|
||||
"lib/rust/parser/jni",
|
||||
"lib/rust/parser/generate-java",
|
||||
"lib/rust/profiler/data",
|
||||
"lib/rust/profiler/demo-data",
|
||||
"integration-test",
|
||||
"tools/language-server/logstat",
|
||||
"tools/language-server/wstest",
|
||||
|
@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"]
|
||||
[dependencies]
|
||||
enso-debug-api = { path = "../../../debug-api" }
|
||||
enso-frp = { path = "../../../frp" }
|
||||
enso-profiler = { path = "../../../profiler" }
|
||||
enso-profiler-data = { path = "../../../profiler/data" }
|
||||
enso-profiler-demo-data = { path = "../../../profiler/demo-data" }
|
||||
enso-profiler-enso-data = { path = "../../../../../app/gui/enso-profiler-enso-data" }
|
||||
enso-profiler-flame-graph = { path = "../../../profiler/flame-graph" }
|
||||
enso-web = { path = "../../../web" }
|
||||
|
@ -19,8 +19,6 @@
|
||||
use ensogl_core::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use enso_profiler as profiler;
|
||||
use enso_profiler::profile;
|
||||
use enso_profiler_data::parse_multiprocess_profile;
|
||||
use enso_profiler_data::Profile;
|
||||
use enso_profiler_enso_data::Metadata;
|
||||
@ -66,6 +64,9 @@ const SHOW_BACKEND_MESSAGE_MARKS: bool = true;
|
||||
#[entry_point]
|
||||
#[allow(dead_code)]
|
||||
pub async fn main() {
|
||||
let profiles = get_log_data().await;
|
||||
|
||||
ensogl_text_msdf::initialized().await;
|
||||
let app = &Application::new("root");
|
||||
let world = &app.display;
|
||||
let scene = &world.default_scene;
|
||||
@ -75,8 +76,6 @@ pub async fn main() {
|
||||
|
||||
init_theme(scene);
|
||||
|
||||
let profiles = get_log_data().await;
|
||||
|
||||
let base_profile = &profiles[0];
|
||||
let flame_graph = profile_to_graph(base_profile, app);
|
||||
scene.add_child(&flame_graph);
|
||||
@ -243,8 +242,14 @@ async fn get_data_http() -> Option<String> {
|
||||
let window = web_sys::window().unwrap();
|
||||
let response = window.fetch_with_request(&request);
|
||||
let response = wasm_bindgen_futures::JsFuture::from(response).await.unwrap();
|
||||
assert!(response.is_instance_of::<web_sys::Response>());
|
||||
let response: web_sys::Response = response.dyn_into().unwrap();
|
||||
if !response.ok() {
|
||||
ERROR!(
|
||||
"Error retrieving profile file from {url}: {response.status_text()}. \
|
||||
Falling back to demo data."
|
||||
);
|
||||
return None;
|
||||
}
|
||||
let data = response.text().unwrap();
|
||||
let data = wasm_bindgen_futures::JsFuture::from(data).await.unwrap();
|
||||
data.as_string()
|
||||
@ -269,109 +274,10 @@ async fn get_log_data() -> Vec<Profile<Metadata>> {
|
||||
match data {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
let dummy_data = create_dummy_data().await;
|
||||
vec![dummy_data]
|
||||
let dummy_data = enso_profiler_demo_data::create_data().await;
|
||||
let profile: Result<Profile<Metadata>, _> = dummy_data.parse();
|
||||
let profile = profile.expect("Failed to deserialize profiling event log.");
|
||||
vec![profile]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==========================
|
||||
// === Dummy Computations ===
|
||||
// ==========================
|
||||
|
||||
async fn create_dummy_data() -> Profile<Metadata> {
|
||||
start_project().await;
|
||||
|
||||
let log = profiler::internal::take_log();
|
||||
let profile: Result<Profile<Metadata>, _> = log.parse();
|
||||
profile.expect("Failed to deserialize profiling event log.")
|
||||
}
|
||||
|
||||
/// A dummy computation that is intended to take some time based on input (where a higher number
|
||||
///takes longer).
|
||||
fn work(n: u32) {
|
||||
let mut m = n;
|
||||
for x in 0..n {
|
||||
for y in 0..n {
|
||||
for z in 0..n {
|
||||
m = m.wrapping_add(x * y * z)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create a side effect to avoid optimising away the computation.
|
||||
println!("{}", m % 7)
|
||||
}
|
||||
|
||||
#[profile(Objective)]
|
||||
async fn start_project() {
|
||||
wake_dragon().await;
|
||||
feed_troll();
|
||||
ride_rainbow();
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn ride_rainbow() {
|
||||
work(333)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn feed_troll() {
|
||||
gather_herbs_and_spices();
|
||||
cook_troll_food();
|
||||
run_away();
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn run_away() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn cook_troll_food() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn gather_herbs_and_spices() {
|
||||
walk_to_woods();
|
||||
search_stuff();
|
||||
find_stuff();
|
||||
gather_stuff();
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn gather_stuff() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn find_stuff() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn search_stuff() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn walk_to_woods() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn wake_dragon() {
|
||||
gather_gold().await;
|
||||
bake_gold_cake().await;
|
||||
start_tea_party().await;
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn start_tea_party() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn bake_gold_cake() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn pick_coin() {
|
||||
work(75)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn gather_gold() {
|
||||
for _ in 0..5 {
|
||||
pick_coin()
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
enso-frp = { path = "../../../frp" }
|
||||
enso-profiler = { path = "../../../profiler" }
|
||||
enso-profiler-data = { path = "../../../profiler/data" }
|
||||
enso-profiler-demo-data = { path = "../../../profiler/demo-data" }
|
||||
enso-profiler-flame-graph = { path = "../../../profiler/flame-graph" }
|
||||
enso-web = { path = "../../../web" }
|
||||
ensogl-core = { path = "../../core" }
|
||||
|
@ -37,6 +37,9 @@ use ensogl_flame_graph as flame_graph;
|
||||
#[wasm_bindgen]
|
||||
#[allow(dead_code)]
|
||||
pub async fn entry_point_render_profile_flamegraph() {
|
||||
let data = get_data().await;
|
||||
let profile: profiler_data::Profile<profiler_data::OpaqueMetadata> = data.parse().unwrap();
|
||||
ensogl_text_msdf::initialized().await;
|
||||
use ensogl_core::display::object::ObjectOps;
|
||||
let app = &application::Application::new("root");
|
||||
let world = &app.display;
|
||||
@ -44,8 +47,6 @@ pub async fn entry_point_render_profile_flamegraph() {
|
||||
let network = app.frp.network();
|
||||
let navigator = navigator::Navigator::new(scene, &scene.camera());
|
||||
init_theme(scene);
|
||||
let data = get_data().await;
|
||||
let profile: profiler_data::Profile<profiler_data::OpaqueMetadata> = data.parse().unwrap();
|
||||
let mut builder = profiler_flame_graph::FlamegraphBuilder::default();
|
||||
builder.add_profile(&profile);
|
||||
let flame_graph = flame_graph::FlameGraph::from_data(builder.into(), app);
|
||||
@ -89,6 +90,13 @@ async fn get_data() -> String {
|
||||
let response = wasm_bindgen_futures::JsFuture::from(response).await.unwrap();
|
||||
assert!(response.is_instance_of::<web_sys::Response>());
|
||||
let response: web_sys::Response = response.dyn_into().unwrap();
|
||||
if !response.ok() {
|
||||
ERROR!(
|
||||
"Error retrieving profile file from {url}: {response.status_text()}. \
|
||||
Falling back to demo data."
|
||||
);
|
||||
return enso_profiler_demo_data::create_data().await;
|
||||
}
|
||||
let data = response.text().unwrap();
|
||||
let data = wasm_bindgen_futures::JsFuture::from(data).await.unwrap();
|
||||
data.as_string().unwrap()
|
||||
|
9
lib/rust/profiler/demo-data/Cargo.toml
Normal file
9
lib/rust/profiler/demo-data/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "enso-profiler-demo-data"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Enso Team <contact@enso.org>"]
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3"
|
||||
enso-profiler = { path = ".." }
|
114
lib/rust/profiler/demo-data/src/lib.rs
Normal file
114
lib/rust/profiler/demo-data/src/lib.rs
Normal file
@ -0,0 +1,114 @@
|
||||
//! Produces example profile data.
|
||||
|
||||
// === Standard Linter Configuration ===
|
||||
#![deny(non_ascii_idents)]
|
||||
#![warn(unsafe_code)]
|
||||
// === Non-Standard Linter Configuration ===
|
||||
#![allow(unused_qualifications)]
|
||||
#![warn(missing_copy_implementations)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(trivial_casts)]
|
||||
#![warn(trivial_numeric_casts)]
|
||||
|
||||
use enso_profiler as profiler;
|
||||
use enso_profiler::profile;
|
||||
|
||||
|
||||
|
||||
// ==========================
|
||||
// === Dummy Computations ===
|
||||
// ==========================
|
||||
|
||||
/// Create example profiling data.
|
||||
pub async fn create_data() -> String {
|
||||
start_project().await;
|
||||
profiler::internal::take_log()
|
||||
}
|
||||
|
||||
/// A dummy computation that is intended to take some time based on input (where a higher number
|
||||
///takes longer).
|
||||
fn work(n: u32) {
|
||||
let mut m = n;
|
||||
for x in 0..n {
|
||||
for y in 0..n {
|
||||
for z in 0..n {
|
||||
m = m.wrapping_add(x * y * z)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create a side effect to avoid optimising away the computation.
|
||||
println!("{}", m % 7)
|
||||
}
|
||||
|
||||
#[profile(Objective)]
|
||||
async fn start_project() {
|
||||
wake_dragon().await;
|
||||
feed_troll();
|
||||
ride_rainbow();
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn ride_rainbow() {
|
||||
work(333)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn feed_troll() {
|
||||
gather_herbs_and_spices();
|
||||
cook_troll_food();
|
||||
run_away();
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn run_away() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn cook_troll_food() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn gather_herbs_and_spices() {
|
||||
walk_to_woods();
|
||||
search_stuff();
|
||||
find_stuff();
|
||||
gather_stuff();
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn gather_stuff() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn find_stuff() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn search_stuff() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn walk_to_woods() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn wake_dragon() {
|
||||
gather_gold().await;
|
||||
bake_gold_cake().await;
|
||||
start_tea_party().await;
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn start_tea_party() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn bake_gold_cake() {
|
||||
work(100)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
fn pick_coin() {
|
||||
work(75)
|
||||
}
|
||||
#[profile(Objective)]
|
||||
async fn gather_gold() {
|
||||
for _ in 0..5 {
|
||||
pick_coin()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user