Skip to content

Commit 1082985

Browse files
committed
feat: Performance improvements
1 parent 6cca92b commit 1082985

File tree

10 files changed

+106
-60
lines changed

10 files changed

+106
-60
lines changed

Cargo.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ use_camera = ["freya/use_camera"]
1313
hot-reload = ["freya/hot-reload"]
1414

1515
[patch.crates-io]
16-
dioxus = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
17-
dioxus-rsx = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
18-
dioxus-core-macro = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
19-
dioxus-hooks = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
20-
dioxus-signals = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
21-
dioxus-core = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
22-
dioxus-hot-reload = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
23-
dioxus-router = { git = "https://github.com/DioxusLabs/dioxus", rev = "f266213618b9715e9df8c28fb51ca81e38b28055" }
16+
dioxus = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
17+
dioxus-rsx = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
18+
dioxus-core-macro = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
19+
dioxus-hooks = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
20+
dioxus-signals = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
21+
dioxus-core = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
22+
dioxus-hot-reload = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
23+
dioxus-router = { git = "https://github.com/DioxusLabs/dioxus", rev = "46b0eeb12cf2b388d29a9061b74e9470a8487679" }
2424

2525
[workspace.dependencies]
2626
freya = { path = "crates/freya", version = "0.1" }

crates/common/src/paragraphs.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ impl ParagraphElements {
2222

2323
pub fn remove_paragraph(&self, node_id: NodeId, text_id: &Uuid) {
2424
let mut paragraphs = self.paragraphs.lock().unwrap();
25-
let text_group = paragraphs.get_mut(text_id).unwrap();
25+
let text_group = paragraphs.get_mut(text_id);
2626

27-
text_group.retain(|id| *id != node_id);
27+
if let Some(text_group) = text_group {
28+
text_group.retain(|id| *id != node_id);
2829

29-
if text_group.is_empty() {
30-
paragraphs.remove(text_id);
30+
if text_group.is_empty() {
31+
paragraphs.remove(text_id);
32+
}
3133
}
3234
}
3335

crates/components/src/switch.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,10 @@ pub fn Switch(props: SwitchProps) -> Element {
9494
platform.set_cursor(CursorIcon::Pointer);
9595
};
9696

97-
let onclick = {
98-
let ontoggled = props.ontoggled.clone();
99-
move |e: MouseEvent| {
100-
e.stop_propagation();
101-
focus.focus();
102-
ontoggled.call(());
103-
}
97+
let onclick = move |e: MouseEvent| {
98+
e.stop_propagation();
99+
focus.focus();
100+
props.ontoggled.call(());
104101
};
105102

106103
let onkeydown = move |e: KeyboardEvent| {

crates/core/src/dom/mutations_writer.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,6 @@ impl<'a> WriteMutations for MutationsWriter<'a> {
132132
}
133133

134134
fn remove_node(&mut self, id: dioxus_core::ElementId) {
135-
let node_id = self.native_writer.state.element_to_node_id(id);
136-
let mut dom_adapter = DioxusDOMAdapter::new_with_cache(self.native_writer.rdom);
137-
self.layout.remove(node_id, &mut dom_adapter, true);
138135
self.remove(id);
139136
self.native_writer.remove_node(id);
140137
}

crates/core/src/events/events_measurer.rs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,6 @@ fn measure_dom_events(
192192
'event: for collateral_event in collateral_events {
193193
let mut child_node: Option<NodeId> = None;
194194

195-
let listeners = rdom.get_listening_sorted(&collateral_event);
196-
197195
// Iterate over the event nodes
198196
for PotentialEvent {
199197
node_id,
@@ -205,28 +203,25 @@ fn measure_dom_events(
205203
continue;
206204
};
207205

208-
// Iterate over the event listeners
209-
for listener in &listeners {
210-
if listener.id() == *node_id {
211-
let valid_node = if let Some(child_node) = child_node {
212-
is_node_parent_of(rdom, child_node, *node_id)
213-
} else {
214-
true
215-
};
206+
if rdom.is_node_listening(node_id, &collateral_event) {
207+
let valid_node = if let Some(child_node) = child_node {
208+
is_node_parent_of(rdom, child_node, *node_id)
209+
} else {
210+
true
211+
};
216212

217-
if valid_node {
218-
let mut valid_event = event.clone();
219-
valid_event.set_name(collateral_event);
220-
valid_events.push(PotentialEvent {
221-
node_id: *node_id,
222-
event: valid_event,
223-
layer: *layer,
224-
});
225-
226-
// Stack events that do not bubble up
227-
if event.get_name().does_bubble() {
228-
continue 'event;
229-
}
213+
if valid_node {
214+
let mut valid_event = event.clone();
215+
valid_event.set_name(collateral_event);
216+
valid_events.push(PotentialEvent {
217+
node_id: *node_id,
218+
event: valid_event,
219+
layer: *layer,
220+
});
221+
222+
// Stack events that do not bubble up
223+
if event.get_name().does_bubble() {
224+
continue 'event;
230225
}
231226
}
232227
}
@@ -274,7 +269,7 @@ fn emit_global_events_listeners(
274269
) {
275270
for global_event in global_events {
276271
let event_name = global_event.get_name();
277-
let listeners = fdom.rdom().get_listening_sorted(&event_name);
272+
let listeners = fdom.rdom().get_listeners(&event_name);
278273

279274
for listener in listeners {
280275
let element_id = listener.mounted_id().unwrap();

crates/core/src/plugins.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ pub enum PluginEvent<'a> {
4747

4848
/// After measuring the layout.
4949
FinishedLayout(&'a Torin<NodeId>),
50+
51+
StartedUpdatingDOM,
52+
53+
FinishedUpdatingDOM,
5054
}
5155

5256
/// Skeleton for Freya plugins.

crates/freya/src/plugins/performance_overlay.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use std::time::{Duration, Instant};
22

33
use freya_core::plugins::{FreyaPlugin, PluginEvent};
44
use freya_engine::prelude::{
5-
Color, FontStyle, ParagraphBuilder, ParagraphStyle, Slant, TextShadow, TextStyle, Weight, Width,
5+
Color, FontStyle, Paint, PaintStyle, ParagraphBuilder, ParagraphStyle, Rect, Slant, TextShadow,
6+
TextStyle, Weight, Width,
67
};
78

89
#[derive(Default)]
@@ -11,6 +12,10 @@ pub struct PerformanceOverlayPlugin {
1112
started_render: Option<Instant>,
1213
started_layout: Option<Instant>,
1314
finished_layout: Option<Duration>,
15+
started_dom_updates: Option<Instant>,
16+
finished_dom_updates: Option<Duration>,
17+
fps_historic: Vec<usize>,
18+
max_fps: usize,
1419
}
1520

1621
impl FreyaPlugin for PerformanceOverlayPlugin {
@@ -20,6 +25,10 @@ impl FreyaPlugin for PerformanceOverlayPlugin {
2025
PluginEvent::FinishedLayout(_) => {
2126
self.finished_layout = Some(self.started_layout.unwrap().elapsed())
2227
}
28+
PluginEvent::StartedUpdatingDOM => self.started_dom_updates = Some(Instant::now()),
29+
PluginEvent::FinishedUpdatingDOM => {
30+
self.finished_dom_updates = Some(self.started_dom_updates.unwrap().elapsed())
31+
}
2332
PluginEvent::BeforeRender { .. } => self.started_render = Some(Instant::now()),
2433
PluginEvent::AfterRender {
2534
canvas,
@@ -28,6 +37,7 @@ impl FreyaPlugin for PerformanceOverlayPlugin {
2837
} => {
2938
let started_render = self.started_render.take().unwrap();
3039
let finished_layout = self.finished_layout.unwrap();
40+
let finished_dom_updates = self.finished_dom_updates.unwrap();
3141
let rdom = freya_dom.rdom();
3242
let layout = freya_dom.layout();
3343

@@ -57,6 +67,11 @@ impl FreyaPlugin for PerformanceOverlayPlugin {
5767
30.0,
5868
);
5969

70+
self.fps_historic.push(self.frames.len());
71+
if self.fps_historic.len() > 70 {
72+
self.fps_historic.remove(0);
73+
}
74+
6075
// Rendering time
6176
add_text(
6277
&mut paragraph_builder,
@@ -71,6 +86,13 @@ impl FreyaPlugin for PerformanceOverlayPlugin {
7186
18.0,
7287
);
7388

89+
// DOM updates time
90+
add_text(
91+
&mut paragraph_builder,
92+
format!("DOM Updates: {}ms \n", finished_dom_updates.as_millis()),
93+
18.0,
94+
);
95+
7496
// DOM size
7597
add_text(
7698
&mut paragraph_builder,
@@ -88,6 +110,31 @@ impl FreyaPlugin for PerformanceOverlayPlugin {
88110
let mut paragraph = paragraph_builder.build();
89111
paragraph.layout(f32::MAX);
90112
paragraph.paint(canvas, (5.0, 0.0));
113+
114+
let mut paint = Paint::default();
115+
paint.set_anti_alias(true);
116+
paint.set_style(PaintStyle::Fill);
117+
paint.set_color(Color::from_argb(120, 255, 255, 255));
118+
119+
self.max_fps = self
120+
.max_fps
121+
.max(self.fps_historic.iter().max().copied().unwrap_or_default());
122+
let start_x = 5.0;
123+
let start_y = 150.0 + self.max_fps.max(60) as f32;
124+
125+
canvas.draw_rect(Rect::new(5., 150., 200., start_y), &paint);
126+
127+
for (i, fps) in self.fps_historic.iter().enumerate() {
128+
let mut paint = Paint::default();
129+
paint.set_anti_alias(true);
130+
paint.set_style(PaintStyle::Fill);
131+
paint.set_color(Color::from_rgb(63, 255, 0));
132+
paint.set_stroke_width(3.0);
133+
134+
let x = start_x + (i * 2) as f32;
135+
let y = start_y - *fps as f32 + 2.0;
136+
canvas.draw_circle((x, y), 2.0, &paint);
137+
}
91138
}
92139
_ => {}
93140
}

crates/native-core/src/real_dom.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,18 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
238238
NodeMut::new(id, self)
239239
}
240240

241-
/// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
242-
/// This can be useful to avoid creating duplicate events.
243-
pub fn get_listening_sorted(&self, event: &EventName) -> Vec<NodeRef<V>> {
241+
pub fn is_node_listening(&self, node_id: &NodeId, event: &EventName) -> bool {
242+
self.nodes_listening
243+
.get(event)
244+
.map(|listeners| listeners.contains(node_id))
245+
.unwrap_or_default()
246+
}
247+
248+
pub fn get_listeners(&self, event: &EventName) -> Vec<NodeRef<V>> {
244249
if let Some(nodes) = self.nodes_listening.get(event) {
245-
let mut listening: Vec<_> = nodes
250+
nodes
246251
.iter()
247-
.map(|id| (*id, self.tree_ref().height(*id).unwrap()))
248-
.collect();
249-
listening.sort_by(|(_, h1), (_, h2)| h1.cmp(h2).reverse());
250-
listening
251-
.into_iter()
252-
.map(|(id, _)| NodeRef { id, dom: self })
252+
.map(|id| NodeRef { id: *id, dom: self })
253253
.collect()
254254
} else {
255255
Vec::new()
@@ -624,8 +624,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
624624
.mark_child_changed(parent_id);
625625
}
626626
let children_ids = self.child_ids();
627-
let children_ids_vec = children_ids.to_vec();
628-
for child in children_ids_vec {
627+
for child in children_ids {
629628
self.dom.get_mut(child).unwrap().remove();
630629
}
631630
self.dom.tree_mut().remove(id);

crates/renderer/src/app.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,25 @@ impl<State: 'static + Clone> App<State> {
133133

134134
/// Make the first build of the VirtualDOM and sync it with the RealDOM.
135135
pub fn init_doms(&mut self) {
136+
self.plugins.send(PluginEvent::StartedUpdatingDOM);
136137
let scale_factor = self.window_env.window.scale_factor() as f32;
137138
self.provide_vdom_contexts();
138139

139140
self.sdom.get_mut().init_dom(&mut self.vdom, scale_factor);
141+
self.plugins.send(PluginEvent::FinishedUpdatingDOM);
140142
}
141143

142144
/// Update the DOM with the mutations from the VirtualDOM.
143145
pub fn apply_vdom_changes(&mut self) -> (bool, bool) {
146+
self.plugins.send(PluginEvent::StartedUpdatingDOM);
144147
let scale_factor = self.window_env.window.scale_factor() as f32;
145148
let (repaint, relayout) = self
146149
.sdom
147150
.get_mut()
148151
.render_mutations(&mut self.vdom, scale_factor);
149152

153+
self.plugins.send(PluginEvent::FinishedUpdatingDOM);
154+
150155
if repaint {
151156
if let Some(mutations_notifier) = &self.mutations_notifier {
152157
mutations_notifier.notify_one();

crates/state/src/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub struct LayoutState {
3131
pub position: Position,
3232
pub content: Content,
3333
pub node_ref: Option<NodeReference>,
34-
pub node_id: NodeId
34+
pub node_id: NodeId,
3535
}
3636

3737
#[partial_derive_state]

0 commit comments

Comments
 (0)