Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[draft] top-level profiling #3431

Draft
wants to merge 26 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f5a88e9
aligned special keywords in binding.d
mahrud Aug 23, 2024
765c09c
added profile keyword
mahrud Aug 24, 2024
22b97da
added depth to stacktrace
mahrud Aug 24, 2024
a62e1f8
keyword profile works
mahrud Aug 24, 2024
7a4c350
added breakpoint keyword
mahrud Aug 24, 2024
1db9dcc
store Position objects in vector
mahrud Aug 24, 2024
6e3ef97
stored stacktraces as Position sequences
mahrud Aug 24, 2024
970e30a
added comments for profiler.dd
mahrud Aug 24, 2024
602a71c
improved profile to return a tally
mahrud Aug 25, 2024
6120034
setup profileSummary to display a leaderboard
mahrud Aug 25, 2024
0620175
added timing data to profileSummary
mahrud Aug 25, 2024
0da3645
fixed a variable name conflict in EngineTests
mahrud Aug 25, 2024
181abb5
added typical value for elapsedTiming and threadLocal
mahrud Aug 25, 2024
a82725c
setup tvalues.m2 to be remade if it's not complete
mahrud Aug 25, 2024
cdfff42
removed keyword profile from a test
mahrud Aug 25, 2024
4e1d1cb
conditioned few printed messages on debugLevel
mahrud Aug 25, 2024
e9f8693
added test for of Adjacent code
mahrud Aug 26, 2024
430d8b6
reduced code duplication in the profiler
mahrud Aug 26, 2024
99e55cf
added support for line by line profiling
mahrud Aug 27, 2024
8d1c917
added profiling for ifCode
mahrud Aug 27, 2024
2cb301b
removed suprefluous forward declaration
mahrud Aug 27, 2024
3944c06
added profileSummary methods for locatable things
mahrud Aug 27, 2024
08e35b8
added coverageSummary
mahrud Aug 27, 2024
abacf25
removed old profile code
mahrud Aug 27, 2024
76f4731
added format for ZZ and QQ
mahrud Aug 31, 2024
8b79255
exported stacktrace
mahrud Sep 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 12 additions & 27 deletions M2/Macaulay2/bin/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,10 @@ int main(/* const */ int argc, /* const */ char *argv[], /* const */ char *env[]

/* ######################################################################### */

std::ofstream prof_log;
thread_local std::vector<char*> M2_stack;

void stack_trace(std::ostream &stream, bool M2) {
if(M2) {
stream << "M2";
for (char* M2_frame : M2_stack)
stream << ";" << M2_frame;
stream << std::endl;
void profiler_stacktrace(std::ostream &stream, int traceDepth) {
if(0 < traceDepth) {
// TODO: pipe output to the stream
profiler_stacktrace(traceDepth);
} else {
stream << "-* stack trace, pid: " << (long) getpid() << std::endl;
stream << boost::stacktrace::stacktrace();
Expand All @@ -139,29 +134,19 @@ void stack_trace(std::ostream &stream, bool M2) {
}

void M2_flint_abort(void) {
stack_trace(std::cerr, false);
profiler_stacktrace(std::cerr, 0);
abort();
}

extern "C" {
void M2_stack_trace() { stack_trace(std::cout, false); }
#if PROFILING
void M2_stack_push(char* M2_frame) { M2_stack.emplace_back(M2_frame); }
void M2_stack_pop() { M2_stack.pop_back(); }
#else
void M2_stack_push(char* M2_frame) {}
void M2_stack_pop() {}
#endif
}

void* profFunc(ArgCell* p)
{
using namespace std::chrono_literals;
std::string filename("profile-" + std::to_string(getpid())+ ".raw");
// std::cerr << "Saving profile data in " << filename << std::endl;
prof_log.open(filename, std::ios::out | std::ios::trunc );
std::cerr << "-- Storing profiling data in " << filename << std::endl;
std::ofstream prof_log(filename, std::ios::out | std::ios::trunc );
while(true) {
std::this_thread::sleep_for(1000ms);
// use prime number to avoid oversampling scheduled tasks
std::this_thread::sleep_for(997ms);
tryGlobalTrace();
}
return NULL;
Expand Down Expand Up @@ -235,7 +220,7 @@ extern "C" void oursignal(int sig, void (*handler)(int)) {

void trace_handler(int sig) {
if (tryGlobalTrace() == 0)
stack_trace(prof_log, true);
profiler_stacktrace(std::cerr, 1);
oursignal(SIGUSR1,trace_handler);
}

Expand All @@ -253,7 +238,7 @@ void segv_handler(int sig) {
fprintf(stderr,"-- SIGSEGV handler called a second time, aborting\n");
_exit(2);
}
stack_trace(std::cerr, false);
profiler_stacktrace(std::cerr, 0);
level --;
_exit(1);
}
Expand Down Expand Up @@ -292,7 +277,7 @@ void interrupt_handler(int sig) {
}
}
if (buf[0]=='b' || buf[0]=='B') {
stack_trace(std::cout, false);
profiler_stacktrace(std::cout, 0);
fprintf(stderr,"exiting\n");
exit(12);
}
Expand Down
1 change: 1 addition & 0 deletions M2/Macaulay2/d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ set(DLIST
xmlactors.d # removed unless WITH_XML
actors5.d
chrono.dd
profiler.dd
threads.dd
python.d # removed unless WITH_PYTHON
interface.dd interface2.d
Expand Down
1 change: 1 addition & 0 deletions M2/Macaulay2/d/Makefile.files.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ M2_SRCFILES += xmlactors.d
endif
M2_DFILES += actors5.d
M2_DFILES += chrono.dd
M2_DFILES += profiler.dd
M2_DFILES += threads.dd

ifeq (@PYTHON@,yes)
Expand Down
4 changes: 4 additions & 0 deletions M2/Macaulay2/d/actors4.d
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,8 @@ setupfun("connectionCount", connectionCount);
format(e:Expr):Expr := (
when e
is s:stringCell do toExpr("\"" + present(s.v) + "\"")
is ZZcell do e
is QQcell do e
is RRcell do format(Expr(Sequence(e)))
is RRicell do format(Expr(Sequence(e)))
is CCcell do format(Expr(Sequence(e)))
Expand All @@ -1102,6 +1104,8 @@ format(e:Expr):Expr := (
is Nothing do nothing else return WrongArgZZ(4);
if n > 5 then when args.4 is p:stringCell do sep = p.v else return WrongArgString(5);
when args.(n-1)
is x:ZZcell do toExpr(concatenate(format(s,ac,l,t,sep,toRR(x.v,defaultPrecision))))
is x:QQcell do toExpr(concatenate(format(s,ac,l,t,sep,toRR(x.v,defaultPrecision))))
is x:RRcell do toExpr(concatenate(format(s,ac,l,t,sep,x.v)))
is z:CCcell do toExpr(format(s,ac,l,t,sep,false,false,z.v))
else WrongArgRR(n)
Expand Down
6 changes: 4 additions & 2 deletions M2/Macaulay2/d/actors5.d
Original file line number Diff line number Diff line change
Expand Up @@ -1741,8 +1741,10 @@ storeInHashTable(
Expr(newCompiledFunction(storeGlobalDictionaries)));

getcwdfun(e:Expr):Expr := ( -- this has to be a function, because getcwd may fail
when e is s:Sequence do
if length(s) == 0 then cwd() else WrongNumArgs(0)
when e is s:Sequence do if length(s) != 0 then WrongNumArgs(0) else (
dir := getcwd();
if dir != "" then Expr(stringCell(dir))
else buildErrorPacket("can't get current working directory: " + syserrmsg()))
else WrongNumArgs(0));
setupfun("currentDirectory",getcwdfun);

Expand Down
45 changes: 23 additions & 22 deletions M2/Macaulay2/d/binding.d
Original file line number Diff line number Diff line change
Expand Up @@ -306,24 +306,25 @@ bumpPrecedence();
export leftparen := parens("(",")",precSpace, precRightParen, precRightParen);
export leftbrace := parens("{","}",precSpace, precRightParen, precRightParen);
parseWORD.precedence = prec; parseWORD.binaryStrength = nopr; parseWORD.unaryStrength = nopr;
export timeS := special("time",unaryop,precSpace,wide);
export timingS := special("timing",unaryop,precSpace,wide);
export elapsedTimeS := special("elapsedTime",unaryop,precSpace,wide);
export elapsedTimingS := special("elapsedTiming",unaryop,precSpace,wide);
export shieldS := special("shield",unaryop,precSpace,wide);
export TestS := special("TEST",unaryop,precSpace,wide);
export throwS := special("throw",nunaryop,precSpace,wide);
export returnS := special("return",nunaryop,precSpace,wide);
export breakS := special("break",nunaryop,precSpace,wide);
export continueS := special("continue",nunaryop,precSpace,wide);
export stepS := special("step",nunaryop,precSpace,wide);
-- export codePositionS := special("codePosition",unaryop,precSpace,narrow);
special("new",unarynew,precSpace,narrow);
special("for",unaryfor,precSpace,narrow);
special("while",unarywhile,precSpace,wide);
special("if",unaryif,precSpace,wide);
special("try",unarytry,precSpace,wide);
special("catch",unarycatch,precSpace,wide);
export TestS := special("TEST", unaryop, precSpace, wide);
export timeS := special("time", unaryop, precSpace, wide);
export timingS := special("timing", unaryop, precSpace, wide);
export elapsedTimeS := special("elapsedTime", unaryop, precSpace, wide);
export elapsedTimingS := special("elapsedTiming", unaryop, precSpace, wide);
export breakpointS := special("breakpoint", unaryop, precSpace, wide);
export profileS := special("profile", unaryop, precSpace, wide);
export shieldS := special("shield", unaryop, precSpace, wide);
export throwS := special("throw", nunaryop, precSpace, wide);
export returnS := special("return", nunaryop, precSpace, wide);
export breakS := special("break", nunaryop, precSpace, wide);
export continueS := special("continue", nunaryop, precSpace, wide);
export stepS := special("step", nunaryop, precSpace, wide);
special("new", unarynew, precSpace, narrow);
special("for", unaryfor, precSpace, narrow);
special("while", unarywhile, precSpace, wide);
special("if", unaryif, precSpace, wide);
special("try", unarytry, precSpace, wide);
special("catch", unarycatch, precSpace, wide);
bumpPrecedence();
export ParenStarParenS := makeKeyword(postfix("(*)"));
bumpPrecedence();
Expand Down Expand Up @@ -360,10 +361,10 @@ bumpPrecedence();
--export UnderscoreSharpS := makeKeyword(postfix("_#"));
bumpPrecedence();
--why are these using precSpace and not prec?
special("symbol",unarysymbol,precSpace,prec);
special("global",unaryglobal,precSpace,prec);
special("threadLocal",unarythread,precSpace,prec);
special("local",unarylocal,precSpace,prec);
special("symbol", unarysymbol, precSpace, prec);
special("global", unaryglobal, precSpace, prec);
special("threadLocal", unarythread, precSpace, prec);
special("local", unarylocal, precSpace, prec);
-----------------------------------------------------------------------------
export GlobalAssignS := makeProtectedSymbolClosure("GlobalAssignHook");
export GlobalAssignE := Expr(GlobalAssignS);
Expand Down
8 changes: 5 additions & 3 deletions M2/Macaulay2/d/chrono.dd
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ cpuTime(e:Expr):Expr := (
else WrongNumArgs(0));
setupfun("cpuTime", cpuTime);

cpuTimer(c:Code):Sequence := (
export cpuTimer(c:Code):Sequence := (
T0 := cpuTime();
ret := eval(c);
T1 := cpuTime();
Sequence(toExpr(T1 - T0), ret));

wallTimer(c:Code):Sequence := (
export wallTimer(c:Code):Sequence := (
T0 := Ccode(Chrono, "std::chrono::steady_clock::now()");
ret := eval(c);
-- Note: here we intentionally call evalraw so
-- that evalprof can call this function safely.
ret := evalraw(c);
T1 := Ccode(Chrono, "std::chrono::steady_clock::now()");
dT := double(Ccode(uint64_t, "(", T1, " - ", T0, ").count()"));
dT = dT/1000000000.;
Expand Down
9 changes: 9 additions & 0 deletions M2/Macaulay2/d/debugging.dd
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ use common;
use util;
use hashtables;

-- debugger is not defined until interp.dd
-- so we use a pointer and populate it later.
dummydebugger(f:Frame,c:Code):Expr := nullE;
export debuggerpointer := dummydebugger;

-- enters the debugger (defined in interp.dd) at that spot
breakpoint(c:Code):Expr := debuggerpointer(localFrame, c);
setupop(breakpointS, breakpoint);

export tostring(c:Code):string := (
when c
is x:nullCode do "(null)"
Expand Down
34 changes: 10 additions & 24 deletions M2/Macaulay2/d/evaluate.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ use hashtables;
use convertr;
use debugging;

-- evalprof is not defined until profiler.dd
-- so we use a pointer and populate it later.
dummyevalprof(c:Code):Expr := nullE;
export evalprofpointer := dummyevalprof;

export globalAssignmentHooks := newHashTableWithHash(mutableHashTableClass,nothingClass);
setupconst("globalAssignmentHooks",Expr(globalAssignmentHooks));
export threadLocal evalSequenceHadError := false;
Expand All @@ -14,6 +19,7 @@ threadLocal errorreturn := nullE;
threadLocal recycleBin := new array(Frame) len 20 do provide dummyFrame;
export trace := false;
threadLocal export backtrace := true;
threadLocal export profiling := false;
threadLocal lastCode := dummyCode;
threadLocal lastCodePosition := Position("",ushort(0),ushort(0),ushort(0),ushort(0),ushort(0),ushort(0),ushort(0));
export chars := new array(Expr) len 256 do (
Expand Down Expand Up @@ -1340,9 +1346,7 @@ export handleError(c:Code,e:Expr):Expr := (
if !err.printed || backtrace && localFrame != oldReportFrame then (
if debuggingMode && !stopIfError && (! (p.filename === "stdio")) then (
if !err.printed then printError(err);
printErrorMessage(err.position,"--entering debugger (type help to see debugger commands)");
z := debuggerFun(localFrame,c);
-- printErrorMessage(err.position,"--leaving debugger");
z := debuggerpointer(localFrame,c);
when z is z:Error do (
if z.message == breakMessage then buildErrorPacket(unwindMessage)
else if z.message == returnMessage then (
Expand Down Expand Up @@ -1373,28 +1377,10 @@ export handleError(c:Code,e:Expr):Expr := (
e))
else e);

header "extern void M2_stack_push(char*);";
header "extern void M2_stack_pop();";
header "extern void M2_stack_trace();";
stacktrace(e:Expr):Expr := (
Ccode(void,"M2_stack_trace()"); e );
setupfun("stacktrace",stacktrace);

evalprof(c:Code):Expr;
evalraw(c:Code):Expr;
export eval(c:Code):Expr := (
if Ccode(bool,"PROFILING == 1")
then Ccode(Expr,"evaluate_evalprof(",c,")")
else Ccode(Expr,"evaluate_evalraw(",c,")"));
export evalprof(c:Code):Expr := (
when c is f:semiCode do ( -- what makes semiCode special?
-- printErrorMessage(codePosition(c),"--evaluating a semiCode");
-- TODO: how to get f.name?
Ccode(void,"M2_stack_push(",tocharstar(tostring(codePosition(c))),")");
e := evalraw(c);
Ccode(void,"M2_stack_pop()");
e)
else evalraw(c));
if profiling -- see evalprof in profiling.dd
then Ccode(Expr, "evaluate_evalprofpointer(", c, ")")
else Ccode(Expr, "evaluate_evalraw(", c, ")"));
export evalraw(c:Code):Expr := (
-- # typical value: symbol SPACE, Function, Thing, Thing
-- better would for cancellation requests to set exceptionFlag:
Expand Down
6 changes: 5 additions & 1 deletion M2/Macaulay2/d/interp.dd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use evaluate;
use parser;
use texmacs;
use actors5;
use profiler;

import dirname(s:string):string;

Expand Down Expand Up @@ -493,6 +494,7 @@ debugger(f:Frame,c:Code):Expr := (
setDebuggingMode(false);
oldDebuggerCode := getGlobalVariable(currentS);
setGlobalVariable(currentS,Expr(PseudocodeClosure(f,c)));
printMessage(codePosition(c), "entering debugger (enter 'help' to see commands)");
incrementInterpreterDepth();
if debuggerHook != nullE then (
r := applyEE(debuggerHook,True);
Expand All @@ -503,12 +505,14 @@ debugger(f:Frame,c:Code):Expr := (
r := applyEE(debuggerHook,False);
when r is Error do return r else nothing;
);
if debugLevel != 0 then
printMessage(codePosition(c), "leaving debugger");
decrementInterpreterDepth();
setGlobalVariable(currentS,oldDebuggerCode);
setDebuggingMode(true);
recursionDepth = oldrecursionDepth;
ret);
debuggerFun = debugger;
debuggerpointer = debugger;

currentString := setupvar("currentString", nullE);
value(e:Expr):Expr := (
Expand Down
Loading
Loading