Skip to content

Commit

Permalink
add a benchmark for ericniebler/stl2#34
Browse files Browse the repository at this point in the history
  • Loading branch information
ericniebler committed Oct 5, 2018
1 parent 8c6dadb commit 887ec2a
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 31 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "external/google-benchmark"]
path = external/google-benchmark
url = https://github.com/google/benchmark.git

1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ install(
FILES ${PROJECT_BINARY_DIR}/cmcstl2-config.cmake
DESTINATION lib/cmake/cmcstl2)

add_subdirectory(benchmark)
add_subdirectory(examples)

enable_testing()
Expand Down
19 changes: 19 additions & 0 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# cmcstl2 - A concept-enabled C++ standard library
#
# Copyright Eric Niebler 2018
#
# Use, modification and distribution is subject to the
# Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# Project home: https://github.com/caseycarter/cmcstl2
#

find_package(Threads REQUIRED)

include_directories("../external/google-benchmark/include")
file(GLOB GOOGLE_BENCHMARK_FILES "../external/google-benchmark/src/*.cc")

add_executable(itinerary itinerary.cpp ${GOOGLE_BENCHMARK_FILES})
target_link_libraries(itinerary stl2 Threads::Threads)
173 changes: 173 additions & 0 deletions benchmark/itinerary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Tomasz Kamiński 2016
// Copyright Eric Niebler 2018
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2

#include <vector>
#include <algorithm>
#include <random>
#include <array>
#include <benchmark/benchmark.h>
#include <experimental/ranges/range>
#include <experimental/ranges/algorithm>

namespace std::experimental::ranges
{
template<class Ref>
struct any_view
{
any_view() = default;
template<class R>
requires !Same<decay_t<R>, any_view> && Range<R> &&
ConvertibleTo<iter_reference_t<iterator_t<R>>, Ref>
any_view(R&&)
{}
std::add_pointer_t<Ref> begin() const { return 0; }
std::add_pointer_t<Ref> end() const { return 0; }
};
template <Range R1, Range R2>
requires CommonReference<iter_reference_t<iterator_t<R1>>,
iter_reference_t<iterator_t<R2>>>
struct common_type<R1, R2>
{
using type =
any_view<common_reference_t<iter_reference_t<iterator_t<R1>>,
iter_reference_t<iterator_t<R2>>>>;
};
}

namespace ranges = std::experimental::ranges;

struct Date
{
int v;
};

bool operator==(Date d1, Date d2) { return d1.v == d2.v; }
bool operator!=(Date t1, Date t2) { return !(t1 == t2); }

bool operator<(Date d1, Date d2) { return d1.v < d2.v; }
bool operator>(Date t1, Date t2) { return t1 < t2; }
bool operator>=(Date t1, Date t2) { return !(t1 < t2); }
bool operator<=(Date t1, Date t2) { return !(t2 < t1); }

struct Leg
{
Date d;
Date departure_date() const { return d; }
};

struct Itinerary
{
std::vector<Leg> l;
std::vector<Leg> const& legs() const { return l; }
};

struct LegDepartureComparator
{
bool operator()(Date d, Leg const& l) const
{ return d < l.departure_date(); }

bool operator()(Leg const& l, Date d) const
{ return l.departure_date() < d; }

bool operator()(Leg const& l1, Leg const& l2) const
{ return l1.departure_date() < l2.departure_date(); }
};

struct ItineraryDepartureComparator
{
bool operator()(std::vector<Date> const& ds, Itinerary const& i) const
{ return std::lexicographical_compare(ds.begin(), ds.end(),
i.legs().begin(), i.legs().end(),
LegDepartureComparator()); }

bool operator()(Itinerary const& i, std::vector<Date> const& ds) const
{ return std::lexicographical_compare(i.legs().begin(), i.legs().end(),
ds.begin(), ds.end(),
LegDepartureComparator()); }

bool operator()(Itinerary const& i1, Itinerary const& i2) const
{ return std::lexicographical_compare(i1.legs().begin(), i1.legs().end(),
i2.legs().begin(), i2.legs().end(),
LegDepartureComparator()); }
};

class ItineraryFixture : public ::benchmark::Fixture {
public:
void SetUp(const ::benchmark::State& st)
{
std::size_t const elements = st.range(0);
std::size_t const legs = st.range(1);

std::mt19937 gen;
std::uniform_int_distribution<int> dist(0, 30);

dates.resize(legs);
for (Date& d : dates)
d.v = dist(gen);

itineraries.resize(elements);
for (Itinerary& itin : itineraries)
{
itin.l.resize(legs);
for (Leg& leg : itin.l)
leg.d.v = dist(gen);
}
std::sort(itineraries.begin(), itineraries.end(),
ItineraryDepartureComparator());
}

void TearDown(const ::benchmark::State&)
{
itineraries.clear();
dates.clear();
}

std::vector<Itinerary> itineraries;
std::vector<Date> dates;
};

