diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 1e17132f..dd7df011 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -349,7 +350,18 @@ EvalState::EvalState(const Strings & _searchPath, ref store) EvalState::~EvalState() -{ +{ /* + std::cout << std::endl << "============= " << std::endl; + std::cout << "Maps summary: " << std::endl; + std::cout << "============= " << std::endl; + std::cout << "FuncMap:" << std::endl; + for(auto e: profState.funcMap) { + std::cout << e.first << ": " << e.second << std::endl; + } + std::cout << std::endl << "FileMap:" << std::endl; + for(auto e: profState.fileMap) { + std::cout << e.first << ": " << e.second << std::endl; + } */ } @@ -1178,6 +1190,26 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po } nrFunctionCalls++; + /* Lo and behold. + + There's no way to get the symbol name in the Symbol class. + + That said, there's a ostream operator *WINK WINK* + */ + if (settings.profileEvaluation && lambda.name.set()) { + std::ostringstream ossFunc; + ossFunc << lambda.name; + string functionName = ossFunc.str(); + profState.registerFunction(functionName); + + if (pos.file.set()) { + std::ostringstream ossFi; + ossFi << pos.file; + string fileName = ossFi.str(); + profState.registerFile(fileName); + std::cout << "file: " << fileName << " funcName: " << functionName << " " << pos.line << ":" << pos.column << std::endl; + } + } if (countCalls) incrFunctionCall(&lambda); /* Evaluate the body. This is conditional on showTrace, because @@ -1978,5 +2010,39 @@ EvalSettings evalSettings; static GlobalConfig::Register r1(&evalSettings); +/* Profiler stuff +***************** +*/ + +ProfilerState::ProfilerState() { +} + +CompressedFileId ProfilerState::registerFile(FileName& fName) { + CompressedFileId fid; + auto it = fileMap.find(fName); + if(it == fileMap.end()) { + fid = currentFuncId; + fileMap.insert({fName,currentFuncId}); + currentFuncId++; + } + else { + fid = it->second; + } + return fid; +} + +CompressedFuncId ProfilerState::registerFunction(FunctionName& fName) { + CompressedFuncId fid; + auto it = funcMap.find(fName); + if(it == funcMap.end()) { + fid = currentFuncId; + funcMap.insert({fName,currentFuncId}); + currentFuncId++; + } + else { + fid = it->second; + } + return fid; +} } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 4997d139..92b5aa8a 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -20,6 +20,55 @@ class Store; class EvalState; enum RepairFlag : bool; +/* Profiler-related operations. + [callGrindSpec]: TODO: add URL */ + +typedef string FunctionName; +typedef string FileName; +typedef int CompressedFuncId; +typedef int CompressedFileId; +typedef int LineNumber; + +struct ProfFuncOcc { + CompressedFuncId funcId; + CompressedFileId fileId; +}; + +struct ProfFuncCall { + CompressedFuncId calledFunc; + CompressedFileId calledFile; + LineNumber calledFuncLineNb; + int cost; +}; + +struct ProfCostOcc { + CompressedFuncId funcId; + CompressedFileId fileId; + ProfFuncOcc funcOcc; + int selfCost; + std::vector calledFunctions; +}; + +class ProfilerState { + +public: + ProfilerState(); + CompressedFileId registerFile(FileName& fName); + CompressedFuncId registerFunction(FunctionName& fName); + ProfCostOcc& getFuncOcc(FileName& fName, FunctionName& fnName); + void saveCost(ProfCostOcc& occCost); + +public: + std::vector stackedMeasurements; + string funcName; + /* We index every func and file to leverage Callgrind's string compression. + See section "3.1.6.�Subposition Compression" section from [callgrindSpec]. */ + std::map funcMap; + std::map fileMap; + CompressedFuncId currentFuncId; + CompressedFileId currentFileId; +}; + typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v); @@ -315,7 +364,7 @@ private: friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); /* Profiler-related members */ - + ProfilerState profState; };