Skip to content

Commit

Permalink
adding PythonCProfileEvaluation Builtin (#867)
Browse files Browse the repository at this point in the history
Here is a proposal for a Builtin symbol that produces a Low-level
profile of the evaluation.
  • Loading branch information
mmatera authored Jun 14, 2023
1 parent 45b0ce8 commit b6ba601
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
56 changes: 56 additions & 0 deletions mathics/builtin/lowlevelprofile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-

"""
Low-level Profiling
Low-level (Python) profile from inside the Mathics interpreter
"""

import cProfile
import pstats
import sys
from io import StringIO

from mathics.builtin import Builtin
from mathics.core.attributes import A_HOLD_ALL_COMPLETE, A_PROTECTED
from mathics.core.convert.python import from_python
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.list import ListExpression
from mathics.core.symbols import SymbolNull


class PythonCProfileEvaluation(Builtin):
"""
<url>:Python:https://docs.python.org/3/library/profile.html</url>
<dl>
<dt>'PythonProfileEvaluation[$expr$]'
<dd>profile $expr$ with the Python's cProfiler.
</dl>
>> PythonCProfileEvaluation[a + b + 1]
= ...
"""

attributes = A_HOLD_ALL_COMPLETE | A_PROTECTED
summary_text = "profile the internal evaluation of an expression"

def eval(self, expr: Expression, evaluation: Evaluation):
"PythonCProfileEvaluation[expr_]"
profile_result = SymbolNull
textstream = StringIO()
if sys.version_info >= (3, 8):
with cProfile.Profile() as pr:
result = expr.evaluate(evaluation)
stats = pstats.Stats(pr, stream=textstream)
stats.strip_dirs().sort_stats(-1).print_stats()
# TODO: convert the string (or the statistics)
# into something like a WL Table, by splitting the
# rows and the columns. By now, just a string
# is returned.
profile_result = from_python(textstream.getvalue())
else:
result = expr.evaluate(evaluation)
return ListExpression(result, profile_result)
4 changes: 3 additions & 1 deletion mathics/docpipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def print_and_log(*args):


def compare(result, wanted) -> bool:
if result == wanted:
if wanted == "..." or result == wanted:
return True

if result is None or wanted is None:
Expand All @@ -67,8 +67,10 @@ def compare(result, wanted) -> bool:
wanted = wanted.splitlines()
if result == [] and wanted == ["#<--#"]:
return True

if len(result) != len(wanted):
return False

for r, w in zip(result, wanted):
wanted_re = re.escape(w.strip())
wanted_re = wanted_re.replace("\\.\\.\\.", ".*?")
Expand Down

0 comments on commit b6ba601

Please sign in to comment.