use boxed slices instead of vecs where possible

This commit is contained in:
Evan Almloff 2024-01-07 13:41:39 -06:00
parent c59926cb1f
commit aefa8a2431
9 changed files with 53 additions and 46 deletions

View file

@ -76,7 +76,7 @@ impl VirtualDom {
/// Create this template and write its mutations
pub(crate) fn create(&mut self, node: &VNode, to: &mut impl WriteMutations) -> usize {
// check for a overriden template
// check for a overridden template
#[cfg(debug_assertions)]
{
let (path, byte_index) = node.template.get().name.rsplit_once(':').unwrap();
@ -86,14 +86,14 @@ impl VirtualDom {
.and_then(|map| map.get(&byte_index.parse().unwrap()))
{
node.template.set(*template);
}
}
// Initialize the root nodes slice
{
let mut nodes_mut = node.root_ids.borrow_mut();
let len = node.template.get().roots.len();
nodes_mut.resize(len, ElementId::default());
// Initialize the root nodes slice if it was changed
let mut nodes_mut = node.root_ids.borrow_mut();
let len = node.template.get().roots.len();
if nodes_mut.len() != len {
*nodes_mut = vec![ElementId::default(); len].into_boxed_slice();
};
}
};
// The best renderers will have templates prehydrated and registered

View file

@ -149,9 +149,9 @@ impl VirtualDom {
// Make sure the roots get transferred over while we're here
{
let mut right = right_template.root_ids.borrow_mut();
right.clear();
for &element in left_template.root_ids.borrow().iter() {
right.push(element);
let left = left_template.root_ids.borrow();
for (from, into) in left.iter().zip(right.iter_mut()) {
*into = *from;
}
}
}

View file

@ -2,12 +2,24 @@ use std::hash::Hash;
use crate::ScopeId;
#[derive(Debug, Clone, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Eq)]
pub struct DirtyScope {
pub height: u32,
pub id: ScopeId,
}
impl PartialOrd for DirtyScope {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for DirtyScope {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.height.cmp(&other.height).then(self.id.cmp(&other.id))
}
}
impl PartialEq for DirtyScope {
fn eq(&self, other: &Self) -> bool {
self.id == other.id

View file

@ -287,8 +287,8 @@ fn default_handler(error: CapturedError) -> Element {
Some(VNode::new(
None,
TEMPLATE,
Vec::with_capacity(1usize),
vec![error.to_string().into_dyn_node()],
Box::new([Default::default(); 1]),
Box::new([error.to_string().into_dyn_node()]),
Default::default(),
))
}
@ -460,8 +460,8 @@ pub fn ErrorBoundary(props: ErrorBoundaryProps) -> Element {
VNode::new(
None,
TEMPLATE,
Vec::with_capacity(1usize),
vec![(props.children).into_dyn_node()],
Box::new([Default::default(); 1]),
Box::new([(props.children).into_dyn_node()]),
Default::default(),
)
}),

View file

@ -77,8 +77,8 @@ pub use crate::innerlude::{
fc_to_builder, generation, once, schedule_update, schedule_update_any, vdom_is_rendering,
AnyValue, Attribute, AttributeValue, CapturedError, Component, DynamicNode, Element, ElementId,
Event, Fragment, IntoDynNode, Mutation, MutationsVec, Properties, RenderReturn, ScopeId, Task,
Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, VirtualDom,
WriteMutations,
Template, TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder, VText,
VirtualDom, WriteMutations,
};
/// The purpose of this module is to alleviate imports of many common types
@ -91,6 +91,7 @@ pub mod prelude {
push_future, remove_future, schedule_update, schedule_update_any, spawn, spawn_forever,
suspend, use_error_boundary, AnyValue, Component, Element, ErrorBoundary, Event,
EventHandler, Fragment, IntoAttributeValue, IntoDynNode, Properties, Runtime, RuntimeGuard,
ScopeId, Task, Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom,
ScopeId, Task, Template, TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner,
VirtualDom,
};
}

View file

@ -4,6 +4,7 @@ use crate::Properties;
use crate::{arena::ElementId, Element, Event, ScopeId};
use std::ops::Deref;
use std::rc::Rc;
use std::vec;
use std::{
any::{Any, TypeId},
cell::{Cell, RefCell},
@ -53,16 +54,16 @@ pub struct VNodeInner {
/// The IDs for the roots of this template - to be used when moving the template around and removing it from
/// the actual Dom
pub root_ids: RefCell<Vec<ElementId>>,
pub root_ids: RefCell<Box<[ElementId]>>,
/// The static nodes and static descriptor of the template
pub template: Cell<Template>,
/// The dynamic parts of the template
pub dynamic_nodes: Vec<DynamicNode>,
pub dynamic_nodes: Box<[DynamicNode]>,
/// The dynamic parts of the template
pub dynamic_attrs: Vec<Attribute>,
pub dynamic_attrs: Box<[Attribute]>,
}
/// A reference to a template along with any context needed to hydrate it
@ -93,8 +94,8 @@ impl VNode {
key: None,
parent: Default::default(),
root_ids: Default::default(),
dynamic_nodes: Vec::new(),
dynamic_attrs: Vec::new(),
dynamic_nodes: Box::new([]),
dynamic_attrs: Box::new([]),
template: Cell::new(Template {
name: "dioxus-empty",
roots: &[],
@ -108,9 +109,9 @@ impl VNode {
pub fn new(
key: Option<String>,
template: Template,
root_ids: Vec<ElementId>,
dynamic_nodes: Vec<DynamicNode>,
dynamic_attrs: Vec<Attribute>,
root_ids: Box<[ElementId]>,
dynamic_nodes: Box<[DynamicNode]>,
dynamic_attrs: Box<[Attribute]>,
) -> Self {
Self(Rc::new(VNodeInner {
key,

View file

@ -317,9 +317,9 @@ impl VirtualDom {
///
/// Whenever the Runtime "works", it will re-render this scope
pub fn mark_dirty(&mut self, id: ScopeId) {
if let Some(scope) = self.get_scope(id) {
let height = scope.context().height();
tracing::trace!("Marking scope {:?} ({}) as dirty", id, scope.context().name);
if let Some(context) = self.runtime.get_context(id) {
let height = context.height();
tracing::trace!("Marking scope {:?} ({}) as dirty", id, context.name);
self.dirty_scopes.insert(DirtyScope { height, id });
}
}
@ -504,7 +504,7 @@ impl VirtualDom {
/// Replace a template at runtime. This will re-render all components that use this template.
/// This is the primitive that enables hot-reloading.
///
/// The caller must ensure that the template refrences the same dynamic attributes and nodes as the original template.
/// The caller must ensure that the template references the same dynamic attributes and nodes as the original template.
///
/// This will only replace the the parent template, not any nested templates.
pub fn replace_template(&mut self, template: Template) {
@ -619,9 +619,7 @@ impl VirtualDom {
loop {
// Next, diff any dirty scopes
// We choose not to poll the deadline since we complete pretty quickly anyways
if let Some(dirty) = self.dirty_scopes.iter().next().cloned() {
self.dirty_scopes.remove(&dirty);
while let Some(dirty) = self.dirty_scopes.pop_first() {
// If the scope doesn't exist for whatever reason, then we should skip it
if !self.scopes.contains(dirty.id.0) {
continue;
@ -635,11 +633,6 @@ impl VirtualDom {
}
}
// If there's more work, then just continue, plenty of work to do
if !self.dirty_scopes.is_empty() {
continue;
}
// Poll the suspense leaves in the meantime
let mut work = self.wait_for_work();

View file

@ -15,7 +15,7 @@ use syn::spanned::Spanned;
use super::hot_reload_diff::{find_rsx, DiffResult};
pub enum UpdateResult {
UpdatedRsx(Vec<Template<'static>>),
UpdatedRsx(Vec<Template>),
NeedsRebuild,
}
@ -28,7 +28,7 @@ pub struct FileMapBuildResult<Ctx: HotReloadingContext> {
}
pub struct FileMap<Ctx: HotReloadingContext> {
pub map: HashMap<PathBuf, (String, Option<Template<'static>>)>,
pub map: HashMap<PathBuf, (String, Option<Template>)>,
in_workspace: HashMap<PathBuf, Option<PathBuf>>,
phantom: std::marker::PhantomData<Ctx>,
}
@ -45,7 +45,7 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
mut filter: impl FnMut(&Path) -> bool,
) -> io::Result<FileMapBuildResult<Ctx>> {
struct FileMapSearchResult {
map: HashMap<PathBuf, (String, Option<Template<'static>>)>,
map: HashMap<PathBuf, (String, Option<Template>)>,
errors: Vec<io::Error>,
}
fn find_rs_files(
@ -115,7 +115,7 @@ impl<Ctx: HotReloadingContext> FileMap<Ctx> {
self.map.insert(file_path.to_path_buf(), (src, None));
}
DiffResult::RsxChanged(changed) => {
let mut messages: Vec<Template<'static>> = Vec::new();
let mut messages: Vec<Template> = Vec::new();
for (old, new) in changed.into_iter() {
let old_start = old.span().start();

View file

@ -256,9 +256,9 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
::dioxus::core::VNode::new(
#key_tokens,
TEMPLATE,
Vec::with_capacity(#root_count),
vec![ #( #node_printer ),* ],
vec![ #( #dyn_attr_printer ),* ],
Box::new([Default::default();#root_count]),
Box::new([ #( #node_printer ),* ]),
Box::new([ #( #dyn_attr_printer ),* ]),
)
});
}