Skip to content

Commit

Permalink
Add combine based benchmark to catch exponential regression
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Westerlind committed Feb 4, 2020
1 parent 48d49d2 commit 74ac6e8
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
1 change: 1 addition & 0 deletions collector/benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,4 @@ programs.
- **wf-projection-stress-65510**: A stress test which showcases [quadratic
behavior](https://github.com/rust-lang/rust/issues/65510) (in the number of
associated type bounds).
- **trait-stress-68666**: A stress test which constructs a parser in the same manner that `combine` does. Showcases [exponential behavior](https://github.com/rust-lang/rust/issues/68666) in trait selection.
1 change: 1 addition & 0 deletions collector/benchmarks/trait-stress/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cargo.lock
11 changes: 11 additions & 0 deletions collector/benchmarks/trait-stress/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "combine"
version = "0.1.0"
authors = ["Markus Westerlind <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[workspace]
62 changes: 62 additions & 0 deletions collector/benchmarks/trait-stress/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::marker::PhantomData;

pub trait Parser<Input> {
type Output;

fn or<P2>(self, p: P2) -> Or<Self, P2>
where
Self: Sized,
P2: Parser<Input, Output = Self::Output>,
{
Or(self, p)
}
}

#[macro_export]
macro_rules! choice {
($first : expr) => {
$first
};
($first : expr, $($rest : expr),+) => {
$first.or(choice!($($rest),+))
}
}

pub struct Or<P1, P2>(P1, P2);
impl<Input, P1, P2> Parser<Input> for Or<P1, P2>
where
P1: Parser<Input, Output = P2::Output>,
P2: Parser<Input>,
{
type Output = P2::Output;
}

pub struct P<I, O>(PhantomData<fn(I) -> O>);
impl<Input, O> Parser<Input> for P<Input, O> {
type Output = O;
}

pub fn token<I>(_: u8) -> impl Parser<I, Output = u8> {
P(PhantomData)
}

fn mcc_payload_item<I>() -> impl Parser<I, Output = u8> {
choice!(
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G'),
token(b'G')
)
}

fn main() {}

0 comments on commit 74ac6e8

Please sign in to comment.