gdharness 1.1.57 → 1.1.59
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 +244 -37
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +4 -1
- package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +31 -13
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +55 -1
- package/build/index.js +243 -33
- package/build/keeper.js +7078 -144
- package/package.json +1 -1
|
@@ -12,9 +12,10 @@ extends Node
|
|
|
12
12
|
|
|
13
13
|
const Read = preload("../reading.gd")
|
|
14
14
|
|
|
15
|
-
## The
|
|
16
|
-
##
|
|
17
|
-
|
|
15
|
+
## The most functions a frame may carry when the server does not say. The engine names a function
|
|
16
|
+
## once, as it first appears, and the game's debugger queue drops those messages past its size, so
|
|
17
|
+
## the server keeps this below the queue the project sets; this is that for the engine's default.
|
|
18
|
+
const FRAME_FUNCTIONS: int = 1536
|
|
18
19
|
const DEBUGGER_CLASS: String = "ScriptEditorDebugger"
|
|
19
20
|
|
|
20
21
|
|
|
@@ -44,6 +45,10 @@ var _started_msec: int = 0
|
|
|
44
45
|
var _last_frame_msec: int = -1
|
|
45
46
|
var _frames: int = 0
|
|
46
47
|
var _complete: bool = false
|
|
48
|
+
var _frame_functions: int = FRAME_FUNCTIONS
|
|
49
|
+
## Frames that carried as many functions as were asked for, and whether the totals did.
|
|
50
|
+
var _capped_frames: int = 0
|
|
51
|
+
var _total_capped: bool = false
|
|
47
52
|
var _names: Dictionary[int, String] = {}
|
|
48
53
|
## Per signature: calls, self seconds, total seconds.
|
|
49
54
|
var _totals: Dictionary[String, PackedFloat64Array] = {}
|
|
@@ -81,6 +86,8 @@ func profile_start(args: Dictionary) -> Dictionary:
|
|
|
81
86
|
),
|
|
82
87
|
}
|
|
83
88
|
_reset()
|
|
89
|
+
var asked: int = Read.as_int(args.get("frameFunctions", FRAME_FUNCTIONS))
|
|
90
|
+
_frame_functions = asked if asked > 0 else FRAME_FUNCTIONS
|
|
84
91
|
if Read.as_bool(args.get("arm", false)):
|
|
85
92
|
_armed = true
|
|
86
93
|
return {"ok": true, "started": false, "armed": true, "session": -1}
|
|
@@ -104,6 +111,9 @@ func profile_read(_args: Dictionary) -> Dictionary:
|
|
|
104
111
|
"playing": EditorInterface.is_playing_scene(),
|
|
105
112
|
"frames": _frames,
|
|
106
113
|
"complete": _complete,
|
|
114
|
+
"frameFunctions": _frame_functions,
|
|
115
|
+
"cappedFrames": _capped_frames,
|
|
116
|
+
"totalCapped": _total_capped,
|
|
107
117
|
"coveredMs": _last_frame_msec - _started_msec if _last_frame_msec >= 0 else 0,
|
|
108
118
|
"functions": functions,
|
|
109
119
|
}
|
|
@@ -114,6 +124,8 @@ func _reset() -> void:
|
|
|
114
124
|
_session = -1
|
|
115
125
|
_frames = 0
|
|
116
126
|
_complete = false
|
|
127
|
+
_capped_frames = 0
|
|
128
|
+
_total_capped = false
|
|
117
129
|
_last_frame_msec = -1
|
|
118
130
|
_names.clear()
|
|
119
131
|
_totals.clear()
|
|
@@ -133,7 +145,7 @@ func _switch_on(session_id: int) -> void:
|
|
|
133
145
|
_session = session_id
|
|
134
146
|
_started_msec = Time.get_ticks_msec()
|
|
135
147
|
var session: EditorDebuggerSession = _sessions.get_session(session_id)
|
|
136
|
-
session.toggle_profiler("servers", true, [
|
|
148
|
+
session.toggle_profiler("servers", true, [_frame_functions, false])
|
|
137
149
|
|
|
138
150
|
|
|
139
151
|
## A play that was asked to be profiled is switched on as it starts. Any other play drops what is
|
|
@@ -170,37 +182,42 @@ func _on_debug_data(message: String, data: Array, session_id: int) -> void:
|
|
|
170
182
|
if message == "servers:function_signature" and data.size() >= 2:
|
|
171
183
|
_names[Read.as_int(data[1])] = str(data[0])
|
|
172
184
|
elif message == "servers:profile_frame":
|
|
173
|
-
|
|
185
|
+
var carried: int = _add(data, _totals)
|
|
186
|
+
if carried >= 0:
|
|
174
187
|
_frames += 1
|
|
188
|
+
_capped_frames += 1 if carried >= _frame_functions else 0
|
|
175
189
|
_last_frame_msec = Time.get_ticks_msec()
|
|
176
190
|
elif message == "servers:profile_total":
|
|
177
191
|
# The engine's own count since the profiler started, so it replaces the frames' sum.
|
|
178
192
|
var whole: Dictionary[String, PackedFloat64Array] = {}
|
|
179
|
-
|
|
193
|
+
var carried: int = _add(data, whole)
|
|
194
|
+
if carried >= 0:
|
|
180
195
|
_totals = whole
|
|
181
196
|
_complete = true
|
|
197
|
+
_total_capped = carried >= _frame_functions
|
|
182
198
|
_last_frame_msec = Time.get_ticks_msec()
|
|
183
199
|
|
|
184
200
|
|
|
185
201
|
## Adds one frame's functions into [param into], reading past the servers' section to reach them:
|
|
186
202
|
## six frame times, the server count, each server's name and field count and fields, then five
|
|
187
|
-
## numbers per function.
|
|
188
|
-
func _add(data: Array, into: Dictionary[String, PackedFloat64Array]) ->
|
|
203
|
+
## numbers per function. Answers how many functions it carried, or -1 for a frame it cannot read.
|
|
204
|
+
func _add(data: Array, into: Dictionary[String, PackedFloat64Array]) -> int:
|
|
189
205
|
var at: int = 6
|
|
190
206
|
if data.size() <= at:
|
|
191
|
-
return
|
|
207
|
+
return -1
|
|
192
208
|
var servers: int = Read.as_int(data[at])
|
|
193
209
|
at += 1
|
|
194
210
|
for _server: int in servers:
|
|
195
211
|
if data.size() <= at + 1:
|
|
196
|
-
return
|
|
212
|
+
return -1
|
|
197
213
|
at += 2 + Read.as_int(data[at + 1])
|
|
198
214
|
if data.size() <= at:
|
|
199
|
-
return
|
|
215
|
+
return -1
|
|
200
216
|
var values: int = Read.as_int(data[at])
|
|
201
217
|
at += 1
|
|
202
218
|
if values % 5 != 0 or data.size() < at + values:
|
|
203
|
-
return
|
|
219
|
+
return -1
|
|
220
|
+
var carried: int = 0
|
|
204
221
|
for index: int in range(at, at + values, 5):
|
|
205
222
|
var id: int = Read.as_int(data[index])
|
|
206
223
|
var signature: String = _names[id] if _names.has(id) else "#%d" % id
|
|
@@ -211,4 +228,5 @@ func _add(data: Array, into: Dictionary[String, PackedFloat64Array]) -> bool:
|
|
|
211
228
|
sum[1] += Read.as_float(data[index + 2])
|
|
212
229
|
sum[2] += Read.as_float(data[index + 3])
|
|
213
230
|
into[signature] = sum
|
|
214
|
-
|
|
231
|
+
carried += 1
|
|
232
|
+
return carried
|
|
@@ -172,6 +172,7 @@ func _report_errors() -> void:
|
|
|
172
172
|
func _process(_delta: float) -> void:
|
|
173
173
|
if not _enabled or _server == null:
|
|
174
174
|
return
|
|
175
|
+
_queries.note_frame(Time.get_ticks_usec())
|
|
175
176
|
|
|
176
177
|
if _server.is_connection_available():
|
|
177
178
|
var client: StreamPeerTCP = _server.take_connection()
|
|
@@ -28,8 +28,14 @@ const READ_LIMIT: int = 500
|
|
|
28
28
|
## and said nothing, and a caller told to raise a number that stays put concludes the screen moved.
|
|
29
29
|
const LIMIT_CEILING: int = 5000
|
|
30
30
|
|
|
31
|
+
## How many frames the frame time is the mean of: two seconds at sixty frames a second.
|
|
32
|
+
const FRAMES_TIMED: int = 120
|
|
33
|
+
|
|
31
34
|
var _host: Node
|
|
32
35
|
var _values: Values
|
|
36
|
+
## How long each of the last frames took, oldest first, in microseconds, as the game timed them.
|
|
37
|
+
var _frame_usec: PackedInt64Array = PackedInt64Array()
|
|
38
|
+
var _last_frame_usec: int = 0
|
|
33
39
|
|
|
34
40
|
|
|
35
41
|
## The host is the autoload, which is how the tree is reached: it is not in one when the
|
|
@@ -649,12 +655,60 @@ func get_property(params: Dictionary) -> Dictionary:
|
|
|
649
655
|
}
|
|
650
656
|
|
|
651
657
|
|
|
658
|
+
## Called by the autoload once a frame, whatever else it does that frame, with the time it was called.
|
|
659
|
+
##
|
|
660
|
+
## The engine's own monitors do not follow the frame: TIME_PROCESS and the frame rate are set once a
|
|
661
|
+
## second, the first to the slowest process step of that second, so a game whose frames took 16.7ms
|
|
662
|
+
## read 45ms for a second at a time, and a change to the game showed only on the next second's
|
|
663
|
+
## worst frame. The time between two of these calls is the frame as it passed, physics and the wait
|
|
664
|
+
## for the display included.
|
|
665
|
+
func note_frame(now_usec: int) -> void:
|
|
666
|
+
if _last_frame_usec > 0:
|
|
667
|
+
var _grew: bool = _frame_usec.push_back(now_usec - _last_frame_usec)
|
|
668
|
+
if _frame_usec.size() > FRAMES_TIMED:
|
|
669
|
+
_frame_usec.remove_at(0)
|
|
670
|
+
_last_frame_usec = now_usec
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
## Whether the frame waits for the display, which sets its floor: a game with vsync on cannot
|
|
674
|
+
## finish a frame sooner than the display refreshes, however little it does.
|
|
675
|
+
static func _vsync() -> String:
|
|
676
|
+
if DisplayServer.get_name() == "headless":
|
|
677
|
+
return "none, headless"
|
|
678
|
+
match DisplayServer.window_get_vsync_mode():
|
|
679
|
+
DisplayServer.VSYNC_DISABLED:
|
|
680
|
+
return "disabled"
|
|
681
|
+
DisplayServer.VSYNC_ADAPTIVE:
|
|
682
|
+
return "adaptive"
|
|
683
|
+
DisplayServer.VSYNC_MAILBOX:
|
|
684
|
+
return "mailbox"
|
|
685
|
+
_:
|
|
686
|
+
return "enabled"
|
|
687
|
+
|
|
688
|
+
|
|
652
689
|
func get_metrics(params: Dictionary) -> Dictionary:
|
|
653
690
|
var metrics: Array = params.get("metrics", [])
|
|
691
|
+
var timed: int = _frame_usec.size()
|
|
692
|
+
var total_usec: int = 0
|
|
693
|
+
var slowest_usec: int = 0
|
|
694
|
+
for one: int in _frame_usec:
|
|
695
|
+
total_usec += one
|
|
696
|
+
slowest_usec = maxi(slowest_usec, one)
|
|
697
|
+
# Null rather than zero before a frame has been timed: no frame took no time.
|
|
698
|
+
var frame_time: Variant = null
|
|
699
|
+
var frame_time_max: Variant = null
|
|
700
|
+
if timed > 0:
|
|
701
|
+
frame_time = float(total_usec) / timed / 1000000.0
|
|
702
|
+
frame_time_max = slowest_usec / 1000000.0
|
|
654
703
|
var all: Dictionary = {
|
|
655
704
|
"fps": Engine.get_frames_per_second(),
|
|
656
|
-
"frame_time":
|
|
705
|
+
"frame_time": frame_time,
|
|
706
|
+
"frame_time_max": frame_time_max,
|
|
707
|
+
"frames_timed": timed,
|
|
708
|
+
"process_time_max": Performance.get_monitor(Performance.TIME_PROCESS),
|
|
657
709
|
"physics_time": Performance.get_monitor(Performance.TIME_PHYSICS_PROCESS),
|
|
710
|
+
"vsync": _vsync(),
|
|
711
|
+
"max_fps": Engine.max_fps,
|
|
658
712
|
"memory_static": Performance.get_monitor(Performance.MEMORY_STATIC),
|
|
659
713
|
"memory_static_max": Performance.get_monitor(Performance.MEMORY_STATIC_MAX),
|
|
660
714
|
"object_count": Performance.get_monitor(Performance.OBJECT_COUNT),
|