AI: create a macro that measurements the performance of a component

This commit is contained in:
2026-05-05 22:59:43 -04:00
committed by savanni
parent d8c090e705
commit 1ff1cf4a7b
7 changed files with 81 additions and 2 deletions

10
Cargo.lock generated
View File

@@ -1685,6 +1685,7 @@ name = "glimmer-yew"
version = "0.1.0"
dependencies = [
"derive_builder",
"glimmer-yew-macros",
"gloo-console 0.3.0",
"gloo-timers 0.3.0",
"lazy_static",
@@ -1695,6 +1696,15 @@ dependencies = [
"yew-router",
]
[[package]]
name = "glimmer-yew-macros"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "gloo"
version = "0.8.1"

View File

@@ -37,7 +37,7 @@ members = [
"visions/server",
# "visions/types",
"visions/ui",
"visions/core", "glimmer/yew", "utils",
"visions/core", "glimmer/yew", "glimmer/yew-macros", "utils",
# "bike-lights/bike",
]

View File

@@ -0,0 +1,12 @@
[package]
name = "glimmer-yew-macros"
version = "0.1.0"
edition = "2024"
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["full"] }

View File

@@ -0,0 +1,37 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{ItemFn, parse_macro_input};
/// Wraps a Yew function component's body with wall-time performance measurement.
///
/// Captures the time before and after the component function executes and logs
/// the duration via `gloo_console`. Apply it above `#[function_component]` so
/// the timing wraps the raw function before Yew transforms it.
///
/// # Example
/// ```rust
/// #[measured]
/// #[function_component]
/// fn MyComponent(props: &MyProps) -> Html {
/// html! { <div /> }
/// }
/// ```
/// Emits: `[PERF] MyComponent: 0.123ms`
#[proc_macro_attribute]
pub fn measured(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut func = parse_macro_input!(item as ItemFn);
let fn_name = func.sig.ident.to_string();
let stmts = func.block.stmts.clone();
let new_block = syn::parse_quote! {
{
let __measured_t0 = ::glimmer_yew::__measured_start();
let __measured_result = { #(#stmts)* };
::glimmer_yew::__measured_end(#fn_name, __measured_t0);
__measured_result
}
};
func.block = Box::new(new_block);
quote! { #func }.into()
}

View File

@@ -4,11 +4,12 @@ version = "0.1.0"
edition = "2024"
[dependencies]
glimmer-yew-macros = { path = "../yew-macros" }
stylist = { workspace = true, features = ["yew", "yew_integration"] }
yew.workspace = true
lazy_static.workspace = true
wasm-bindgen-futures.workspace = true
web-sys = { workspace = true, features = ["HtmlDialogElement"] }
web-sys = { workspace = true, features = ["HtmlDialogElement", "Performance", "Window"] }
gloo-timers = { version = "0.3.0", features = ["futures"] }
yew-router.workspace = true
gloo-console.workspace = true

View File

@@ -9,6 +9,7 @@ mod label;
mod list;
mod macros;
mod modal;
pub use glimmer_yew_macros::measured;
mod panel;
mod range;
mod row;
@@ -20,10 +21,13 @@ mod tabbed_view;
mod text_entry;
mod utils;
pub use utils::{__measured_end, __measured_start};
pub mod prelude {
use std::{ops::Deref, rc::Rc};
pub use crate::{
measured,
adjustable_value_field::AdjustableValueField,
button::{Button, ButtonVariant, Toggle},
button_group::ButtonGroup,

View File

@@ -1,3 +1,18 @@
#[doc(hidden)]
pub fn __measured_start() -> f64 {
web_sys::window()
.and_then(|w| w.performance())
.map_or(0.0, |p| p.now())
}
#[doc(hidden)]
pub fn __measured_end(name: &str, start: f64) {
let end = web_sys::window()
.and_then(|w| w.performance())
.map_or(start, |p| p.now());
gloo_console::log!(format!("[PERF] {}: {:.3}ms", name, end - start));
}
pub fn navigate_to(path: &str) {
match web_sys::window() {
Some(window) => {