mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-13 00:49:54 +00:00
Replace std::function with hyper_function for a 37% speedup in compile time.
Before: time c++ -O2 -DMAC -I/usr/local/include -std=c++11 -march=native -W -Wall -Wextra -Werror -pedantic -Wno-format-pedantic -Wno-missing-field-initializers -Wno-unused-parameter -DCAP_GLEW=0 -DCAP_PNG=0 -c hyper.cpp -o hyper.o real 2m22.508s user 2m20.625s sys 0m1.648s After: time c++ -O2 -DMAC -I/usr/local/include -std=c++11 -march=native -W -Wall -Wextra -Werror -pedantic -Wno-format-pedantic -Wno-missing-field-initializers -Wno-unused-parameter -DCAP_GLEW=0 -DCAP_PNG=0 -c hyper.cpp -o hyper.o real 1m30.515s user 1m29.793s sys 0m0.689s Comparing object file size: -rw-r--r-- 1 ajo staff 8215036 Jan 5 20:46 old-hyper.o -rw-r--r-- 1 ajo staff 7538072 Jan 5 20:47 new-hyper.o Comparing number of symbols: nm old-hyper.o | wc -l => 12590 nm new-hyper.o | wc -l => 9742 No appreciable difference in link time; the linker takes less than half a second in either case.
This commit is contained in:
parent
a478bb1485
commit
87240cf990
4
hyper.h
4
hyper.h
@ -7,6 +7,7 @@
|
||||
#define VERNUM_HEX 0xA505
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "hyper_function.h"
|
||||
|
||||
namespace hr {
|
||||
|
||||
@ -15,6 +16,8 @@ void ignore(T&&) {
|
||||
// placate GCC's overzealous -Wunused-result
|
||||
}
|
||||
|
||||
template<class Sig> using function = hyper_function<Sig>;
|
||||
|
||||
// functions and types used from the standard library
|
||||
using std::vector;
|
||||
using std::map;
|
||||
@ -24,7 +27,6 @@ using std::sort;
|
||||
using std::multimap;
|
||||
using std::set;
|
||||
using std::string;
|
||||
using std::function;
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
using std::shared_ptr;
|
||||
|
61
hyper_function.h
Normal file
61
hyper_function.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
template<class Sig>
|
||||
class hyper_function;
|
||||
|
||||
template<class R, class... Args>
|
||||
struct hyper_function_state_base {
|
||||
virtual R call(Args...) const = 0;
|
||||
virtual hyper_function_state_base *clone() const = 0;
|
||||
virtual ~hyper_function_state_base() = default;
|
||||
};
|
||||
|
||||
template<class T, class R, class... Args>
|
||||
struct hyper_function_state : hyper_function_state_base<R, Args...> {
|
||||
using Self = hyper_function_state<T, R, Args...>;
|
||||
T t_;
|
||||
explicit hyper_function_state(T t) : t_(std::move(t)) {}
|
||||
R call(Args... args) const override {
|
||||
return const_cast<T&>(t_)(static_cast<Args&&>(args)...);
|
||||
}
|
||||
hyper_function_state_base<R, Args...> *clone() const override {
|
||||
return new Self(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R, class... Args>
|
||||
class hyper_function<R(Args...)>
|
||||
{
|
||||
hyper_function_state_base<R, Args...> *ptr_ = nullptr;
|
||||
public:
|
||||
hyper_function() = default;
|
||||
|
||||
template<class Callable, class = decltype(R(std::declval<typename std::decay<Callable>::type>()(std::declval<Args>()...)))>
|
||||
hyper_function(Callable&& t) :
|
||||
ptr_(new hyper_function_state<typename std::decay<Callable>::type, R, Args...>(static_cast<Callable&&>(t)))
|
||||
{}
|
||||
|
||||
~hyper_function() {
|
||||
delete ptr_;
|
||||
}
|
||||
|
||||
hyper_function(hyper_function& rhs) : ptr_(rhs.ptr_ ? rhs.ptr_->clone() : nullptr) {}
|
||||
hyper_function(const hyper_function& rhs) : ptr_(rhs.ptr_ ? rhs.ptr_->clone() : nullptr) {}
|
||||
hyper_function(hyper_function&& rhs) noexcept : ptr_(rhs.ptr_) { rhs.ptr_ = nullptr; }
|
||||
hyper_function(const hyper_function&& rhs) = delete;
|
||||
|
||||
void operator=(hyper_function rhs) noexcept {
|
||||
std::swap(ptr_, rhs.ptr_);
|
||||
}
|
||||
|
||||
R operator()(Args... args) const {
|
||||
return ptr_->call(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user