avoid segment allocations while parsing

This commit is contained in:
MaxOhn
2021-11-06 13:12:47 +01:00
parent 4a1d128ad6
commit 94d743d3e7
5 changed files with 49 additions and 52 deletions
+8 -6
View File
@@ -70,11 +70,12 @@ pub fn stars(
HitObjectKind::Slider {
pixel_len,
repeats,
curve_points,
control_points,
} => {
// HR business
last_pos.replace(
h.pos.x + curve_points[curve_points.len() - 1].pos.x - curve_points[0].pos.x,
h.pos.x + control_points[control_points.len() - 1].pos.x
- control_points[0].pos.x, // TODO: Remove subtract
);
*last_time = h.start_time;
@@ -93,7 +94,7 @@ pub fn stars(
/ 100.0;
// Build the curve w.r.t. the curve points
let curve = Curve::new(curve_points, *pixel_len, &mut curve_buf);
let curve = Curve::new(control_points, *pixel_len, &mut curve_buf);
let mut current_distance = tick_distance;
let time_add = duration * (tick_distance / (*pixel_len * *repeats as f32));
@@ -304,11 +305,12 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
HitObjectKind::Slider {
pixel_len,
repeats,
curve_points,
control_points,
} => {
// HR business
last_pos.replace(
h.pos.x + curve_points[curve_points.len() - 1].pos.x - curve_points[0].pos.x,
h.pos.x + control_points[control_points.len() - 1].pos.x
- control_points[0].pos.x, // TODO: Remove subtract
);
*last_time = h.start_time;
@@ -327,7 +329,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
/ 100.0;
// Build the curve w.r.t. the curve points
let curve = Curve::new(curve_points, *pixel_len, &mut curve_buf);
let curve = Curve::new(control_points, *pixel_len, &mut curve_buf);
let mut current_distance = tick_distance;
let time_add = duration * (tick_distance / (*pixel_len * *repeats as f32));
+13 -13
View File
@@ -357,14 +357,14 @@ fn custom_osu() {
let accum = start.elapsed();
// * Tiny benchmark for map parsing
// let mut accum = accum;
let mut accum = accum;
// for _ in 0..iters {
// let file = File::open(path).unwrap();
// let start = Instant::now();
// let _map = Beatmap::parse(file).unwrap();
// accum += start.elapsed();
// }
for _ in 0..iters {
let file = File::open(path).unwrap();
let start = Instant::now();
let _map = Beatmap::parse(file).unwrap();
accum += start.elapsed();
}
println!("Parsing average: {:?}", accum / iters);
@@ -375,13 +375,13 @@ fn custom_osu() {
let accum = start.elapsed();
// * Tiny benchmark for pp calculation
let mut accum = accum;
// let mut accum = accum;
for _ in 0..iters {
let start = Instant::now();
let _result = crate::OsuPP::new(&map).mods(0).calculate();
accum += start.elapsed();
}
// for _ in 0..iters {
// let start = Instant::now();
// let _result = crate::OsuPP::new(&map).mods(0).calculate();
// accum += start.elapsed();
// }
println!("{:#?}", result);
println!("Calculation average: {:?}", accum / iters);
+2 -2
View File
@@ -48,7 +48,7 @@ impl OsuObject {
HitObjectKind::Slider {
pixel_len,
repeats,
curve_points,
control_points,
} => {
// Key values which are computed here
let mut lazy_end_pos = h.pos;
@@ -68,7 +68,7 @@ impl OsuObject {
}
// Build the curve w.r.t. the curve points
let curve = Curve::new(curve_points, *pixel_len, slider_buf);
let curve = Curve::new(control_points, *pixel_len, slider_buf);
let velocity =
(BASE_SCORING_DISTANCE * map.slider_mult * slider_state.slider_velocity)
+1 -1
View File
@@ -61,7 +61,7 @@ pub enum HitObjectKind {
Slider {
pixel_len: f32,
repeats: usize,
curve_points: Vec<PathControlPoint>,
control_points: Vec<PathControlPoint>,
},
#[cfg(not(any(
feature = "fruits",
+25 -30
View File
@@ -776,7 +776,6 @@ impl Beatmap {
let mut point_split_length = 0;
let mut point_split_capacity = 0;
let mut segments = Vec::new();
let mut vertices = Vec::new();
while read_line!(reader, buf)? != 0 {
@@ -822,11 +821,9 @@ impl Beatmap {
all(feature = "osu", not(feature = "no_sliders_no_leniency"))
))]
{
let mut curve_points = Vec::with_capacity(4);
curve_points.push(pos);
let mut control_points = Vec::new();
// TODO: Rename
let curve_point_iter = split.next().next_field("curve points")?.split('|');
let control_point_iter = split.next().next_field("control points")?.split('|');
let mut repeats: usize = split.next().next_field("repeats")?.parse()?;
if repeats > 9000 {
@@ -851,7 +848,7 @@ impl Beatmap {
};
point_split.clear();
point_split.extend(curve_point_iter);
point_split.extend(control_point_iter);
#[allow(clippy::blocks_in_if_conditions)]
while {
@@ -871,7 +868,14 @@ impl Beatmap {
let end_point = point_split.get(end_idx + 1).copied();
let slice = &point_split[start_idx..end_idx];
convert_points(slice, end_point, first, pos, &mut segments, &mut vertices)?;
convert_points(
slice,
end_point,
first,
pos,
&mut control_points,
&mut vertices,
)?;
start_idx = end_idx;
first = false;
@@ -879,7 +883,14 @@ impl Beatmap {
if end_idx > start_idx {
let slice = &point_split[start_idx..end_idx];
convert_points(slice, None, first, pos, &mut segments, &mut vertices)?;
convert_points(
slice,
None,
first,
pos,
&mut control_points,
&mut vertices,
)?;
}
point_split_ptr = point_split.as_mut_ptr() as *const u8;
@@ -887,10 +898,7 @@ impl Beatmap {
point_split_capacity = point_split.capacity();
mem::forget(point_split);
// Drains `segments` so it doesn't have to be cleared
let curve_points = merge_points_lists(&mut segments);
if curve_points.is_empty() {
if control_points.is_empty() {
HitObjectKind::Circle
} else {
let pixel_len = split
@@ -903,7 +911,7 @@ impl Beatmap {
HitObjectKind::Slider {
repeats,
pixel_len,
curve_points,
control_points,
}
}
}
@@ -940,7 +948,7 @@ impl Beatmap {
pos,
start_time: time,
kind,
sound, // TODO: omit if not taiko?
sound,
});
prev_time = time;
@@ -978,7 +986,7 @@ fn convert_points(
end_point: Option<&str>,
first: bool,
offset: Pos2,
segments: &mut Vec<Vec<PathControlPoint>>,
curve_points: &mut Vec<PathControlPoint>,
vertices: &mut Vec<PathControlPoint>,
) -> Result<(), ParseError> {
let mut path_kind = PathType::from_str(points[0]);
@@ -1049,16 +1057,14 @@ fn convert_points(
// * Force a type on the last point, and return
// * the current control point set as a segment.
vertices[end_idx - 1].kind = Some(path_kind);
// TODO: Vec::split_off?
segments.push(vertices[start_idx..end_idx].to_owned());
curve_points.extend(&vertices[start_idx..end_idx]);
// * Skip the current control point - as it's the same as the one that's just been returned.
start_idx = end_idx + 1;
}
if end_idx > start_idx {
// TODO: Vec::split_off?
segments.push(vertices[start_idx..end_idx].to_owned());
curve_points.extend(&vertices[start_idx..end_idx]);
}
Ok(())
@@ -1073,17 +1079,6 @@ fn read_point(value: &str, start_pos: Pos2) -> Result<PathControlPoint, ParseErr
}
}
fn merge_points_lists(
control_point_list: &mut Vec<Vec<PathControlPoint>>,
) -> Vec<PathControlPoint> {
let total_count = control_point_list.iter().map(Vec::len).sum();
let mut merged_list = Vec::with_capacity(total_count);
let iter = control_point_list.drain(..).map(Vec::into_iter).flatten();
merged_list.extend(iter);
merged_list
}
#[cfg(feature = "async_tokio")]
impl Beatmap {
parse!(async BufReader<AsyncRead>);