goalc: add a performance report feature

This commit is contained in:
Tyler Wilding 2024-05-14 23:14:48 -04:00
parent 4aafab2fc9
commit d3ccda6d6e
No known key found for this signature in database
GPG Key ID: BF7B068C2FEFD7EF
7 changed files with 98 additions and 21 deletions

1
.gitignore vendored
View File

@ -76,3 +76,4 @@ __pycache__/
/TODO.md
unifont-15.0.03.ttf
*.diff
goalc-report.html

View File

@ -10846,9 +10846,7 @@
["_stack_", 76, "float"],
["_stack_", 100, "float"]
],
"real-wang-texture-anim-func": [
[[3, 31], "v1", "mood-context"]
],
"real-wang-texture-anim-func": [[[3, 31], "v1", "mood-context"]],
"(method 24 sky-work)": [
[256, "s4", "(pointer int32)"],
[261, "s4", "(pointer int32)"]
@ -10865,12 +10863,8 @@
[67, "s5", "(pointer int32)"],
[72, "s5", "(pointer int32)"]
],
"(method 38 sky-work)": [
[[83, 179], "v1", "(inline-array qword)"]
],
"(method 14 sky-work)": [
[[80, 256], "s4", "sky-work"]
],
"(method 38 sky-work)": [[[83, 179], "v1", "(inline-array qword)"]],
"(method 14 sky-work)": [[[80, 256], "s4", "sky-work"]],
"(method 13 sky-work)": [
[65, "v1", "(pointer uint128)"],
[[70, 77], "a0", "vector4w"],

View File

@ -997,8 +997,8 @@
`(make ,(string-append "$OUT/iso/" file ".DGO"))
)
(defmacro make-group (name &key (verbose #f) &key (force #f))
`(make ,(string-append "GROUP:" name) :verbose ,verbose :force ,force)
(defmacro make-group (name &key (verbose #f) &key (force #f) &key (report #f))
`(make ,(string-append "GROUP:" name) :verbose ,verbose :force ,force :report ,report)
)
(defmacro rl ()
@ -1014,6 +1014,10 @@
`(make-group "iso")
)
(defmacro mi-report ()
"Make ISO with Report"
`(make-group "iso" :report #t))
(defmacro mkr ()
"Make kernel"
`(make-group "kernel")

View File

@ -824,7 +824,8 @@ Val* Compiler::compile_make(const goos::Object& form, const goos::Object& rest,
auto args = get_va(form, rest);
va_check(form, args, {goos::ObjectType::STRING},
{{"force", {false, {goos::ObjectType::SYMBOL}}},
{"verbose", {false, {goos::ObjectType::SYMBOL}}}});
{"verbose", {false, {goos::ObjectType::SYMBOL}}},
{"report", {false, {goos::ObjectType::SYMBOL}}}});
bool force = false;
if (args.has_named("force")) {
force = get_true_or_false(form, args.get_named("force"));
@ -835,7 +836,12 @@ Val* Compiler::compile_make(const goos::Object& form, const goos::Object& rest,
verbose = get_true_or_false(form, args.get_named("verbose"));
}
m_make.make(args.unnamed.at(0).as_string()->data, force, verbose);
bool report = false;
if (args.has_named("report")) {
report = get_true_or_false(form, args.get_named("report"));
}
m_make.make(args.unnamed.at(0).as_string()->data, force, verbose, report);
return get_none();
}

View File

@ -0,0 +1,41 @@
#pragma once
#include <string>
const std::string compiler_report_base =
"<!doctypehtml><html lang=en><meta charset=UTF-8><meta "
"content=\"width=device-width,initial-scale=1\"name=viewport><title>OpenGOALc "
"Report</"
"title><style>html{font-size:10pt;font-family:sans-serif}table{width:100%;border-collapse:"
"collapse;margin:20px 0;box-shadow:0 2px 3px rgba(0,0,0,.1)}thead "
"th{background-color:#4caf50;color:#fff;text-align:left;padding:12px "
"15px;font-weight:700}tbody tr{border-bottom:1px solid #ddd}tbody td{padding:12px 15px}tbody "
"tr:nth-child(even){background-color:#f2f2f2}tbody "
"tr:hover{background-color:#f1f1f1}table{margin:20px 0}</style><canvas height=75vh "
"id=chart></canvas><br>Compare Against: <select id=compare></select> Accepted Margin of Error "
"%: <input id=margin type=number value=15>File Regex: <input id=regex><button "
"onclick=renderData()>Apply</button><table id=table><thead><tr "
"id=table-head-row><th>File<tbody id=table-body></table><script "
"src=https://cdn.jsdelivr.net/npm/chart.js></script><script>\n// DATA BEGINS\nconst tests = "
"[]\n// DATA ENDS\nlet testOrder=[],tableData={};for(const test of "
"tests)for(const[fileName,fileTime]of(testOrder.push(test.name),document.getElementById("
"\"compare\").innerHTML+=`<option "
"value=\"${test.name}\">${test.name}</"
"option>`,Object.entries(test.files)))Object.keys(tableData).includes(fileName)||(tableData["
"fileName]={}),tableData[fileName][test.name]=fileTime;const "
"tableHeadRow=document.getElementById(\"table-head-row\");let tableHeadContents=\"\";for(const "
"testName of testOrder)tableHeadContents+=`<th>${testName}</th>`;function renderData(){let "
"e=parseInt(document.getElementById(\"margin\").value)/"
"100,t=document.getElementById(\"regex\").value;t=\"\"!==t?RegExp(t):void 0;let "
"a=document.getElementById(\"compare\").value;\"\"!==a&&a||(a=testOrder[0]);let "
"l=document.getElementById(\"table-body\");for(let[n,d]of(l.innerHTML=\"\",Object.entries("
"tableData)))if(void 0===t||t.test(n)){var o=`<tr><td>${n}</td>`;for(let r of "
"testOrder)Object.keys(d).includes(r)?a!==r&&Object.keys(d).includes(a)?d[r]>d[a]*(1+e)?o+=`<"
"td style=\"background-color: #faa;\">${d[r]}</td>`:d[r]<d[a]*(1-e)?o+=`<td "
"style=\"background-color: "
"#c7ffc7;\">${d[r]}</td>`:o+=`<td>${d[r]}</td>`:o+=`<td>${d[r]}</td>`:o+=\"<td>--</"
"td>\";l.innerHTML+=o+\"</tr>\"}}tableHeadRow.innerHTML+=tableHeadContents,renderData();const "
"ctx=document.getElementById(\"chart\");new "
"Chart(ctx,{type:\"bar\",data:{labels:tests.map(e=>e.name),datasets:[{label:\"Total "
"Time\",data:tests.map(e=>e.total),borderWidth:1}]},options:{scales:{y:{beginAtZero:!0,type:"
"\"logarithmic\",title:{display:!0,text:\"Seconds\"}}}}});</script>";

View File

@ -6,6 +6,7 @@
#include "common/util/Timer.h"
#include "common/util/string_util.h"
#include "goalc/make/CompilerReport.h"
#include "goalc/make/Tools.h"
#include "fmt/color.h"
@ -438,7 +439,7 @@ void print_input(const std::vector<std::string>& in, char end) {
}
} // namespace
bool MakeSystem::make(const std::string& target_in, bool force, bool verbose) {
bool MakeSystem::make(const std::string& target_in, bool force, bool verbose, bool gen_report) {
std::string target = m_path_map.apply_remaps(target_in);
auto deps = get_dependencies(target);
// lg::print("All deps:\n");
@ -454,6 +455,22 @@ bool MakeSystem::make(const std::string& target_in, bool force, bool verbose) {
// lg::print("{}\n", dep);
// }
fs::path report_path;
std::string report_output;
std::string report_contents;
if (gen_report) {
report_path = file_util::get_jak_project_dir() / "goalc-report.html";
lg::print("Will save compiler report to - {}", report_path.string());
// Check if a report is already there, if it is, we'll append to it instead of overwriting it
if (file_util::file_exists(report_path.string())) {
report_output = file_util::read_text_file(report_path);
} else {
report_output = compiler_report_base;
}
report_contents += fmt::format("tests.push({{'name': \"Test - {}\",'files': {{",
str_util::current_isotimestamp());
}
Timer make_timer;
lg::print("Building {} targets...\n", deps.size());
int i = 0;
@ -483,25 +500,39 @@ bool MakeSystem::make(const std::string& target_in, bool force, bool verbose) {
return false;
}
const auto seconds = step_timer.getSeconds();
if (verbose) {
if (step_timer.getSeconds() > 0.05) {
lg::print(fg(fmt::color::yellow), " {:.3f}\n", step_timer.getSeconds());
if (seconds > 0.05) {
lg::print(fg(fmt::color::yellow), " {:.3f}\n", seconds);
} else {
lg::print(" {:.3f}\n", step_timer.getSeconds());
lg::print(" {:.3f}\n", seconds);
}
} else {
if (step_timer.getSeconds() > 0.05) {
if (seconds > 0.05) {
lg::print("[{:3d}%] [{:8s}] ", percent, tool->name());
lg::print(fg(fmt::color::yellow), "{:.3f} ", step_timer.getSeconds());
lg::print(fg(fmt::color::yellow), "{:.3f} ", seconds);
print_input(rule->input, '\n');
} else {
lg::print("[{:3d}%] [{:8s}] {:.3f} ", percent, tool->name(), step_timer.getSeconds());
lg::print("[{:3d}%] [{:8s}] {:.3f} ", percent, tool->name(), seconds);
print_input(rule->input, '\n');
}
}
if (gen_report) {
report_contents +=
fmt::format("\"{}\": {}{}", str_util::split_string(rule->input.at(0), "/").back(),
seconds, i == deps.size() ? "" : ",");
}
}
lg::print("\nSuccessfully built all {} targets in {:.3f}s\n", deps.size(),
make_timer.getSeconds());
if (gen_report) {
report_contents += fmt::format("}}, 'total': {}}});", make_timer.getSeconds());
str_util::replace(report_output, "// DATA ENDS\n",
fmt::format("{}\n// DATA ENDS\n", report_contents));
file_util::write_text_file(report_path, report_output);
lg::print("Saved report to: {}\n", report_path.string());
}
return true;
}

View File

@ -57,7 +57,7 @@ class MakeSystem {
std::vector<std::string> get_dependencies(const std::string& target) const;
std::vector<std::string> filter_dependencies(const std::vector<std::string>& all_deps);
bool make(const std::string& target, bool force, bool verbose);
bool make(const std::string& target, bool force, bool verbose, bool gen_report);
void add_tool(std::shared_ptr<Tool> tool);
void set_constant(const std::string& name, const std::string& value);