File: //usr/include/hphp/util/bisector.h
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_UTIL_BISECTOR_H_
#define incl_HPHP_UTIL_BISECTOR_H_
#include "hphp/util/compilation-flags.h"
#include "hphp/util/trace.h"
namespace HPHP {
/*
Use this class to help bisect issues with optimizations.
Declare a bisector via:
BISECTOR(name);
Then guard each optimization by
if (name.go(<optional msg>)) {
// do the optimization
}
Then run via eg
env TRACE=bisector:1 name2=1000000 <program>
and look in the trace output to see how many times the optimization happened.
eg:
name : 0
name : 1
name : 2
Now you can bisect down to the optimization thats causing issues by setting
name1 and name2 (name1 will default to 0 if not set). If name1 < name2 it
will run the optimizations in the interval [name1, name2). If name1 > name2
it will skip the optimizations in the interval [name2, name1).
Note that its usually best to at least start by bisecting with name2 only,
since (for some optimizations) skipping earlier optimizations can change
later results.
*/
struct BisectorHelper {
TRACE_SET_MOD(bisector)
explicit BisectorHelper(const char* e) : env(e) {
if (debug) {
auto const p1 = getenv((env + std::string("1")).c_str());
auto const p2 = getenv((env + std::string("2")).c_str());
if (p2) {
low = p1 ? atoi(p1) : 0;
high = atoi(p2);
}
}
}
bool go(const char* msg = nullptr) {
if (!debug || (!high && !low)) return true;
if ((count++ - low) < (high - low)) {
FTRACE(1, "{} : {} {}\n",
env, count - 1, msg ? msg : "");
return true;
}
return false;
}
private:
const char *env;
uint32_t low = 0u;
uint32_t high = 0u;
uint32_t count = 0u;
};
#define BISECTOR(name) static BisectorHelper name(#name);
}
#endif