Compare commits
1 Commits
71bfa35647
...
f3b71acc0b
Author | SHA1 | Date |
---|---|---|
Félix Baylac-Jacqué | f3b71acc0b |
|
@ -11,12 +11,13 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
@ -966,10 +967,9 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v)
|
||||||
std::ostringstream ossName;
|
std::ostringstream ossName;
|
||||||
ossName << *this;
|
ossName << *this;
|
||||||
string name = ossName.str();
|
string name = ossName.str();
|
||||||
ProfilerCallLevel lvl {&(this->pos), name, ProfilerCallLevel::var};
|
state.profState.jumpInValue(&(this->pos), name, ProfilerCallType::var);
|
||||||
state.profState.jumpInValue(lvl);
|
|
||||||
state.forceValue(*v2, pos);
|
state.forceValue(*v2, pos);
|
||||||
state.profState.createCallgraphentry(lvl);
|
state.profState.jumpOutValue();
|
||||||
}
|
}
|
||||||
v = *v2;
|
v = *v2;
|
||||||
}
|
}
|
||||||
|
@ -1032,10 +1032,10 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||||
std::ostringstream ossName;
|
std::ostringstream ossName;
|
||||||
ossName << *this;
|
ossName << *this;
|
||||||
string name = ossName.str();
|
string name = ossName.str();
|
||||||
ProfilerCallLevel lvl {pos2 != NULL ? pos2 : &(this->pos), name, ProfilerCallLevel::select};
|
Pos* fpos = pos2 != NULL ? pos2 : &(this->pos);
|
||||||
state.profState.jumpInValue(lvl);
|
state.profState.jumpInValue(fpos, name, ProfilerCallType::select);
|
||||||
state.forceValue(*vAttrs, ( pos2 != NULL ? *pos2 : this->pos ) );
|
state.forceValue(*vAttrs, *fpos);
|
||||||
state.profState.createCallgraphentry(lvl);
|
state.profState.jumpOutValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
|
@ -1809,6 +1809,8 @@ void EvalState::printStats()
|
||||||
uint64_t bLists = nrListElems * sizeof(Value *);
|
uint64_t bLists = nrListElems * sizeof(Value *);
|
||||||
uint64_t bValues = nrValues * sizeof(Value);
|
uint64_t bValues = nrValues * sizeof(Value);
|
||||||
uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr);
|
uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr);
|
||||||
|
if(settings.profileEvaluation)
|
||||||
|
profState.printCallGraph();
|
||||||
|
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
GC_word heapSize, totalBytes;
|
GC_word heapSize, totalBytes;
|
||||||
|
@ -2035,16 +2037,19 @@ static GlobalConfig::Register r1(&evalSettings);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ProfilerState::ProfilerState():
|
ProfilerState::ProfilerState():
|
||||||
nestedLevel(0)
|
profilerTreeRoot(std::nullopt),
|
||||||
{}
|
lastProfilerCall(std::nullopt)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
CompressedFileId ProfilerState::registerFile(FileName& fName) {
|
CompressedFileId ProfilerState::registerFile(FileName& fName) {
|
||||||
CompressedFileId fid;
|
CompressedFileId fid;
|
||||||
auto it = fileMap.find(fName);
|
auto it = fileMap.find(fName);
|
||||||
if(it == fileMap.end()) {
|
if(it == fileMap.end()) {
|
||||||
fid = currentFuncId;
|
fid = currentFileId;
|
||||||
fileMap.insert({fName,currentFuncId});
|
fileMap.insert({fName,currentCostCenterId});
|
||||||
currentFuncId++;
|
currentFileId++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fid = it->second;
|
fid = it->second;
|
||||||
|
@ -2052,13 +2057,13 @@ CompressedFileId ProfilerState::registerFile(FileName& fName) {
|
||||||
return fid;
|
return fid;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompressedFuncId ProfilerState::registerFunction(CostCenterName& fName) {
|
CompressedCostCenterId ProfilerState::registerCostCenter(CostCenterName& fName) {
|
||||||
CompressedFuncId fid;
|
CompressedCostCenterId fid;
|
||||||
auto it = costMap.find(fName);
|
auto it = costMap.find(fName);
|
||||||
if(it == costMap.end()) {
|
if(it == costMap.end()) {
|
||||||
fid = currentFuncId;
|
fid = currentCostCenterId;
|
||||||
costMap.insert({fName,currentFuncId});
|
costMap.insert({fName,currentCostCenterId});
|
||||||
currentFuncId++;
|
currentCostCenterId++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fid = it->second;
|
fid = it->second;
|
||||||
|
@ -2066,36 +2071,139 @@ CompressedFuncId ProfilerState::registerFunction(CostCenterName& fName) {
|
||||||
return fid;
|
return fid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerState::jumpInValue(ProfilerCallLevel& call) {
|
void ProfilerState::jumpInValue(Pos* pos, CostCenterName name, ProfilerCallType type) {
|
||||||
|
std::shared_ptr<ProfilerCallLevel> call =
|
||||||
|
std::make_shared<ProfilerCallLevel>
|
||||||
|
(ProfilerCallLevel{
|
||||||
|
lastProfilerCall,
|
||||||
|
std::forward_list<ProfilerCallLevel*>(),
|
||||||
|
pos, name, type, false});
|
||||||
string delim="";
|
string delim="";
|
||||||
string opStr="";
|
string opStr="";
|
||||||
std::ostringstream srcPos;
|
std::ostringstream srcPos;
|
||||||
|
|
||||||
|
if (lastProfilerCall) {
|
||||||
|
lastProfilerCall->children.push_front(call);
|
||||||
|
} else {
|
||||||
|
std::cout << "Redifining tree root " << std::endl;
|
||||||
|
profilerTreeRoot = call;
|
||||||
|
}
|
||||||
callGraphStack.push(call);
|
callGraphStack.push(call);
|
||||||
|
lastProfilerCall = call;
|
||||||
|
|
||||||
|
// Printing stuff
|
||||||
int stackSize = callGraphStack.size();
|
int stackSize = callGraphStack.size();
|
||||||
for(int i=0;i<stackSize;i++) {
|
for(int i=0;i<stackSize;i++) {
|
||||||
delim+="=";
|
delim+="=";
|
||||||
}
|
}
|
||||||
switch (call.callType) {
|
switch (type) {
|
||||||
case ProfilerCallLevel::select:
|
case ProfilerCallType::select:
|
||||||
opStr="select";
|
opStr="select";
|
||||||
break;
|
break;
|
||||||
case ProfilerCallLevel::var:
|
case ProfilerCallType::var:
|
||||||
opStr="var";
|
opStr="var";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(call.pos->file.set()) {
|
if(pos->file.set()) {
|
||||||
std::ostringstream ossFi;
|
std::ostringstream ossFi;
|
||||||
ossFi << call.pos->file;
|
ossFi << pos->file;
|
||||||
string fileName = ossFi.str();
|
string fileName = ossFi.str();
|
||||||
srcPos << fileName << " " << call.pos->line << ":" << call.pos->column;
|
srcPos << fileName << " " << pos->line << ":" << pos->column;
|
||||||
} else {
|
} else {
|
||||||
srcPos << "NOT DEFINED";
|
srcPos << "NOT DEFINED";
|
||||||
}
|
}
|
||||||
std::cout << delim << " " << opStr << "::" << call.name << " " << srcPos.str() << std::endl;
|
//std::cout << delim << " " << opStr << "::" << name << " " << srcPos.str() << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerState::createCallgraphentry(ProfilerCallLevel& call) {
|
void ProfilerState::jumpOutValue() {
|
||||||
|
if (!callGraphStack.empty())
|
||||||
|
lastProfilerCall = callGraphStack.top().get().parent.get();
|
||||||
|
else {
|
||||||
|
std::cout << "jumpOutValue, CONDITION CHELOUE" << std::endl;
|
||||||
|
}
|
||||||
callGraphStack.pop();
|
callGraphStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProfilerState::printCallGraph() {
|
||||||
|
std::stack<ProfilerCallLevel*> nodesToProcess;
|
||||||
|
std::ostringstream ossFi;
|
||||||
|
LineNumber line;
|
||||||
|
nodesToProcess.push(profilerTreeRoot);
|
||||||
|
|
||||||
|
while(!nodesToProcess.empty()) {
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
// Get Node struct
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
auto currentNode = nodesToProcess.top();
|
||||||
|
if (!currentNode->visited) {
|
||||||
|
nodesToProcess.pop();
|
||||||
|
currentNode->visited = true;
|
||||||
|
std::cout << "Current stack size: " << nodesToProcess.size() << std::endl;
|
||||||
|
string fileName;
|
||||||
|
if(currentNode->pos->file.set()) {
|
||||||
|
ossFi << currentNode->pos->file;
|
||||||
|
fileName = ossFi.str();
|
||||||
|
} else {
|
||||||
|
fileName = "NOT DEFINED";
|
||||||
|
}
|
||||||
|
FileName fname = fileName;
|
||||||
|
CostCenterName ccname = currentNode->name;
|
||||||
|
line = currentNode->pos->line;
|
||||||
|
PosCost entryPos = {line, 666};
|
||||||
|
CallGraphCostEntry costEntry = { fname, ccname, std::forward_list<CallGraphCall>(), entryPos };
|
||||||
|
auto children = currentNode->children;
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
// Create Children Structs
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
PosCost posCost;
|
||||||
|
CallGraphCall call;
|
||||||
|
for (auto it = children.begin(); it != children.end(); it++) {
|
||||||
|
nodesToProcess.push(*it);
|
||||||
|
if((*it)->pos->file.set()) {
|
||||||
|
ossFi << (*it)->pos->file;
|
||||||
|
fileName = ossFi.str();
|
||||||
|
} else {
|
||||||
|
fileName = "NOT DEFINED";
|
||||||
|
}
|
||||||
|
line = (*it)->pos->line;
|
||||||
|
posCost = { line, 666 };
|
||||||
|
/* fid = registerFile(fileName);
|
||||||
|
ccid = registerCostCenter(currentNode->name); */
|
||||||
|
call = { fileName, (*it)->name, posCost };
|
||||||
|
costEntry.calls.push_front(call);
|
||||||
|
}
|
||||||
|
costEntries.push_front(costEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
renderCostEntries(costEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerState::renderCostEntries(std::forward_list<CallGraphCostEntry> costEntries){
|
||||||
|
for (auto i = costEntries.begin(); i != costEntries.end(); i++) {
|
||||||
|
std::cout << "fl=" << i->fileName << std::endl;
|
||||||
|
std::cout << "fn=" << i->costCenter << std::endl;
|
||||||
|
std::cout << i->pos.line << " " << i->pos.cost << std::endl;
|
||||||
|
auto calls = i->calls;
|
||||||
|
for (auto j = calls.begin(); j != calls.end(); j++) {
|
||||||
|
std::cout << "cfi=" << j->fileName << std::endl;
|
||||||
|
std::cout << "cfn=" << j->costCenter << std::endl;
|
||||||
|
std::cout << "calls=" << "1 " << j->pos.cost << std::endl;
|
||||||
|
std::cout << "1 " << i->pos.line << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fl=(1) file1.c
|
||||||
|
fn=(1) main
|
||||||
|
16 20
|
||||||
|
cfn=(2) func1
|
||||||
|
calls=1 50
|
||||||
|
16 400
|
||||||
|
cfi=(2) file2.c
|
||||||
|
cfn=(3) func2
|
||||||
|
calls=3 20
|
||||||
|
16 400*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "function-trace.hh"
|
#include "function-trace.hh"
|
||||||
|
|
||||||
|
#include <forward_list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <optional>
|
||||||
|
#include <optional>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -25,34 +28,43 @@ enum RepairFlag : bool;
|
||||||
|
|
||||||
typedef string CostCenterName;
|
typedef string CostCenterName;
|
||||||
typedef string FileName;
|
typedef string FileName;
|
||||||
typedef int CompressedFuncId;
|
typedef int CompressedCostCenterId;
|
||||||
typedef int CompressedFileId;
|
typedef int CompressedFileId;
|
||||||
typedef int LineNumber;
|
typedef int LineNumber;
|
||||||
|
typedef int BullshitCost;
|
||||||
|
|
||||||
struct ProfFuncOcc {
|
struct PosCost {
|
||||||
CompressedFuncId funcId;
|
LineNumber line;
|
||||||
CompressedFileId fileId;
|
BullshitCost cost;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProfFuncCall {
|
struct CallCost {
|
||||||
CompressedFuncId calledFunc;
|
LineNumber line;
|
||||||
CompressedFileId calledFile;
|
int nbCalls;
|
||||||
LineNumber calledFuncLineNb;
|
|
||||||
int cost;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProfCostOcc {
|
struct CallGraphCall {
|
||||||
CompressedFuncId funcId;
|
FileName fileName;
|
||||||
CompressedFileId fileId;
|
CostCenterName costCenter;
|
||||||
ProfFuncOcc funcOcc;
|
PosCost pos;
|
||||||
int selfCost;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CallGraphCostEntry {
|
||||||
|
FileName fileName;
|
||||||
|
CostCenterName costCenter;
|
||||||
|
std::forward_list<CallGraphCall> calls;
|
||||||
|
PosCost pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ProfilerCallType { select=0, var};
|
||||||
|
|
||||||
struct ProfilerCallLevel {
|
struct ProfilerCallLevel {
|
||||||
|
std::shared_ptr<ProfilerCallLevel> parent;
|
||||||
|
std::forward_list<std::shared_ptr<ProfilerCallLevel>> children;
|
||||||
Pos* pos;
|
Pos* pos;
|
||||||
CostCenterName name;
|
CostCenterName name;
|
||||||
enum { select=0, var} callType;
|
ProfilerCallType type;
|
||||||
|
bool visited;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProfilerState {
|
class ProfilerState {
|
||||||
|
@ -60,21 +72,23 @@ class ProfilerState {
|
||||||
public:
|
public:
|
||||||
ProfilerState();
|
ProfilerState();
|
||||||
CompressedFileId registerFile(FileName& fName);
|
CompressedFileId registerFile(FileName& fName);
|
||||||
CompressedFuncId registerFunction(CostCenterName& fName);
|
CompressedCostCenterId registerCostCenter(CostCenterName& fName);
|
||||||
ProfCostOcc& getFuncOcc(FileName& fName, CostCenterName& fnName);
|
void jumpInValue(Pos* pos, CostCenterName name, ProfilerCallType type);
|
||||||
void saveCost(ProfCostOcc& occCost);
|
void jumpOutValue();
|
||||||
void jumpInValue(ProfilerCallLevel& call);
|
void printCallGraph();
|
||||||
void createCallgraphentry(ProfilerCallLevel& call);
|
|
||||||
int nestedLevel;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* We index every func and file to leverage Callgrind's string compression.
|
/* We index every func and file to leverage Callgrind's string compression.
|
||||||
See section "3.1.6.<EFBFBD>Subposition Compression" section from [callgrindSpec]. */
|
See section "3.1.6.Subposition Compression" section from [callgrindSpec]. */
|
||||||
std::map<CostCenterName,CompressedFuncId> costMap;
|
std::map<CostCenterName,CompressedCostCenterId> costMap;
|
||||||
std::map<FileName,CompressedFileId> fileMap;
|
std::map<FileName,CompressedFileId> fileMap;
|
||||||
CompressedFuncId currentFuncId;
|
CompressedCostCenterId currentCostCenterId;
|
||||||
CompressedFileId currentFileId;
|
CompressedFileId currentFileId;
|
||||||
std::stack<ProfilerCallLevel> callGraphStack;
|
std::stack<std::shared_ptr<ProfilerCallLevel>> callGraphStack;
|
||||||
|
std::optional<std::shared_ptr<ProfilerCallLevel>> lastProfilerCall;
|
||||||
|
std::optional<std::shared_ptr<ProfilerCallLevel>> profilerTreeRoot;
|
||||||
|
std::forward_list<CallGraphCostEntry> costEntries;
|
||||||
|
void renderCostEntries(std::forward_list<CallGraphCostEntry> costEntries);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::ostream & operator << (std::ostream & str, const Symbol & sym);
|
friend std::ostream & operator << (std::ostream & str, const Symbol & sym);
|
||||||
|
|
||||||
|
string str() const
|
||||||
|
{
|
||||||
|
return *s;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SymbolTable
|
class SymbolTable
|
||||||
|
|
Loading…
Reference in New Issue