diff --git a/rbx_binary/src/deserializer/state.rs b/rbx_binary/src/deserializer/state.rs index ea3cbbf7c..4ca5f2ffd 100644 --- a/rbx_binary/src/deserializer/state.rs +++ b/rbx_binary/src/deserializer/state.rs @@ -295,13 +295,24 @@ impl<'db, R: Read> DeserializerState<'db, R> { let mut referents = vec![0; number_instances as usize]; chunk.read_referent_array(&mut referents)?; + let prop_capacity = self + .deserializer + .database + .classes + .get(type_name.as_str()) + .map(|class| class.default_properties.len()) + .unwrap_or(0); + // TODO: Check object_format and check for service markers if it's 1? for &referent in &referents { self.instances_by_ref.insert( referent, Instance { - builder: InstanceBuilder::new(&type_name), + builder: InstanceBuilder::with_property_capacity( + type_name.as_str(), + prop_capacity, + ), children: Vec::new(), }, ); diff --git a/rbx_dom_weak/CHANGELOG.md b/rbx_dom_weak/CHANGELOG.md index c6c8b00cb..f089c48af 100644 --- a/rbx_dom_weak/CHANGELOG.md +++ b/rbx_dom_weak/CHANGELOG.md @@ -93,6 +93,9 @@ where ### Other changes * Added `UstrMapExt`, a helper trait providing convenience methods `UstrMap::new` and `UstrMap::with_capacity`. * Added re-exports for `ustr` (a convenience function for creating `Ustr`s), `Ustr`, `UstrMap`, and `UstrSet`. +* Added `InstanceBuilder::with_property_capacity`, which can preallocate an `InstanceBuilder`'s property table. [#464] + +[#464]: https://github.com/rojo-rbx/rbx-dom/pull/464 ## 2.9.0 (2024-08-22) * Added `WeakDom::descendants` and `WeakDom::descendants_of` to support iterating through the descendants of a DOM. ([#431]) diff --git a/rbx_dom_weak/src/instance.rs b/rbx_dom_weak/src/instance.rs index 9b225f77c..9118a8b7b 100644 --- a/rbx_dom_weak/src/instance.rs +++ b/rbx_dom_weak/src/instance.rs @@ -57,6 +57,21 @@ impl InstanceBuilder { } } + /// Create a new `InstanceBuilder` with the given ClassName and with a + /// property table with at least enough space for the given capacity. + pub fn with_property_capacity>(class: S, capacity: usize) -> Self { + let class = class.into(); + let name = class.to_string(); + + InstanceBuilder { + referent: Ref::new(), + name, + class, + properties: UstrMap::with_capacity(capacity), + children: Vec::new(), + } + } + /// Create a new `InstanceBuilder` with all values set to empty. pub fn empty() -> Self { InstanceBuilder { diff --git a/rbx_xml/src/deserializer.rs b/rbx_xml/src/deserializer.rs index c9510d6ea..ec4dc876c 100644 --- a/rbx_xml/src/deserializer.rs +++ b/rbx_xml/src/deserializer.rs @@ -447,7 +447,15 @@ fn deserialize_instance( trace!("Class {} with referent {:?}", class_name, referent); - let builder = InstanceBuilder::new(class_name); + let prop_capacity = state + .options + .database + .classes + .get(class_name.as_str()) + .map(|class| class.default_properties.len()) + .unwrap_or(0); + + let builder = InstanceBuilder::with_property_capacity(class_name, prop_capacity); let instance_id = state.tree.insert(parent_id, builder); if let Some(referent) = referent {