gdharness 1.2.6 → 1.2.7
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
|
@@ -42721,7 +42721,7 @@ function callersOf(totals, name, scripts) {
|
|
|
42721
42721
|
sites.sort((a, b) => (b.withinTotalMs ?? -1) - (a.withinTotalMs ?? -1) || a.script.localeCompare(b.script) || a.line - b.line);
|
|
42722
42722
|
return { target, sites: sites.slice(0, CALL_SITES), omitted: Math.max(0, sites.length - CALL_SITES) };
|
|
42723
42723
|
}
|
|
42724
|
-
var QUEUE_SETTING = "limits/debugger/max_queued_messages", QUEUE_DEFAULT = 2048, QUEUE_HEADROOM = 512, UNNAMED_PREFIX = "#", ms = (seconds) => Math.round(seconds * 1e6) / 1000, RUNTIME_SCRIPT = "gdharness_runtime/runtime_autoload.gd", PROFILER_PROBE = "_profiler_probe", PROFILER_CALIBRATOR = "_calibrate_the_profiler", CALL_SITES = 40;
|
|
42724
|
+
var QUEUE_SETTING = "limits/debugger/max_queued_messages", QUEUE_DEFAULT = 2048, QUEUE_HEADROOM = 512, UNNAMED_PREFIX = "#", PROFILE_FROM_START = "GDHARNESS_PROFILE_FROM_START", ms = (seconds) => Math.round(seconds * 1e6) / 1000, RUNTIME_SCRIPT = "gdharness_runtime/runtime_autoload.gd", PROFILER_PROBE = "_profiler_probe", PROFILER_CALIBRATOR = "_calibrate_the_profiler", CALL_SITES = 40;
|
|
42725
42725
|
var init_script_profile = __esm(() => {
|
|
42726
42726
|
init_gdscript_source();
|
|
42727
42727
|
init_godot_variant();
|
|
@@ -46929,10 +46929,11 @@ class GodotServer {
|
|
|
46929
46929
|
const startedAt = Date.now();
|
|
46930
46930
|
const transcript = openTranscript(startedAt);
|
|
46931
46931
|
closeSync2(transcript.fd);
|
|
46932
|
+
const gameEnv = profiled ? { ...env ?? process.env, [PROFILE_FROM_START]: "1" } : env;
|
|
46932
46933
|
const launched = await launchOutsideTheTree({
|
|
46933
46934
|
command: godotPath,
|
|
46934
46935
|
args: cmdArgs,
|
|
46935
|
-
...
|
|
46936
|
+
...gameEnv === undefined ? {} : { env: gameEnv },
|
|
46936
46937
|
run: {
|
|
46937
46938
|
transcript: transcript.path,
|
|
46938
46939
|
startedAt,
|
|
@@ -22,6 +22,9 @@ const DEBUGGER_CLASS: String = "ScriptEditorDebugger"
|
|
|
22
22
|
const PROFILE_CAPTURE: String = "gdharness"
|
|
23
23
|
const PROFILE_SENT: String = "gdharness:profile_sent"
|
|
24
24
|
const PROFILE_RECEIVED: String = "gdharness:profile_received"
|
|
25
|
+
## Set in the environment a played game inherits, when the play is to be profiled from its start.
|
|
26
|
+
## Kept in step with the runtime addon's runtime_autoload.gd.
|
|
27
|
+
const PROFILE_FROM_START: String = "GDHARNESS_PROFILE_FROM_START"
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
## The editor's debugger sessions, numbered as the editor numbers its debugger tabs.
|
|
@@ -106,6 +109,10 @@ func profile_start(args: Dictionary) -> Dictionary:
|
|
|
106
109
|
_frame_functions = asked if asked > 0 else FRAME_FUNCTIONS
|
|
107
110
|
if Read.as_bool(args.get("arm", false)):
|
|
108
111
|
_armed = true
|
|
112
|
+
# The game the editor starts next inherits the editor's environment, and this tells its
|
|
113
|
+
# runtime addon to hold its start until the profiler is on, which the session's start
|
|
114
|
+
# switches on with a message the game reads only on a later poll.
|
|
115
|
+
OS.set_environment(PROFILE_FROM_START, "1")
|
|
109
116
|
return {"ok": true, "started": false, "armed": true, "session": -1}
|
|
110
117
|
var active: int = _active_session()
|
|
111
118
|
if active < 0:
|
|
@@ -137,6 +144,7 @@ func profile_read(_args: Dictionary) -> Dictionary:
|
|
|
137
144
|
|
|
138
145
|
func _reset() -> void:
|
|
139
146
|
_armed = false
|
|
147
|
+
OS.unset_environment(PROFILE_FROM_START)
|
|
140
148
|
_session = -1
|
|
141
149
|
_frames = 0
|
|
142
150
|
_complete = false
|
|
@@ -172,6 +180,8 @@ func _on_session_started(session_id: int) -> void:
|
|
|
172
180
|
_reset()
|
|
173
181
|
return
|
|
174
182
|
_armed = false
|
|
183
|
+
# The game has started with it by now, and a later play must not.
|
|
184
|
+
OS.unset_environment(PROFILE_FROM_START)
|
|
175
185
|
if _hook() > 0:
|
|
176
186
|
_switch_on(session_id)
|
|
177
187
|
|
|
@@ -47,6 +47,13 @@ const PROFILER_PROBE_CALLS: int = 10000
|
|
|
47
47
|
## on every 2048th call and only counts the others.
|
|
48
48
|
const POLLS_PER_READ: int = 2048
|
|
49
49
|
|
|
50
|
+
## Set in a game's environment by whatever starts it to be profiled from its start: the server for
|
|
51
|
+
## a run it spawns, the editor for a play. Kept in step with `PROFILE_FROM_START` in the server.
|
|
52
|
+
const PROFILE_FROM_START: String = "GDHARNESS_PROFILE_FROM_START"
|
|
53
|
+
|
|
54
|
+
## How long such a game waits for its debugger to switch the profiler on before carrying on.
|
|
55
|
+
const PROFILER_WAIT_MS: int = 5000
|
|
56
|
+
|
|
50
57
|
## How the engine is told to run a script instead of the game: `godot -s thing.gd`.
|
|
51
58
|
const SCRIPT_FLAGS: PackedStringArray = ["-s", "--script"]
|
|
52
59
|
|
|
@@ -134,6 +141,37 @@ func _init() -> void:
|
|
|
134
141
|
"wait_signal": _waits.wait_signal,
|
|
135
142
|
"wait_until": _waits.wait_until,
|
|
136
143
|
}
|
|
144
|
+
_wait_for_the_profiler()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
## Holds the game's start until the profiler is on, when whatever started the game asked for a
|
|
148
|
+
## profile from its start. The debugger switches the profiler on with a message the game reads only
|
|
149
|
+
## on a poll, which comes every [constant POLLS_PER_READ] lines of script, so the main scene's _ready
|
|
150
|
+
## could run first: a game played on a macOS runner counted 25 calls of a function called 26 times,
|
|
151
|
+
## the first of them from _ready. Run at the autoload's construction, before the main scene loads.
|
|
152
|
+
func _wait_for_the_profiler() -> void:
|
|
153
|
+
if OS.get_environment(PROFILE_FROM_START).is_empty():
|
|
154
|
+
return
|
|
155
|
+
# Read once: a process this game starts inherits its environment and must not wait as well.
|
|
156
|
+
OS.unset_environment(PROFILE_FROM_START)
|
|
157
|
+
if not EngineDebugger.is_active():
|
|
158
|
+
return
|
|
159
|
+
var deadline: int = Time.get_ticks_msec() + PROFILER_WAIT_MS
|
|
160
|
+
while not EngineDebugger.is_profiling("servers"):
|
|
161
|
+
if Time.get_ticks_msec() >= deadline:
|
|
162
|
+
push_warning(
|
|
163
|
+
(
|
|
164
|
+
(
|
|
165
|
+
"gdharness: this game was started to be profiled from its start, and the profiler"
|
|
166
|
+
+ " was not on %d ms later, so what ran before it is not counted"
|
|
167
|
+
)
|
|
168
|
+
% PROFILER_WAIT_MS
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
return
|
|
172
|
+
for _poll: int in POLLS_PER_READ:
|
|
173
|
+
EngineDebugger.line_poll()
|
|
174
|
+
OS.delay_msec(1)
|
|
137
175
|
|
|
138
176
|
|
|
139
177
|
func _ready() -> void:
|
package/build/index.js
CHANGED
|
@@ -33393,6 +33393,7 @@ function queuedMessagesOf(projectGodot) {
|
|
|
33393
33393
|
return typeof set === "number" && Number.isInteger(set) && set > 0 ? set : QUEUE_DEFAULT;
|
|
33394
33394
|
}
|
|
33395
33395
|
var UNNAMED_PREFIX = "#";
|
|
33396
|
+
var PROFILE_FROM_START = "GDHARNESS_PROFILE_FROM_START";
|
|
33396
33397
|
function signatureParts(signature) {
|
|
33397
33398
|
const parts = signature.split("::");
|
|
33398
33399
|
if (parts.length < 3) {
|
|
@@ -39426,10 +39427,11 @@ class GodotServer {
|
|
|
39426
39427
|
const startedAt = Date.now();
|
|
39427
39428
|
const transcript = openTranscript(startedAt);
|
|
39428
39429
|
closeSync2(transcript.fd);
|
|
39430
|
+
const gameEnv = profiled ? { ...env ?? process.env, [PROFILE_FROM_START]: "1" } : env;
|
|
39429
39431
|
const launched = await launchOutsideTheTree({
|
|
39430
39432
|
command: godotPath,
|
|
39431
39433
|
args: cmdArgs,
|
|
39432
|
-
...
|
|
39434
|
+
...gameEnv === undefined ? {} : { env: gameEnv },
|
|
39433
39435
|
run: {
|
|
39434
39436
|
transcript: transcript.path,
|
|
39435
39437
|
startedAt,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
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",
|