BENCHMARK_DEFINE_F(ItineraryFixture, STL1)(benchmark::State& state)
{
while (state.KeepRunning())
{
benchmark::DoNotOptimize(
std::equal_range(itineraries.begin(), itineraries.end(),
dates, ItineraryDepartureComparator()));
}
}
BENCHMARK_REGISTER_F(ItineraryFixture, STL1)
-> Ranges({{1<<10, 1<<20}, {1,2}});

inline constexpr auto toDate = [](Leg const& l)
{
return l.departure_date();
};
inline constexpr auto toDates = [](Itinerary const& i)
{
return i.legs() |
ranges::view::transform(toDate);
};

BENCHMARK_DEFINE_F(ItineraryFixture, STL2)(benchmark::State& state)
{
while (state.KeepRunning())
{
benchmark::DoNotOptimize(
ranges::equal_range(
itineraries,
ranges::view::all(dates),
[](auto const& r1, auto const& r2) { return ranges::lexicographical_compare(r1, r2); },
toDates));
}
}
BENCHMARK_REGISTER_F(ItineraryFixture, STL2)
-> Ranges({{1<<10, 1<<20}, {1,2}});
1 change: 1 addition & 0 deletions external/google-benchmark
Submodule google-benchmark added at d93963
65 changes: 34 additions & 31 deletions include/stl2/detail/algorithm/lexicographical_compare.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,44 @@
// lexicographical_compare [alg.lex.comparison]
//
STL2_OPEN_NAMESPACE {
template<InputIterator I1, Sentinel<I1> S1, InputIterator I2, Sentinel<I2> S2,
class Comp = less<>, class Proj1 = identity, class Proj2 = identity>
requires
IndirectStrictWeakOrder<Comp,
projected<I1, Proj1>, projected<I2, Proj2>>
bool lexicographical_compare(I1 first1, S1 last1, I2 first2, S2 last2,
Comp comp = Comp{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{})
inline constexpr struct lexicographical_compare_fn
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (__stl2::invoke(comp, __stl2::invoke(proj1, *first1), __stl2::invoke(proj2, *first2))) {
return true;
}
if (__stl2::invoke(comp, __stl2::invoke(proj2, *first2), __stl2::invoke(proj1, *first1))) {
return false;
template <InputIterator I1, Sentinel<I1> S1, InputIterator I2, Sentinel<I2> S2,
class Comp = less<>, class Proj1 = identity, class Proj2 = identity>
requires
IndirectStrictWeakOrder<Comp,
projected<I1, Proj1>, projected<I2, Proj2>>
bool operator()(I1 first1, S1 last1, I2 first2, S2 last2,
Comp comp = Comp{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{}) const
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (__stl2::invoke(comp, __stl2::invoke(proj1, *first1), __stl2::invoke(proj2, *first2))) {
return true;
}
if (__stl2::invoke(comp, __stl2::invoke(proj2, *first2), __stl2::invoke(proj1, *first1))) {
return false;
}
}
return first1 == last1 && first2 != last2;
}
return first1 == last1 && first2 != last2;
}

template<InputRange Rng1, InputRange Rng2, class Comp = less<>,
class Proj1 = identity, class Proj2 = identity>
requires
IndirectStrictWeakOrder<Comp,
projected<iterator_t<Rng1>, Proj1>,
projected<iterator_t<Rng2>, Proj2>>
bool lexicographical_compare(Rng1&& rng1, Rng2&& rng2,
Comp comp = Comp{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{})
{
return __stl2::lexicographical_compare(
__stl2::begin(rng1), __stl2::end(rng1),
__stl2::begin(rng2), __stl2::end(rng2),
std::ref(comp),
std::ref(proj1),
std::ref(proj2));
}
template <InputRange Rng1, InputRange Rng2, class Comp = less<>,
class Proj1 = identity, class Proj2 = identity>
requires
IndirectStrictWeakOrder<Comp,
projected<iterator_t<Rng1>, Proj1>,
projected<iterator_t<Rng2>, Proj2>>
bool operator()(Rng1&& rng1, Rng2&& rng2,
Comp comp = Comp{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{}) const
{
return (*this)(
__stl2::begin(rng1), __stl2::end(rng1),
__stl2::begin(rng2), __stl2::end(rng2),
std::ref(comp),
std::ref(proj1),
std::ref(proj2));
}
} const lexicographical_compare {};
} STL2_CLOSE_NAMESPACE

#endif

0 comments on commit 887ec2a

Please sign in to comment.