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 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: that much of its 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
+ 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
- notes.push(`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}`);
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: that much of its 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
+ 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
- notes.push(`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}`);
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.7",
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",