gdharness 1.2.7 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +13 -3
- package/build/index.js +13 -3
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -42623,7 +42623,8 @@ function profiledFunctions(totals, limit, sourceOf = () => null) {
|
|
|
42623
42623
|
counted: rows.length,
|
|
42624
42624
|
superCallers: rows.filter((row) => row.selfIncludesSuper === true).length,
|
|
42625
42625
|
perCallUs,
|
|
42626
|
-
overheadDominated: rows.filter((row) => row.overheadMs !== undefined).length
|
|
42626
|
+
overheadDominated: rows.filter((row) => row.overheadMs !== undefined).length,
|
|
42627
|
+
overheadNamed: rows.filter((row) => row.overheadMs !== undefined).map((row) => row.function)
|
|
42627
42628
|
};
|
|
42628
42629
|
}
|
|
42629
42630
|
function isCalibration(signature) {
|
|
@@ -43542,7 +43543,7 @@ function profileAnswer(reading, limit) {
|
|
|
43542
43543
|
notes.push(`${table.superCallers === 1 ? "One function calls" : `${table.superCallers} functions call`} through super, marked selfIncludesSuper: the engine takes every other call out of the caller's self time, and not a super call, so ${table.superCallers === 1 ? "its" : "their"} selfMs holds the overridden function's time, which that function's own row counts again. Self time therefore cannot be added along an override chain, and scriptMs counts the time under a super call once more for each level above it.`);
|
|
43543
43544
|
}
|
|
43544
43545
|
if (table.overheadDominated > 0 && table.perCallUs !== null) {
|
|
43545
|
-
notes.push(`The profiler costs about ${table.perCallUs}µs a call in this run, measured on an empty function the runtime addon calls as it goes on, and that time lands in the self time of the function called. ${table.overheadDominated === 1 ? "One function has" : `${table.overheadDominated} functions have`} at least half ${table.overheadDominated === 1 ? "its" : "their"} selfMs in it, under overheadMs:
|
|
43546
|
+
notes.push(`The profiler costs about ${table.perCallUs}µs a call in this run, measured on an empty function the runtime addon calls as it goes on, and that time lands in the self time of the function called. ${table.overheadDominated === 1 ? "One function has" : `${table.overheadDominated} functions have`} at least half ${table.overheadDominated === 1 ? "its" : "their"} selfMs in it, under overheadMs: ${namedFew(table.overheadNamed)}. That much of ${table.overheadDominated === 1 ? "its" : "their"} time is the profiler's and goes once the profiler is off, whether the function is inlined or not. What inlining saves is the call itself, which costs something without the profiler too, not the work inside it.`);
|
|
43546
43547
|
}
|
|
43547
43548
|
notes.push(...cappedNotes(totals));
|
|
43548
43549
|
if (totals.unreadable > 0) {
|
|
@@ -43564,12 +43565,21 @@ function profileAnswer(reading, limit) {
|
|
|
43564
43565
|
note: notes.length > 0 ? notes.join(" ") : undefined
|
|
43565
43566
|
};
|
|
43566
43567
|
}
|
|
43568
|
+
function namedFew(names) {
|
|
43569
|
+
const shown = names.slice(0, 5);
|
|
43570
|
+
const more = names.length - shown.length;
|
|
43571
|
+
if (more > 0) {
|
|
43572
|
+
return `${shown.join(", ")} and ${more} more`;
|
|
43573
|
+
}
|
|
43574
|
+
return shown.length > 1 ? `${shown.slice(0, -1).join(", ")} and ${shown.at(-1) ?? ""}` : shown[0] ?? "";
|
|
43575
|
+
}
|
|
43567
43576
|
function cappedNotes(totals) {
|
|
43568
43577
|
const notes = [];
|
|
43569
43578
|
const most = totals.frameFunctions;
|
|
43570
43579
|
const why = `${most} is kept below the game's debugger queue (network/limits/debugger/max_queued_messages), which drops the message naming a function when one frame names more than it holds, and a function whose name is dropped is never named afterwards.`;
|
|
43571
43580
|
if (most !== undefined && totals.complete && totals.totalCapped === true) {
|
|
43572
|
-
|
|
43581
|
+
const leastKept = Math.min(...Object.values(totals.functions).map((one) => one.totalSeconds));
|
|
43582
|
+
notes.push(leastKept > 0 ? `The engine's totals carried the most functions the profiler asks for, ${most}, so the functions with the least time are not in them: ${why}` : `The engine's totals carried the most functions the profiler asks for, ${most}, and the last of them took no measurable time, so neither did any left out: the time is all here, and only a function too quick for the clock can be missing, with its calls. The engine lists every function it has compiled, run or not, and sends them busiest first. ${why}`);
|
|
43573
43583
|
} else if (most !== undefined && !totals.complete && (totals.cappedFrames ?? 0) > 0) {
|
|
43574
43584
|
const capped = totals.cappedFrames ?? 0;
|
|
43575
43585
|
notes.push(`${capped === totals.frames ? capped === 1 ? "The one frame" : `All ${capped} frames` : `${capped} of the ${totals.frames} frames`} carried the most functions the profiler asks for in one, ${most}, so the functions with the least time in ${capped === 1 ? "it" : "them"} are not counted there: ${why}`);
|
package/build/index.js
CHANGED
|
@@ -33415,7 +33415,8 @@ function profiledFunctions(totals, limit, sourceOf = () => null) {
|
|
|
33415
33415
|
counted: rows.length,
|
|
33416
33416
|
superCallers: rows.filter((row) => row.selfIncludesSuper === true).length,
|
|
33417
33417
|
perCallUs,
|
|
33418
|
-
overheadDominated: rows.filter((row) => row.overheadMs !== undefined).length
|
|
33418
|
+
overheadDominated: rows.filter((row) => row.overheadMs !== undefined).length,
|
|
33419
|
+
overheadNamed: rows.filter((row) => row.overheadMs !== undefined).map((row) => row.function)
|
|
33419
33420
|
};
|
|
33420
33421
|
}
|
|
33421
33422
|
var RUNTIME_SCRIPT = "gdharness_runtime/runtime_autoload.gd";
|
|
@@ -36037,7 +36038,7 @@ function profileAnswer(reading, limit) {
|
|
|
36037
36038
|
notes.push(`${table.superCallers === 1 ? "One function calls" : `${table.superCallers} functions call`} through super, marked selfIncludesSuper: the engine takes every other call out of the caller's self time, and not a super call, so ${table.superCallers === 1 ? "its" : "their"} selfMs holds the overridden function's time, which that function's own row counts again. Self time therefore cannot be added along an override chain, and scriptMs counts the time under a super call once more for each level above it.`);
|
|
36038
36039
|
}
|
|
36039
36040
|
if (table.overheadDominated > 0 && table.perCallUs !== null) {
|
|
36040
|
-
notes.push(`The profiler costs about ${table.perCallUs}µs a call in this run, measured on an empty function the runtime addon calls as it goes on, and that time lands in the self time of the function called. ${table.overheadDominated === 1 ? "One function has" : `${table.overheadDominated} functions have`} at least half ${table.overheadDominated === 1 ? "its" : "their"} selfMs in it, under overheadMs:
|
|
36041
|
+
notes.push(`The profiler costs about ${table.perCallUs}µs a call in this run, measured on an empty function the runtime addon calls as it goes on, and that time lands in the self time of the function called. ${table.overheadDominated === 1 ? "One function has" : `${table.overheadDominated} functions have`} at least half ${table.overheadDominated === 1 ? "its" : "their"} selfMs in it, under overheadMs: ${namedFew(table.overheadNamed)}. That much of ${table.overheadDominated === 1 ? "its" : "their"} time is the profiler's and goes once the profiler is off, whether the function is inlined or not. What inlining saves is the call itself, which costs something without the profiler too, not the work inside it.`);
|
|
36041
36042
|
}
|
|
36042
36043
|
notes.push(...cappedNotes(totals));
|
|
36043
36044
|
if (totals.unreadable > 0) {
|
|
@@ -36059,12 +36060,21 @@ function profileAnswer(reading, limit) {
|
|
|
36059
36060
|
note: notes.length > 0 ? notes.join(" ") : undefined
|
|
36060
36061
|
};
|
|
36061
36062
|
}
|
|
36063
|
+
function namedFew(names) {
|
|
36064
|
+
const shown = names.slice(0, 5);
|
|
36065
|
+
const more = names.length - shown.length;
|
|
36066
|
+
if (more > 0) {
|
|
36067
|
+
return `${shown.join(", ")} and ${more} more`;
|
|
36068
|
+
}
|
|
36069
|
+
return shown.length > 1 ? `${shown.slice(0, -1).join(", ")} and ${shown.at(-1) ?? ""}` : shown[0] ?? "";
|
|
36070
|
+
}
|
|
36062
36071
|
function cappedNotes(totals) {
|
|
36063
36072
|
const notes = [];
|
|
36064
36073
|
const most = totals.frameFunctions;
|
|
36065
36074
|
const why = `${most} is kept below the game's debugger queue (network/limits/debugger/max_queued_messages), which drops the message naming a function when one frame names more than it holds, and a function whose name is dropped is never named afterwards.`;
|
|
36066
36075
|
if (most !== undefined && totals.complete && totals.totalCapped === true) {
|
|
36067
|
-
|
|
36076
|
+
const leastKept = Math.min(...Object.values(totals.functions).map((one) => one.totalSeconds));
|
|
36077
|
+
notes.push(leastKept > 0 ? `The engine's totals carried the most functions the profiler asks for, ${most}, so the functions with the least time are not in them: ${why}` : `The engine's totals carried the most functions the profiler asks for, ${most}, and the last of them took no measurable time, so neither did any left out: the time is all here, and only a function too quick for the clock can be missing, with its calls. The engine lists every function it has compiled, run or not, and sends them busiest first. ${why}`);
|
|
36068
36078
|
} else if (most !== undefined && !totals.complete && (totals.cappedFrames ?? 0) > 0) {
|
|
36069
36079
|
const capped = totals.cappedFrames ?? 0;
|
|
36070
36080
|
notes.push(`${capped === totals.frames ? capped === 1 ? "The one frame" : `All ${capped} frames` : `${capped} of the ${totals.frames} frames`} carried the most functions the profiler asks for in one, ${most}, so the functions with the least time in ${capped === 1 ? "it" : "them"} are not counted there: ${why}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"mcpName": "io.github.Aureliolo/gdharness",
|
|
5
5
|
"description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
|
|
6
6
|
"type": "module",
|