return make_pair(sum / n, sqrt((sum2 - sum * sum / n) / n));
}
+/**
+ * Computes the mode of a sample set through brute force. Assumes
+ * input is sorted.
+ */
+static double mode(const double * begin, const double *const end) {
+ assert(begin < end);
+ // Lower bound and upper bound for result and their respective
+ // densities.
+ auto
+ result = 0.0,
+ bestDensity = 0.0;
+
+ // Get the variance so we pass it down to density()
+ auto const sigma = meanVariance(begin, end).second;
+ if (!sigma) {
+ // No variance means constant signal
+ return *begin;
+ }
+
+ FOR_EACH_RANGE (i, begin, end) {
+ assert(i == begin || *i >= i[-1]);
+ auto candidate = density(begin, end, *i, sigma * sqrt(2.0));
+ if (candidate > bestDensity) {
+ // Found a new best
+ bestDensity = candidate;
+ result = *i;
+ } else {
+ // Density is decreasing... we could break here if we definitely
+ // knew this is unimodal.
+ }
+ }
+
+ return result;
+}
+
/**
* Given a bunch of benchmark samples, estimate the actual run time.
*/
// Current state of the art: get the minimum. After some
// experimentation, it seems taking the minimum is the best.
+
return *min_element(begin, end);
+
+ // What follows after estimates the time as the mode of the
+ // distribution.
+
+ // Select the awesomest (i.e. most frequent) result. We do this by
+ // sorting and then computing the longest run length.
+ sort(begin, end);
+
+ // Eliminate outliers. A time much larger than the minimum time is
+ // considered an outlier.
+ while (end[-1] > 2.0 * *begin) {
+ --end;
+ if (begin == end) {
+ LOG(INFO) << *begin;
+ }
+ assert(begin < end);
+ }
+
+ double result = 0;
+
+ /* Code used just for comparison purposes */ {
+ unsigned bestFrequency = 0;
+ unsigned candidateFrequency = 1;
+ double candidateValue = *begin;
+ for (auto current = begin + 1; ; ++current) {
+ if (current == end || *current != candidateValue) {
+ // Done with the current run, see if it was best
+ if (candidateFrequency > bestFrequency) {
+ bestFrequency = candidateFrequency;
+ result = candidateValue;
+ }
+ if (current == end) {
+ break;
+ }
+ // Start a new run
+ candidateValue = *current;
+ candidateFrequency = 1;
+ } else {
+ // Cool, inside a run, increase the frequency
+ ++candidateFrequency;
+ }
+ }
+ }
+
+ result = mode(begin, end);
+
+ return result;
}
static double runBenchmarkGetNSPerIteration(const BenchmarkFun& fun,
* limitations under the License.
*/
-#include <folly/dynamic.h>
-
-#include <folly/Assume.h>
#include <folly/Hash.h>
+#include <folly/dynamic.h>
#include <folly/portability/BitsFunctexcept.h>
namespace folly {
const auto& str = getString();
return ::folly::hash::fnv32_buf(str.data(), str.size());
}
+ default:
+ CHECK(0); abort();
}
- assume_unreachable();
}
char const* dynamic::typeName(Type t) {
break; // Continue parsing
case OnError::THROW:
stack_.throwErrors(); // Package releaseErrors() into an exception.
+ LOG(FATAL) << "Not reached"; // silence lint false positive
default:
LOG(FATAL) << "Bad onError_: " << static_cast<int>(onError_);
}
namespace __cxxabiv1 {
extern "C" {
-[[noreturn]] void __cxa_throw(
+void __cxa_throw(
void* thrownException,
std::type_info* type,
- void (*destructor)(void*));
+ void (*destructor)(void*)) __attribute__((__noreturn__));
void* __cxa_begin_catch(void* excObj) throw();
-[[noreturn]] void __cxa_rethrow(void);
+void __cxa_rethrow(void) __attribute__((__noreturn__));
+void __cxa_rethrow(void);
void __cxa_end_catch(void);
}
namespace __cxxabiv1 {
-[[noreturn]] void __cxa_throw(void* thrownException,
- std::type_info* type,
- void (*destructor)(void*)) {
+void __cxa_throw(void* thrownException,
+ std::type_info* type,
+ void (*destructor)(void*)) {
static auto orig_cxa_throw =
reinterpret_cast<decltype(&__cxa_throw)>(dlsym(RTLD_NEXT, "__cxa_throw"));
getCxaThrowCallbacks().invoke(thrownException, type, destructor);
orig_cxa_throw(thrownException, type, destructor);
- __builtin_unreachable();
+ __builtin_unreachable(); // orig_cxa_throw never returns
}
-[[noreturn]] void __cxa_rethrow() {
+void __cxa_rethrow() {
// __cxa_rethrow leaves the current exception on the caught stack,
// and __cxa_begin_catch recognizes that case. We could do the same, but
// we'll implement something simpler (and slower): we pop the exception from
dlsym(RTLD_NEXT, "__cxa_rethrow"));
getCxaRethrowCallbacks().invoke();
orig_cxa_rethrow();
- __builtin_unreachable();
+ __builtin_unreachable(); // orig_cxa_rethrow never returns
}
void* __cxa_begin_catch(void* excObj) throw() {
"_ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE"));
getRethrowExceptionCallbacks().invoke(ep);
orig_rethrow_exception(ep);
- // Clang knows this is unreachable, but GCC doesn't.
-#ifndef __clang__
- __builtin_unreachable();
-#endif
+ __builtin_unreachable(); // orig_rethrow_exception never returns
}
} // namespace std
dispatchJobs(executor, jobs, results);
throw std::runtime_error(
"Unexpected exception in user code before commit called");
- // atomicBatchDispatcher.commit();
+ atomicBatchDispatcher.commit();
} catch (...) {
/* User code handles the exception and does not exit process */
}