add jit timing feature

This commit is contained in:
Jake Hillion 2023-06-22 09:27:21 -07:00 committed by Jake Hillion
parent 63ac468a1f
commit 01c9573acb
9 changed files with 119 additions and 38 deletions

View File

@ -105,6 +105,9 @@ void addIncludes(const TypeGraph& typeGraph,
includes.emplace("functional");
includes.emplace("oi/types/st.h");
}
if (features[Feature::JitTiming]) {
includes.emplace("chrono");
}
for (const Type& t : typeGraph.finalTypes) {
if (const auto* c = dynamic_cast<const Container*>(&t)) {
includes.emplace(c->containerInfo_.header);
@ -684,10 +687,10 @@ void CodeGen::generate(
if (config_.features[Feature::TypedDataSegment]) {
FuncGen::DefineTopLevelGetSizeRefTyped(
code, SymbolService::getTypeName(drgnType));
code, SymbolService::getTypeName(drgnType), config_.features);
} else {
FuncGen::DefineTopLevelGetSizeRef(code,
SymbolService::getTypeName(drgnType));
FuncGen::DefineTopLevelGetSizeRef(
code, SymbolService::getTypeName(drgnType), config_.features);
}
if (VLOG_IS_ON(3)) {

View File

@ -42,6 +42,8 @@ std::string_view featureHelp(Feature f) {
return "Log information from the JIT code for debugging.";
case Feature::PolymorphicInheritance:
return "Follow polymorphic inheritance hierarchies in the probed object.";
case Feature::JitTiming:
return "Instrument the JIT code with timing for performance testing.";
case Feature::UnknownFeature:
throw std::runtime_error("should not ask for help for UnknownFeature!");

View File

@ -30,6 +30,7 @@
X(TypedDataSegment, "typed-data-segment") \
X(GenJitDebug, "gen-jit-debug") \
X(JitLogging, "jit-logging") \
X(JitTiming, "jit-timing") \
X(PolymorphicInheritance, "polymorphic-inheritance")
namespace ObjectIntrospection {

View File

@ -22,6 +22,9 @@
#include "oi/ContainerInfo.h"
using ObjectIntrospection::Feature;
using ObjectIntrospection::FeatureSet;
namespace {
const std::string typedValueFunc = R"(
@ -235,7 +238,8 @@ void FuncGen::DefineTopLevelGetObjectSize(std::string& testCode,
}
void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
const std::string& rawType) {
const std::string& rawType,
FeatureSet features) {
std::string func = R"(
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-attributes"
@ -243,21 +247,38 @@ void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
void __attribute__((used, retain)) getSize_%2$016x(const OIInternal::__ROOT_TYPE__& t)
#pragma GCC diagnostic pop
{
)";
if (features[Feature::JitTiming]) {
func += " const auto startTime = std::chrono::steady_clock::now();\n";
}
func += R"(
pointers.initialize();
pointers.add((uintptr_t)&t);
auto data = reinterpret_cast<uintptr_t*>(dataBase);
data[0] = oidMagicId;
data[1] = cookieValue;
data[2] = 0;
size_t dataSegOffset = 3 * sizeof(uintptr_t);
size_t dataSegOffset = 0;
data[dataSegOffset++] = oidMagicId;
data[dataSegOffset++] = cookieValue;
uintptr_t& writtenSize = data[dataSegOffset++];
writtenSize = 0;
uintptr_t& timeTakenNs = data[dataSegOffset++];
dataSegOffset *= sizeof(uintptr_t);
JLOG("%1% @");
JLOGPTR(&t);
OIInternal::getSizeType(t, dataSegOffset);
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
data[2] = dataSegOffset;
writtenSize = dataSegOffset;
dataBase += dataSegOffset;
)";
if (features[Feature::JitTiming]) {
func += R"(
timeTakenNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now() - startTime).count();
)";
}
func += R"(
}
)";
@ -267,7 +288,8 @@ void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
}
void FuncGen::DefineTopLevelGetSizeRefTyped(std::string& testCode,
const std::string& rawType) {
const std::string& rawType,
FeatureSet features) {
std::string func = R"(
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-attributes"
@ -275,17 +297,25 @@ void FuncGen::DefineTopLevelGetSizeRefTyped(std::string& testCode,
void __attribute__((used, retain)) getSize_%2$016x(const OIInternal::__ROOT_TYPE__& t)
#pragma GCC diagnostic pop
{
)";
if (features[Feature::JitTiming]) {
func += " const auto startTime = std::chrono::steady_clock::now();\n";
}
func += R"(
pointers.initialize();
pointers.add((uintptr_t)&t);
auto data = reinterpret_cast<uintptr_t*>(dataBase);
// TODO: Replace these with types::st::Uint64 once the VarInt decoding
// logic is moved out of OIDebugger and into new TreeBuilder.
data[0] = oidMagicId;
data[1] = cookieValue;
data[2] = 0;
size_t dataSegOffset = 0;
data[dataSegOffset++] = oidMagicId;
data[dataSegOffset++] = cookieValue;
uintptr_t& writtenSize = data[dataSegOffset++];
writtenSize = 0;
uintptr_t& timeTakenNs = data[dataSegOffset++];
size_t dataSegOffset = 3 * sizeof(uintptr_t);
dataSegOffset *= sizeof(uintptr_t);
JLOG("%1% @");
JLOGPTR(&t);
@ -310,8 +340,16 @@ void FuncGen::DefineTopLevelGetSizeRefTyped(std::string& testCode,
.write(123456789);
dataSegOffset = end.offset();
data[2] = dataSegOffset;
writtenSize = dataSegOffset;
dataBase += dataSegOffset;
)";
if (features[Feature::JitTiming]) {
func += R"(
timeTakenNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now() - startTime).count();
)";
}
func += R"(
}
)";
@ -342,7 +380,8 @@ void FuncGen::DefineTopLevelGetSizeRefRet(std::string& testCode,
}
void FuncGen::DefineTopLevelGetSizeSmartPtr(std::string& testCode,
const std::string& rawType) {
const std::string& rawType,
FeatureSet features) {
std::string func = R"(
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-attributes"
@ -350,19 +389,36 @@ void FuncGen::DefineTopLevelGetSizeSmartPtr(std::string& testCode,
void __attribute__((used, retain)) getSize_%2$016x(const OIInternal::__ROOT_TYPE__& t)
#pragma GCC diagnostic pop
{
)";
if (features[Feature::JitTiming]) {
func += " const auto startTime = std::chrono::steady_clock::now();\n";
}
func += R"(
pointers.initialize();
auto data = reinterpret_cast<uintptr_t*>(dataBase);
data[0] = oidMagicId;
data[1] = cookieValue;
data[2] = 0;
size_t dataSegOffset = 3 * sizeof(uintptr_t);
size_t dataSegOffset = 0;
data[dataSegOffset++] = oidMagicId;
data[dataSegOffset++] = cookieValue;
uintptr_t& writtenSize = data[dataSegOffset++];
writtenSize = 0;
uintptr_t& timeTakenNs = data[dataSegOffset++];
dataSegOffset *= sizeof(uintptr_t);
OIInternal::getSizeType(t, dataSegOffset);
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
data[2] = dataSegOffset;
writtenSize = dataSegOffset;
dataBase += dataSegOffset;
)";
if (features[Feature::JitTiming]) {
func += R"(
timeTakenNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now() - startTime).count();
)";
}
func += R"(
}
)";
@ -373,7 +429,7 @@ void FuncGen::DefineTopLevelGetSizeSmartPtr(std::string& testCode,
bool FuncGen::DeclareGetSizeFuncs(std::string& testCode,
const ContainerInfoRefSet& containerInfo,
bool chaseRawPointers) {
FeatureSet features) {
for (const ContainerInfo& cInfo : containerInfo) {
std::string ctype = cInfo.typeName;
ctype = ctype.substr(0, ctype.find("<", 0));
@ -383,7 +439,7 @@ bool FuncGen::DeclareGetSizeFuncs(std::string& testCode,
testCode.append(fmt.str());
}
if (chaseRawPointers) {
if (features[Feature::ChaseRawPointers]) {
testCode.append(
"template<typename T, typename = "
"std::enable_if_t<!std::is_pointer_v<std::decay_t<T>>>>\n");
@ -397,7 +453,7 @@ bool FuncGen::DeclareGetSizeFuncs(std::string& testCode,
bool FuncGen::DefineGetSizeFuncs(std::string& testCode,
const ContainerInfoRefSet& containerInfo,
bool chaseRawPointers) {
FeatureSet features) {
for (const ContainerInfo& cInfo : containerInfo) {
std::string ctype = cInfo.typeName;
ctype = ctype.substr(0, ctype.find("<", 0));
@ -407,7 +463,7 @@ bool FuncGen::DefineGetSizeFuncs(std::string& testCode,
testCode.append(fmt.str());
}
if (chaseRawPointers) {
if (features[Feature::ChaseRawPointers]) {
testCode.append("template<typename T, typename C>\n");
} else {
testCode.append("template<typename T>\n");

View File

@ -20,6 +20,7 @@
#include <string>
#include "oi/ContainerInfo.h"
#include "oi/Features.h"
namespace fs = std::filesystem;
@ -39,10 +40,10 @@ class FuncGen {
bool DeclareGetSizeFuncs(std::string& testCode,
const ContainerInfoRefSet& containerInfo,
bool chaseRawPointers);
ObjectIntrospection::FeatureSet features);
bool DefineGetSizeFuncs(std::string& testCode,
const ContainerInfoRefSet& containerInfo,
bool chaseRawPointers);
ObjectIntrospection::FeatureSet features);
static void DeclareGetContainer(std::string& testCode);
@ -54,16 +55,22 @@ class FuncGen {
const std::string& type,
const std::string& linkageName);
static void DefineTopLevelGetSizeRef(std::string& testCode,
const std::string& rawType);
static void DefineTopLevelGetSizeRefTyped(std::string& testCode,
const std::string& rawType);
static void DefineTopLevelGetSizeRef(
std::string& testCode,
const std::string& rawType,
ObjectIntrospection::FeatureSet features);
static void DefineTopLevelGetSizeRefTyped(
std::string& testCode,
const std::string& rawType,
ObjectIntrospection::FeatureSet features);
static void DefineTopLevelGetSizeRefRet(std::string& testCode,
const std::string& type);
static void DefineTopLevelGetSizeSmartPtr(std::string& testCode,
const std::string& rawType);
static void DefineTopLevelGetSizeSmartPtr(
std::string& testCode,
const std::string& rawType,
ObjectIntrospection::FeatureSet features);
static void DefineGetSizeTypedValueFunc(std::string& testCode,
const std::string& ctype);

View File

@ -3038,6 +3038,10 @@ bool OICodeGen::generateJitCode(std::string& code) {
// Required for the offsetof() macro
includedHeaders.insert("cstddef");
if (config.features[Feature::JitTiming]) {
includedHeaders.emplace("chrono");
}
for (const auto& e : includedHeaders) {
code.append("#include <");
code.append(e);
@ -3254,7 +3258,7 @@ bool OICodeGen::generateJitCode(std::string& code) {
functionsCode.append("namespace OIInternal {\nnamespace {\n");
functionsCode.append("// functions -----\n");
if (!funcGen.DeclareGetSizeFuncs(functionsCode, containerTypesFuncDef,
feature(Feature::ChaseRawPointers))) {
config.features)) {
LOG(ERROR) << "declaring get size for containers failed";
return false;
}
@ -3292,7 +3296,7 @@ bool OICodeGen::generateJitCode(std::string& code) {
}
if (!funcGen.DefineGetSizeFuncs(functionsCode, containerTypesFuncDef,
feature(Feature::ChaseRawPointers))) {
config.features)) {
LOG(ERROR) << "defining get size for containers failed";
return false;
}
@ -3389,9 +3393,11 @@ bool OICodeGen::generateJitCode(std::string& code) {
if (rootTypeStr.starts_with("unique_ptr") ||
rootTypeStr.starts_with("LowPtr") ||
rootTypeStr.starts_with("shared_ptr")) {
funcGen.DefineTopLevelGetSizeSmartPtr(functionsCode, rawTypeName);
funcGen.DefineTopLevelGetSizeSmartPtr(functionsCode, rawTypeName,
config.features);
} else {
funcGen.DefineTopLevelGetSizeRef(functionsCode, rawTypeName);
funcGen.DefineTopLevelGetSizeRef(functionsCode, rawTypeName,
config.features);
}
} else {
if (linkageName.empty()) {

View File

@ -2734,6 +2734,10 @@ bool OIDebugger::decodeTargetData(const DataHeader& dataHeader,
return false;
}
if (generatorConfig.features[Feature::JitTiming]) {
LOG(INFO) << "JIT Timing: " << dataHeader.timeTakenNs << "ns";
}
/*
* Currently we use MAX_INT to indicate two things:
* - a single MAX_INT indicates the end of results for the current object
@ -2744,6 +2748,7 @@ bool OIDebugger::decodeTargetData(const DataHeader& dataHeader,
outVec.push_back(0);
outVec.push_back(0);
outVec.push_back(0);
outVec.push_back(0);
uint64_t prevVal = 0;
while (true) {

View File

@ -265,6 +265,7 @@ class OIDebugger {
uintptr_t magicId;
uintptr_t cookie;
uintptr_t size;
uintptr_t timeTakenNs;
/*
* Flexible Array Member are not standard in C++, but this is

View File

@ -227,7 +227,7 @@ void TreeBuilder::build(const std::vector<uint64_t>& data,
th = &typeHierarchy;
oidData = &data;
oidDataIndex = 3; // HACK: OID's first 3 outputs are dummy 0s
oidDataIndex = 4; // HACK: OID's first 4 outputs are dummy 0s
ObjectIntrospection::Metrics::Tracing _("build_tree");
VLOG(1) << "Building tree...";