mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
add jit timing feature
This commit is contained in:
parent
63ac468a1f
commit
01c9573acb
@ -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)) {
|
||||
|
@ -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!");
|
||||
|
@ -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 {
|
||||
|
100
oi/FuncGen.cpp
100
oi/FuncGen.cpp
@ -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");
|
||||
|
23
oi/FuncGen.h
23
oi/FuncGen.h
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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...";
|
||||
|
Loading…
Reference in New Issue
Block a user