bolero-MURAKAMI / Sprout

C++11/14 constexpr based Containers, Algorithms, Random numbers, Parsing, Ray tracing, Synthesizer, and others.

Home Page:http://bolero-murakami.github.io/Sprout/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Suggestion on 'sprout::tpp::all_of'

xiangfan-ms opened this issue · comments

Hi,
I'm a compiler developer from Microsoft. We build lots of RWC (real world code) projects daily to validate compiler changes and we also use the projects to identify areas to improve compiler throughput.
I recently find that 'sprout::tpp::all_of' is fairly heavy-weight and often contributes a significant amount to the compile time.
For example, 'default_remake_container' in 'sprout\container\container_construct_traits.hpp' takes a long time to do overload resolution when compiling the test testspr\sprout.cpp. This is related to the SFINAE condition in one of its overload.
It is expensive mainly because there is a specialization of 'sprout::tpp::all_of' which has 256 template arugments.

Here are some potential ways to reduce the cost:

template<bool> struct helper {};
template<> struct helper<true> { static const bool value = true; };
#ifndef FASTER
				&& !(sizeof...(Args) == 2 && sprout::tpp::all_of<sprout::is_input_iterator<typename std::remove_reference<Args>::type>...>::value)
#else
				// && !(helper<sizeof...(Args) == 2>::value && sprout::tpp::all_of<sprout::is_input_iterator<typename std::remove_reference<Args>::type>...>::value) // this approach forces the compiler to exit early when 'sizeof...(Args) == 2' is false by causing a substitution failure using 'helper'
				&& !(sizeof...(Args) == 2 && std::conjunction_v<sprout::is_input_iterator<typename std::remove_reference<Args>::type>...>) // std::conjunction_v yields the same result and is much light-weight
#endif
With either change, the compile time is improved by 10% when using clang-cl, and is improved by 30% when using MSVC.