Skip to content

Commit 21859fe

Browse files
committed
Avoid collect::<Result<_>> for rotation matrices
This shaves off about 20% of our maximum heap usage in my tests when loading many animations. There are other places where we collect into a Result, but since those vectors are smaller they make less of a difference. See rust-lang/rust#48994. Also did some readability edits nearby.
1 parent 7c39f76 commit 21859fe

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/nitro/animation.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ pub fn read_animation(base_cur: Cur, name: Name) -> Result<Animation> {
132132

133133
// In this case, the data at base_cur + off doesn't store the actual
134134
// curve values, it stores references into pivot_data and basis_data
135-
// (see above, there were stored in the parent J0AC) where the values
136-
// are located. This is used to get the actual values.
137-
let decode = |x: u16| -> Result<Matrix3<f64>> {
135+
// (see above, these were stored in the parent J0AC) where the values
136+
// are located. This lambda is used to get the actual values.
137+
let fetch_matrix = |x: u16| -> Result<Matrix3<f64>> {
138138
let mode = x.bits(15, 16);
139139
let idx = x.bits(0, 15) as usize;
140140
Ok(match mode {
@@ -161,18 +161,26 @@ pub fn read_animation(base_cur: Cur, name: Name) -> Result<Animation> {
161161
if is_const {
162162
let v = cur.next::<u16>()?;
163163
let _ = cur.next::<u16>()?; // Skipped? For alignment?
164-
trs_curves.rotation = Curve::Constant(decode(v)?);
164+
trs_curves.rotation = Curve::Constant(fetch_matrix(v)?);
165165
} else {
166166
let info = CurveInfo::from_u32(cur.next::<u32>()?);
167167
let off = cur.next::<u32>()?;
168168

169169
let start_frame = info.start_frame;
170170
let end_frame = info.end_frame;
171-
let values =
172-
(base_cur + off)
173-
.next_n::<u16>(info.num_samples())?
174-
.map(decode)
175-
.collect::<Result<Vec<Matrix3<f64>>>>()?;
171+
let values = {
172+
// Do this with an explicit with_capacity + push loop
173+
// because collecting an iterator into a Result doesn't
174+
// reserve the capacity in advance.
175+
// See rust-lang/rust/#48994.
176+
let num_samples = info.num_samples();
177+
let mut samples: Vec<Matrix3<f64>> =
178+
Vec::with_capacity(num_samples);
179+
for v in (base_cur + off).next_n::<u16>(num_samples)? {
180+
samples.push(fetch_matrix(v)?);
181+
}
182+
samples
183+
};
176184

177185
trs_curves.rotation = Curve::Samples {
178186
start_frame, end_frame, values,

0 commit comments

Comments
 (0)