Enum imara_diff::Algorithm

source ·
pub enum Algorithm {
    Histogram,
    Myers,
    MyersMinimal,
}
Expand description

imara-diff supports multiple different algorithms for computing an edit sequence. These algorithms have different performance and all produce different output.

Variants§

§

Histogram

A variation of the patience diff algorithm described by Bram Cohen’s blog post that uses a histogram to find the least common LCS. Just like the patience diff algorithm, this algorithm usually produces more human readable output then myers algorithm. However compared to the patience diff algorithm (which is slower then myers algorithm), the Histogram algorithm performs much better.

The implementation here was originally ported from git but has been significantly modified to improve performance. As a result it consistently performs better then myers algorithm (5%-100%) over a wide variety of test data. For example a benchmark of diffing linux kernel commits is shown below:

For pathological subsequences that only contain highly repeating tokens (64+ occurrences) the algorithm falls back on Myers algorithm (with heuristics) to avoid quadratic behavior.

Compared to Myers algorithm, the Histogram diff algorithm is more focused on providing human readable diffs instead of minimal diffs. In practice this means that the edit-sequences produced by the histogram diff are often longer then those produced by Myers algorithm.

The heuristic used by the histogram diff does not work well for inputs with small (often repeated) tokens. For example character diffs do not work well as most (english) text is madeup of a fairly small set of characters. The Histogram algorithm will automatically these cases and fallback to Myers algorithm. However this detection has a nontrivial overhead, so if its known upfront that the sort of tokens is very small Myers algorithm should be used instead.

§

Myers

An implementation of the linear space variant of Myers O((N+M)D) algorithm. The algorithm is enhanced with preprocessing that removes tokens that don’t occur in the other file at all. Furthermore two heuristics to the middle snake search are implemented that ensure reasonable runtime (mostly linear time complexity) even for large files.

Due to the divide and conquer nature of the algorithm the edit sequenced produced are still fairly small even when the middle snake search is aborted by a heuristic. However, the produced edit sequences are not guaranteed to be fully minimal. If that property is vital to you, use the MyersMinimal algorithm instead.

The implementation (including the preprocessing) are mostly ported from git and gnu-diff where Myers algorithm is used as the default diff algorithm. Therefore the used heuristics have been heavily battle tested and are known to behave well over a large variety of inputs

§

MyersMinimal

Same as Myers but the early abort heuristics are disabled to guarantee a minimal edit sequence. This can mean significant slowdown in pathological cases.

Trait Implementations§

source§

impl Clone for Algorithm

source§

fn clone(&self) -> Algorithm

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Algorithm

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Algorithm

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl PartialEq for Algorithm

source§

fn eq(&self, other: &Algorithm) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Copy for Algorithm

source§

impl Eq for Algorithm

source§

impl StructuralPartialEq for Algorithm

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

default unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> CloneToUninit for T
where T: Copy,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.