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