From 8e05367dd0532cd12f287823d07a7ff75de0fa62 Mon Sep 17 00:00:00 2001 From: Philipp Mildenberger Date: Mon, 9 Dec 2024 14:40:15 +0100 Subject: [PATCH] tree_arena: Use `hashbrown::HashMap` as drop-in replacement to optimize tree-access (#774) As noted in https://github.com/linebender/xilem/pull/772#pullrequestreview-2485087588, this seems to be a really cheap but quite effective optimization, as we have `hashbrown` already in our dependency tree. I've noticed speedups of the rewrite passes of up to >100%. On average about 20-50% and is also definitely noticeable (smoother and less latency). Another quite interesting observation with my (admittedly not really reproducible) performance tests, is that the safe tree arena is actually faster than the unsafe version (roughly 10-30%), and tells yet another time that benches are really important while optimizing... Rough overview of my performance tests/benches: I've mostly hovered over 10000 buttons in the mason example while testing, but every second or so a new button is spawned and also this is quite a bit faster. I did a quick'n dirty `Instant::elapsed` in the event loop (so rendering is not included, but I think there's also a speedup as we're iterating the tree). --- Cargo.lock | 3 +++ Cargo.toml | 1 + tree_arena/Cargo.toml | 1 + tree_arena/src/tree_arena_safe.rs | 2 +- tree_arena/src/tree_arena_unsafe.rs | 3 ++- 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df4f1f562..eb16dc5d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3722,6 +3722,9 @@ dependencies = [ [[package]] name = "tree_arena" version = "0.1.0" +dependencies = [ + "hashbrown 0.15.2", +] [[package]] name = "try-lock" diff --git a/Cargo.toml b/Cargo.toml index 1e7b7ec8c..5e56895c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,6 +117,7 @@ peniko = "0.2.0" winit = "0.30.4" tracing = { version = "0.1.40", default-features = false } smallvec = "1.13.2" +hashbrown = "0.15.2" dpi = "0.1.1" image = { version = "0.25.2", default-features = false } web-time = "1.1.0" diff --git a/tree_arena/Cargo.toml b/tree_arena/Cargo.toml index 1b3fd0a4c..3b879ddd8 100644 --- a/tree_arena/Cargo.toml +++ b/tree_arena/Cargo.toml @@ -21,6 +21,7 @@ targets = [] [dependencies] +hashbrown.workspace = true [features] # This crate contains two implementations of a tree for use in masonry, one safe and the other unsafe. diff --git a/tree_arena/src/tree_arena_safe.rs b/tree_arena/src/tree_arena_safe.rs index dcdb6dd7f..aaa29c811 100644 --- a/tree_arena/src/tree_arena_safe.rs +++ b/tree_arena/src/tree_arena_safe.rs @@ -13,7 +13,7 @@ use super::NodeId; -use std::collections::HashMap; +use hashbrown::HashMap; #[derive(Debug)] struct TreeNode { diff --git a/tree_arena/src/tree_arena_unsafe.rs b/tree_arena/src/tree_arena_unsafe.rs index b3c71b271..b58d30b0f 100644 --- a/tree_arena/src/tree_arena_unsafe.rs +++ b/tree_arena/src/tree_arena_unsafe.rs @@ -5,7 +5,8 @@ use super::NodeId; use std::cell::UnsafeCell; -use std::collections::HashMap; + +use hashbrown::HashMap; #[derive(Debug)] struct TreeNode {