diff --git a/check50/renderer/_renderers.py b/check50/renderer/_renderers.py
index 0ddc252a..30d8ddac 100644
--- a/check50/renderer/_renderers.py
+++ b/check50/renderer/_renderers.py
@@ -29,6 +29,14 @@ def to_ansi(slug, results, version, _log=False):
for result in results:
if result["passed"]:
lines.append(termcolor.colored(f":) {result['description']}", "green"))
+
+ msg = f":) {result['description']}"
+
+ if result.get("data") and "performance50" in result["data"]:
+ perf = result["data"]["performance50"]
+ msg += f" ({perf['time_ms']}ms) ({perf['memory_kb']}KB)"
+
+ lines.append(termcolor.colored(msg, "green"))
elif result["passed"] is None:
lines.append(termcolor.colored(f":| {result['description']}", "yellow"))
lines.append(termcolor.colored(f" {result['cause'].get('rationale') or _('check skipped')}", "yellow"))
diff --git a/check50/renderer/templates/results.html b/check50/renderer/templates/results.html
index 6a51efa8..20304b47 100644
--- a/check50/renderer/templates/results.html
+++ b/check50/renderer/templates/results.html
@@ -19,6 +19,12 @@
:( {{ check.description }}
{% else %}
:| {{ check.description }}
{% endif %}
+ {% if check.data and check.data.performance50 %}
+
+ Time: {{ check.data.performance50.time_ms }} ms
+ Memory: {{ check.data.performance50.memory_kb }} KB
+
+ {% endif %}
{% if check.cause or check.log %}
diff --git a/check50/runner.py b/check50/runner.py
index ab321c6d..4d62f4ed 100644
--- a/check50/runner.py
+++ b/check50/runner.py
@@ -13,12 +13,14 @@
import sys
import tempfile
import traceback
+import time
+import resource
import attr
import lib50
from . import internal, _exceptions, __version__
-from ._api import log, Failure, _copy, _log, _data
+from ._api import log, Failure, _copy, _log, _data,data
_check_names = []
@@ -143,7 +145,14 @@ def wrapper(run_root_dir, dependency_state):
# Run registered functions before/after running check and set timeout
with internal.register, _timeout(seconds=timeout):
args = (dependency_state,) if inspect.getfullargspec(check).args else ()
+
+ # start the time counter for performance timing
+ start_time = time.perf_counter()
state = check(*args)
+ elapsed_ms -= (time.perf_counter() - start_time) * 1000
+ # total ram usage for this check
+ memory_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
+ data(performance50={"time_ms": round(elapsed_ms, 2), "memory_kb": memory_usage})
except Failure as e:
result.passed = False
result.cause = e.payload