mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
libexpr: Pass mutable EvalState
to EvalProfiler
Sometimes the profiler might want to do evaluation (e.g. for getting derivation names). This is not ideal, but is really necessary to make the profiler stack traces useful for end users.
This commit is contained in:
parent
543cee1c92
commit
128750225d
4 changed files with 20 additions and 29 deletions
|
@ -5,18 +5,14 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
void EvalProfiler::preFunctionCallHook(
|
||||
const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
}
|
||||
void EvalProfiler::preFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) {}
|
||||
|
||||
void EvalProfiler::postFunctionCallHook(
|
||||
const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
void EvalProfiler::postFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
}
|
||||
|
||||
void MultiEvalProfiler::preFunctionCallHook(
|
||||
const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
for (auto & profiler : profilers) {
|
||||
if (profiler->getNeededHooks().test(Hook::preFunctionCall))
|
||||
|
@ -25,7 +21,7 @@ void MultiEvalProfiler::preFunctionCallHook(
|
|||
}
|
||||
|
||||
void MultiEvalProfiler::postFunctionCallHook(
|
||||
const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
for (auto & profiler : profilers) {
|
||||
if (profiler->getNeededHooks().test(Hook::postFunctionCall))
|
||||
|
@ -126,7 +122,7 @@ class SampleStack : public EvalProfiler
|
|||
}
|
||||
|
||||
public:
|
||||
SampleStack(const EvalState & state, std::filesystem::path profileFile, std::chrono::nanoseconds period)
|
||||
SampleStack(EvalState & state, std::filesystem::path profileFile, std::chrono::nanoseconds period)
|
||||
: state(state)
|
||||
, sampleInterval(period)
|
||||
, profileFd([&]() {
|
||||
|
@ -140,9 +136,9 @@ public:
|
|||
}
|
||||
|
||||
[[gnu::noinline]] void
|
||||
preFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
preFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
[[gnu::noinline]] void
|
||||
postFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
postFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
|
||||
void maybeSaveProfile(std::chrono::time_point<std::chrono::high_resolution_clock> now);
|
||||
void saveProfile();
|
||||
|
@ -156,7 +152,7 @@ public:
|
|||
|
||||
private:
|
||||
/** Hold on to an instance of EvalState for symbolizing positions. */
|
||||
const EvalState & state;
|
||||
EvalState & state;
|
||||
std::chrono::nanoseconds sampleInterval;
|
||||
AutoCloseFD profileFd;
|
||||
FrameStack stack;
|
||||
|
@ -191,7 +187,7 @@ FrameInfo SampleStack::getFrameInfoFromValueAndPos(const Value & v, PosIdx pos)
|
|||
}
|
||||
|
||||
[[gnu::noinline]] void SampleStack::preFunctionCallHook(
|
||||
const EvalState & state, const Value & v, [[maybe_unused]] std::span<Value *> args, const PosIdx pos)
|
||||
EvalState & state, const Value & v, [[maybe_unused]] std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
stack.push_back(getFrameInfoFromValueAndPos(v, pos));
|
||||
|
||||
|
@ -208,9 +204,8 @@ FrameInfo SampleStack::getFrameInfoFromValueAndPos(const Value & v, PosIdx pos)
|
|||
}
|
||||
|
||||
[[gnu::noinline]] void
|
||||
SampleStack::postFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
SampleStack::postFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
|
||||
if (!stack.empty())
|
||||
stack.pop_back();
|
||||
}
|
||||
|
@ -300,8 +295,7 @@ SampleStack::~SampleStack()
|
|||
|
||||
} // namespace
|
||||
|
||||
ref<EvalProfiler>
|
||||
makeSampleStackProfiler(const EvalState & state, std::filesystem::path profileFile, uint64_t frequency)
|
||||
ref<EvalProfiler> makeSampleStackProfiler(EvalState & state, std::filesystem::path profileFile, uint64_t frequency)
|
||||
{
|
||||
/* 0 is a special value for sampling stack after each call. */
|
||||
std::chrono::nanoseconds period = frequency == 0
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
namespace nix {
|
||||
|
||||
void FunctionCallTrace::preFunctionCallHook(
|
||||
const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
auto duration = std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
|
||||
|
@ -12,7 +12,7 @@ void FunctionCallTrace::preFunctionCallHook(
|
|||
}
|
||||
|
||||
void FunctionCallTrace::postFunctionCallHook(
|
||||
const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos)
|
||||
{
|
||||
auto duration = std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
|
||||
|
|
|
@ -62,8 +62,7 @@ public:
|
|||
* @param args Function arguments.
|
||||
* @param pos Function position.
|
||||
*/
|
||||
virtual void
|
||||
preFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos);
|
||||
virtual void preFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos);
|
||||
|
||||
/**
|
||||
* Hook called on EvalState::callFunction exit.
|
||||
|
@ -74,8 +73,7 @@ public:
|
|||
* @param args Function arguments.
|
||||
* @param pos Function position.
|
||||
*/
|
||||
virtual void
|
||||
postFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos);
|
||||
virtual void postFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos);
|
||||
|
||||
virtual ~EvalProfiler() = default;
|
||||
|
||||
|
@ -106,12 +104,11 @@ public:
|
|||
void addProfiler(ref<EvalProfiler> profiler);
|
||||
|
||||
[[gnu::noinline]] void
|
||||
preFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
preFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
[[gnu::noinline]] void
|
||||
postFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
postFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
};
|
||||
|
||||
ref<EvalProfiler>
|
||||
makeSampleStackProfiler(const EvalState & state, std::filesystem::path profileFile, uint64_t frequency);
|
||||
ref<EvalProfiler> makeSampleStackProfiler(EvalState & state, std::filesystem::path profileFile, uint64_t frequency);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ public:
|
|||
FunctionCallTrace() = default;
|
||||
|
||||
[[gnu::noinline]] void
|
||||
preFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
preFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
[[gnu::noinline]] void
|
||||
postFunctionCallHook(const EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
postFunctionCallHook(EvalState & state, const Value & v, std::span<Value *> args, const PosIdx pos) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue