Skip to content

Commit

Permalink
Skip printed lines when computing hunk matched lines
Browse files Browse the repository at this point in the history
This function is hot for textual diffs, such as the sample files in
issue #293. For those files, this produces a 21% reduction in
instruction count.
  • Loading branch information
Wilfred committed Jun 15, 2022
1 parent 95ba06a commit 6ade731
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 6 deletions.
16 changes: 12 additions & 4 deletions src/display/hunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,10 +595,10 @@ fn either_side_equal(
false
}

pub fn matched_lines_for_hunk<'a>(
matched_lines: &'a [(Option<LineNumber>, Option<LineNumber>)],
pub fn matched_lines_indexes_for_hunk(
matched_lines: &[(Option<LineNumber>, Option<LineNumber>)],
hunk: &Hunk,
) -> &'a [(Option<LineNumber>, Option<LineNumber>)] {
) -> (usize, usize) {
let mut hunk_lhs_novel = hunk.novel_lhs.iter().copied().collect::<Vec<_>>();
hunk_lhs_novel.sort();

Expand Down Expand Up @@ -645,7 +645,7 @@ pub fn matched_lines_for_hunk<'a>(
end_i = matched_lines.len();
}

&matched_lines[start_i..end_i]
(start_i, end_i)
}

#[cfg(test)]
Expand Down Expand Up @@ -758,6 +758,14 @@ mod tests {
assert_eq!(hunks[0].lines, vec![(Some(0.into()), Some(0.into()))]);
}

fn matched_lines_for_hunk<'a>(
matched_lines: &'a [(Option<LineNumber>, Option<LineNumber>)],
hunk: &Hunk,
) -> &'a [(Option<LineNumber>, Option<LineNumber>)] {
let (start_i, end_i) = matched_lines_indexes_for_hunk(matched_lines, hunk);
&matched_lines[start_i..end_i]
}

#[test]
fn test_matched_lines_for_hunk() {
let matched_lines = &[
Expand Down
13 changes: 11 additions & 2 deletions src/display/side_by_side.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{cmp::max, collections::HashSet};
use crate::{
constants::Side,
display::context::all_matched_lines_filled,
display::hunks::{matched_lines_for_hunk, Hunk},
display::hunks::{matched_lines_indexes_for_hunk, Hunk},
display::style::{
self, apply_colors, color_positions, novel_style, split_and_apply, BackgroundColor,
},
Expand Down Expand Up @@ -385,6 +385,7 @@ pub fn print(
let mut prev_rhs_line_num = None;

let matched_lines = all_matched_lines_filled(lhs_mps, rhs_mps, &lhs_lines, &rhs_lines);
let mut matched_lines_to_print = &matched_lines[..];

for (i, hunk) in hunks.iter().enumerate() {
println!(
Expand All @@ -399,7 +400,15 @@ pub fn print(
)
);

let aligned_lines = matched_lines_for_hunk(&matched_lines, hunk);
let (start_i, end_i) = matched_lines_indexes_for_hunk(matched_lines_to_print, hunk);
let aligned_lines = &matched_lines_to_print[start_i..end_i];
// We iterate through hunks in order, so we know the next hunk
// must appear after start_i. This makes
// `matched_lines_indexes_for_hunk` faster on later
// iterations, and this function is hot on large textual
// diffs.
matched_lines_to_print = &matched_lines_to_print[start_i..];

let no_lhs_changes = hunk.novel_lhs.is_empty();
let no_rhs_changes = hunk.novel_rhs.is_empty();
let same_lines = aligned_lines.iter().all(|(l, r)| l == r);
Expand Down

0 comments on commit 6ade731

Please sign in to comment.