Skip to content

Commit

Permalink
An ever Increasing Component ID (#2537)
Browse files Browse the repository at this point in the history
* Bring changes to this branch.

* Child components always render after parents.

* Cleanup residual Portal references.

* Fix after merge.

* Fix trybuild.

* Opt for usize.

* Strip Generics.

* take instead of replace, first instead of front.
  • Loading branch information
futursolo authored Mar 21, 2022
1 parent 39d3b37 commit 62d78d0
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 210 deletions.
4 changes: 2 additions & 2 deletions packages/yew/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ trybuild = "1"
[features]
ssr = ["futures", "html-escape"]
csr = []
doc_test = ["csr"]
doc_test = ["csr", "ssr"]
wasm_test = ["csr"]
default = []

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
tokio = { version = "1.15.0", features = ["full"] }

[package.metadata.docs.rs]
features = ["doc_test", "ssr"]
features = ["doc_test"]
rustdoc-args = ["--cfg", "documenting"]
47 changes: 23 additions & 24 deletions packages/yew/src/html/component/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,7 @@ pub(crate) struct ComponentState {

suspension: Option<Suspension>,

// Used for debug logging
#[cfg(debug_assertions)]
pub(crate) vcomp_id: usize,
pub(crate) comp_id: usize,
}

impl ComponentState {
Expand All @@ -164,8 +162,7 @@ impl ComponentState {
scope: Scope<COMP>,
props: Rc<COMP::Properties>,
) -> Self {
#[cfg(debug_assertions)]
let vcomp_id = scope.vcomp_id;
let comp_id = scope.id;
let context = Context { scope, props };

let inner = Box::new(CompStateInner {
Expand All @@ -181,8 +178,7 @@ impl ComponentState {
#[cfg(feature = "csr")]
has_rendered: false,

#[cfg(debug_assertions)]
vcomp_id,
comp_id,
}
}

Expand All @@ -208,7 +204,7 @@ impl<COMP: BaseComponent> Runnable for CreateRunner<COMP> {
let mut current_state = self.scope.state.borrow_mut();
if current_state.is_none() {
#[cfg(debug_assertions)]
super::log_event(self.scope.vcomp_id, "create");
super::log_event(self.scope.id, "create");

*current_state = Some(ComponentState::new(
self.initial_render_state,
Expand Down Expand Up @@ -240,6 +236,7 @@ impl Runnable for UpdateRunner {
if let Some(state) = self.state.borrow_mut().as_mut() {
let schedule_render = match self.event {
UpdateEvent::Message => state.inner.flush_messages(),

#[cfg(feature = "csr")]
UpdateEvent::Properties(props, next_node_ref, next_sibling) => {
match state.render_state {
Expand Down Expand Up @@ -297,16 +294,16 @@ impl Runnable for UpdateRunner {

#[cfg(debug_assertions)]
super::log_event(
state.vcomp_id,
state.comp_id,
format!("update(schedule_render={})", schedule_render),
);

if schedule_render {
scheduler::push_component_render(
self.state.as_ptr() as usize,
RenderRunner {
state.comp_id,
Box::new(RenderRunner {
state: self.state.clone(),
},
}),
);
// Only run from the scheduler, so no need to call `scheduler::start()`
}
Expand All @@ -325,7 +322,7 @@ impl Runnable for DestroyRunner {
fn run(self: Box<Self>) {
if let Some(mut state) = self.state.borrow_mut().take() {
#[cfg(debug_assertions)]
super::log_event(state.vcomp_id, "destroy");
super::log_event(state.comp_id, "destroy");

state.inner.destroy();

Expand Down Expand Up @@ -357,7 +354,7 @@ impl Runnable for RenderRunner {
fn run(self: Box<Self>) {
if let Some(state) = self.state.borrow_mut().as_mut() {
#[cfg(debug_assertions)]
super::log_event(state.vcomp_id, "render");
super::log_event(state.comp_id, "render");

match state.inner.view() {
Ok(m) => self.render(state, m),
Expand All @@ -373,14 +370,16 @@ impl RenderRunner {
// suspension to parent element.
let shared_state = self.state.clone();

let comp_id = state.comp_id;

if suspension.resumed() {
// schedule a render immediately if suspension is resumed.

scheduler::push_component_render(
shared_state.as_ptr() as usize,
RenderRunner {
state.comp_id,
Box::new(RenderRunner {
state: shared_state,
},
}),
);
} else {
// We schedule a render after current suspension is resumed.
Expand All @@ -393,10 +392,10 @@ impl RenderRunner {

suspension.listen(Callback::from(move |_| {
scheduler::push_component_render(
shared_state.as_ptr() as usize,
RenderRunner {
comp_id,
Box::new(RenderRunner {
state: shared_state.clone(),
},
}),
);
scheduler::start();
}));
Expand Down Expand Up @@ -442,11 +441,11 @@ impl RenderRunner {
state.has_rendered = true;

scheduler::push_component_rendered(
self.state.as_ptr() as usize,
RenderedRunner {
state.comp_id,
Box::new(RenderedRunner {
state: self.state.clone(),
first_render,
},
}),
first_render,
);
}
Expand Down Expand Up @@ -474,7 +473,7 @@ mod feat_csr {
fn run(self: Box<Self>) {
if let Some(state) = self.state.borrow_mut().as_mut() {
#[cfg(debug_assertions)]
super::super::log_event(state.vcomp_id, "rendered");
super::super::log_event(state.comp_id, "rendered");

if state.suspension.is_none() {
state.inner.rendered(self.first_render);
Expand Down
22 changes: 6 additions & 16 deletions packages/yew/src/html/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,46 +14,36 @@ pub(crate) use scope::Scoped;
pub use scope::{AnyScope, Scope, SendAsMessage};
use std::rc::Rc;

#[cfg(debug_assertions)]
#[cfg(any(feature = "csr", feature = "ssr"))]
mod feat_csr_ssr {
#[cfg(debug_assertions)]
thread_local! {
static EVENT_HISTORY: std::cell::RefCell<std::collections::HashMap<usize, Vec<String>>>
= Default::default();
static COMP_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
}

/// Push [Component] event to lifecycle debugging registry
#[cfg(debug_assertions)]
pub(crate) fn log_event(vcomp_id: usize, event: impl ToString) {
pub(crate) fn log_event(comp_id: usize, event: impl ToString) {
EVENT_HISTORY.with(|h| {
h.borrow_mut()
.entry(vcomp_id)
.entry(comp_id)
.or_default()
.push(event.to_string())
});
}

/// Get [Component] event log from lifecycle debugging registry
#[cfg(debug_assertions)]
#[allow(dead_code)]
pub(crate) fn get_event_log(vcomp_id: usize) -> Vec<String> {
pub(crate) fn get_event_log(comp_id: usize) -> Vec<String> {
EVENT_HISTORY.with(|h| {
h.borrow()
.get(&vcomp_id)
.get(&comp_id)
.map(|l| (*l).clone())
.unwrap_or_default()
})
}

#[cfg(debug_assertions)]
pub(crate) fn next_id() -> usize {
COMP_ID_COUNTER.with(|m| m.fetch_add(1, Ordering::Relaxed))
}

#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicUsize, Ordering};
}

#[cfg(debug_assertions)]
#[cfg(any(feature = "csr", feature = "ssr"))]
pub(crate) use feat_csr_ssr::*;
Expand Down
49 changes: 26 additions & 23 deletions packages/yew/src/html/component/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::cell::RefCell;
#[cfg(any(feature = "csr", feature = "ssr"))]
use super::lifecycle::{ComponentState, UpdateEvent, UpdateRunner};
use super::BaseComponent;

use crate::callback::Callback;
use crate::context::{ContextHandle, ContextProvider};
use crate::html::IntoComponent;
Expand Down Expand Up @@ -112,8 +113,7 @@ pub struct Scope<COMP: BaseComponent> {
#[cfg(any(feature = "csr", feature = "ssr"))]
pub(crate) state: Shared<Option<ComponentState>>,

#[cfg(debug_assertions)]
pub(crate) vcomp_id: usize,
pub(crate) id: usize,
}

impl<COMP: BaseComponent> fmt::Debug for Scope<COMP> {
Expand All @@ -134,8 +134,7 @@ impl<COMP: BaseComponent> Clone for Scope<COMP> {
#[cfg(any(feature = "csr", feature = "ssr"))]
state: self.state.clone(),

#[cfg(debug_assertions)]
vcomp_id: self.vcomp_id,
id: self.id,
}
}
}
Expand Down Expand Up @@ -211,14 +210,15 @@ mod feat_ssr {
let state = ComponentRenderState::Ssr { sender: Some(tx) };

scheduler::push_component_create(
CreateRunner {
self.id,
Box::new(CreateRunner {
initial_render_state: state,
props,
scope: self.clone(),
},
RenderRunner {
}),
Box::new(RenderRunner {
state: self.state.clone(),
},
}),
);
scheduler::start();

Expand All @@ -227,12 +227,12 @@ mod feat_ssr {
let self_any_scope = AnyScope::from(self.clone());
html.render_to_string(w, &self_any_scope).await;

scheduler::push_component_destroy(DestroyRunner {
scheduler::push_component_destroy(Box::new(DestroyRunner {
state: self.state.clone(),

#[cfg(feature = "csr")]
parent_to_detach: false,
});
}));
scheduler::start();
}
}
Expand Down Expand Up @@ -269,6 +269,7 @@ mod feat_csr_ssr {
use super::*;
use crate::scheduler::{self, Shared};
use std::cell::Ref;
use std::sync::atomic::{AtomicUsize, Ordering};

#[derive(Debug)]
pub(crate) struct MsgQueue<Msg>(Shared<Vec<Msg>>);
Expand Down Expand Up @@ -308,6 +309,8 @@ mod feat_csr_ssr {
}
}

static COMP_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);

impl<COMP: BaseComponent> Scope<COMP> {
/// Crate a scope with an optional parent scope
pub(crate) fn new(parent: Option<AnyScope>) -> Self {
Expand All @@ -325,8 +328,7 @@ mod feat_csr_ssr {
state,
parent,

#[cfg(debug_assertions)]
vcomp_id: super::super::next_id(),
id: COMP_ID_COUNTER.fetch_add(1, Ordering::SeqCst),
}
}

Expand All @@ -345,10 +347,10 @@ mod feat_csr_ssr {
}

pub(super) fn push_update(&self, event: UpdateEvent) {
scheduler::push_component_update(UpdateRunner {
scheduler::push_component_update(Box::new(UpdateRunner {
state: self.state.clone(),
event,
});
}));
// Not guaranteed to already have the scheduler started
scheduler::start();
}
Expand Down Expand Up @@ -415,14 +417,15 @@ mod feat_csr {
};

scheduler::push_component_create(
CreateRunner {
self.id,
Box::new(CreateRunner {
initial_render_state: state,
props,
scope: self.clone(),
},
RenderRunner {
}),
Box::new(RenderRunner {
state: self.state.clone(),
},
}),
);
// Not guaranteed to already have the scheduler started
scheduler::start();
Expand All @@ -435,7 +438,7 @@ mod feat_csr {
next_sibling: NodeRef,
) {
#[cfg(debug_assertions)]
super::super::log_event(self.vcomp_id, "reuse");
super::super::log_event(self.id, "reuse");

self.push_update(UpdateEvent::Properties(props, node_ref, next_sibling));
}
Expand Down Expand Up @@ -470,10 +473,10 @@ mod feat_csr {

/// Process an event to destroy a component
fn destroy(self, parent_to_detach: bool) {
scheduler::push_component_destroy(DestroyRunner {
scheduler::push_component_destroy(Box::new(DestroyRunner {
state: self.state,
parent_to_detach,
});
}));
// Not guaranteed to already have the scheduler started
scheduler::start();
}
Expand All @@ -483,10 +486,10 @@ mod feat_csr {
}

fn shift_node(&self, parent: Element, next_sibling: NodeRef) {
scheduler::push_component_update(UpdateRunner {
scheduler::push_component_update(Box::new(UpdateRunner {
state: self.state.clone(),
event: UpdateEvent::Shift(parent, next_sibling),
})
}))
}
}
}
Expand Down
Loading

1 comment on commit 62d78d0

@github-actions
Copy link

Choose a reason for hiding this comment

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

Yew master branch benchmarks (Lower is better)

Benchmark suite Current: 62d78d0 Previous: 39d3b37 Ratio
yew-struct-keyed 01_run1k 192.5855 173.1495 1.11
yew-struct-keyed 02_replace1k 221.246 190.753 1.16
yew-struct-keyed 03_update10th1k_x16 396.6435 378.332 1.05
yew-struct-keyed 04_select1k 79.553 74.5655 1.07
yew-struct-keyed 05_swap1k 100.9835 90.9495 1.11
yew-struct-keyed 06_remove-one-1k 33.069500000000005 30.694000000000003 1.08
yew-struct-keyed 07_create10k 2401.2574999999997 2047.6115 1.17
yew-struct-keyed 08_create1k-after1k_x2 459.1325 436.2705 1.05
yew-struct-keyed 09_clear1k_x8 224.1385 207.9815 1.08
yew-struct-keyed 21_ready-memory 0.9634475708007812 0.9634475708007812 1
yew-struct-keyed 22_run-memory 1.5048446655273438 1.5048294067382812 1.00
yew-struct-keyed 23_update5-memory 1.4602203369140625 1.4602203369140625 1
yew-struct-keyed 24_run5-memory 1.5095291137695312 1.5052261352539062 1.00
yew-struct-keyed 25_run-clear-memory 1.1240730285644531 1.1272430419921875 1.00
yew-struct-keyed 31_startup-ci 1882.145 1738.04 1.08
yew-struct-keyed 32_startup-bt 36.35199999999999 34.937999999999974 1.04
yew-struct-keyed 34_startup-totalbytes 330.5498046875 330.5498046875 1

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.