@holoscript/core 1.0.0-alpha.2 → 2.0.1
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/package.json +2 -2
- package/src/HoloScript2DParser.js +227 -0
- package/src/HoloScript2DParser.ts +5 -0
- package/src/HoloScriptCodeParser.js +1102 -0
- package/src/HoloScriptCodeParser.ts +145 -20
- package/src/HoloScriptDebugger.js +458 -0
- package/src/HoloScriptParser.js +338 -0
- package/src/HoloScriptPlusParser.js +371 -0
- package/src/HoloScriptPlusParser.ts +543 -0
- package/src/HoloScriptRuntime.js +1399 -0
- package/src/HoloScriptRuntime.test.js +351 -0
- package/src/HoloScriptRuntime.ts +17 -3
- package/src/HoloScriptTypeChecker.js +356 -0
- package/src/__tests__/GraphicsServices.test.js +357 -0
- package/src/__tests__/GraphicsServices.test.ts +427 -0
- package/src/__tests__/HoloScriptPlusParser.test.js +317 -0
- package/src/__tests__/HoloScriptPlusParser.test.ts +392 -0
- package/src/__tests__/integration.test.js +336 -0
- package/src/__tests__/performance.bench.js +218 -0
- package/src/__tests__/type-checker.test.js +60 -0
- package/src/__tests__/type-checker.test.ts +73 -0
- package/src/index.js +217 -0
- package/src/index.ts +158 -18
- package/src/interop/Interoperability.js +413 -0
- package/src/interop/Interoperability.ts +494 -0
- package/src/logger.js +42 -0
- package/src/parser/EnhancedParser.js +205 -0
- package/src/parser/EnhancedParser.ts +251 -0
- package/src/parser/HoloScriptPlusParser.js +928 -0
- package/src/parser/HoloScriptPlusParser.ts +1089 -0
- package/src/runtime/HoloScriptPlusRuntime.js +674 -0
- package/src/runtime/HoloScriptPlusRuntime.ts +861 -0
- package/src/runtime/PerformanceTelemetry.js +323 -0
- package/src/runtime/PerformanceTelemetry.ts +467 -0
- package/src/runtime/RuntimeOptimization.js +361 -0
- package/src/runtime/RuntimeOptimization.ts +416 -0
- package/src/services/HololandGraphicsPipelineService.js +506 -0
- package/src/services/HololandGraphicsPipelineService.ts +662 -0
- package/src/services/PlatformPerformanceOptimizer.js +356 -0
- package/src/services/PlatformPerformanceOptimizer.ts +503 -0
- package/src/state/ReactiveState.js +427 -0
- package/src/state/ReactiveState.ts +572 -0
- package/src/tools/DeveloperExperience.js +376 -0
- package/src/tools/DeveloperExperience.ts +438 -0
- package/src/traits/AIDriverTrait.js +322 -0
- package/src/traits/AIDriverTrait.test.js +329 -0
- package/src/traits/AIDriverTrait.test.ts +357 -0
- package/src/traits/AIDriverTrait.ts +474 -0
- package/src/traits/LightingTrait.js +313 -0
- package/src/traits/LightingTrait.test.js +410 -0
- package/src/traits/LightingTrait.test.ts +462 -0
- package/src/traits/LightingTrait.ts +505 -0
- package/src/traits/MaterialTrait.js +194 -0
- package/src/traits/MaterialTrait.test.js +286 -0
- package/src/traits/MaterialTrait.test.ts +329 -0
- package/src/traits/MaterialTrait.ts +324 -0
- package/src/traits/RenderingTrait.js +356 -0
- package/src/traits/RenderingTrait.test.js +363 -0
- package/src/traits/RenderingTrait.test.ts +427 -0
- package/src/traits/RenderingTrait.ts +555 -0
- package/src/traits/VRTraitSystem.js +740 -0
- package/src/traits/VRTraitSystem.ts +1040 -0
- package/src/traits/VoiceInputTrait.js +284 -0
- package/src/traits/VoiceInputTrait.test.js +226 -0
- package/src/traits/VoiceInputTrait.test.ts +252 -0
- package/src/traits/VoiceInputTrait.ts +401 -0
- package/src/types/AdvancedTypeSystem.js +226 -0
- package/src/types/AdvancedTypeSystem.ts +494 -0
- package/src/types/HoloScriptPlus.d.ts +853 -0
- package/src/types.js +6 -0
- package/src/types.ts +96 -1
- package/tsconfig.json +1 -1
- package/tsup.config.d.ts +2 -0
- package/tsup.config.js +18 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/core Performance Telemetry
|
|
3
|
+
*
|
|
4
|
+
* Real-time performance monitoring, profiling, and metrics collection
|
|
5
|
+
* Exports metrics to analytics platforms and provides performance budgets
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* PerformanceTelemetry - Monitor and analyze runtime performance
|
|
9
|
+
*/
|
|
10
|
+
export class PerformanceTelemetry {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.metrics = [];
|
|
13
|
+
this.budgets = new Map();
|
|
14
|
+
this.frameTimings = [];
|
|
15
|
+
this.memorySnapshots = [];
|
|
16
|
+
this.exporters = [];
|
|
17
|
+
this.frameCounter = 0;
|
|
18
|
+
this.lastFrameTime = Date.now();
|
|
19
|
+
this.frameTimes = [];
|
|
20
|
+
this.maxFrameHistory = 300; // ~5s at 60fps
|
|
21
|
+
this.monitoringEnabled = false;
|
|
22
|
+
this.exportInterval = null;
|
|
23
|
+
this.exportIntervalMs = 10000; // Export every 10s
|
|
24
|
+
this.initializeDefaultBudgets();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Initialize default performance budgets
|
|
28
|
+
*/
|
|
29
|
+
initializeDefaultBudgets() {
|
|
30
|
+
// Frame budget: 16.67ms target (60fps)
|
|
31
|
+
this.setBudget({
|
|
32
|
+
metricName: 'frame_duration',
|
|
33
|
+
maxValue: 16.67,
|
|
34
|
+
severity: 'warning',
|
|
35
|
+
enabled: true,
|
|
36
|
+
});
|
|
37
|
+
// Memory budget: 100MB
|
|
38
|
+
this.setBudget({
|
|
39
|
+
metricName: 'heap_used',
|
|
40
|
+
maxValue: 100 * 1024 * 1024,
|
|
41
|
+
severity: 'warning',
|
|
42
|
+
enabled: true,
|
|
43
|
+
});
|
|
44
|
+
// Render time budget: 10ms
|
|
45
|
+
this.setBudget({
|
|
46
|
+
metricName: 'render_time',
|
|
47
|
+
maxValue: 10,
|
|
48
|
+
severity: 'warning',
|
|
49
|
+
enabled: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Start performance monitoring
|
|
54
|
+
*/
|
|
55
|
+
startMonitoring() {
|
|
56
|
+
if (this.monitoringEnabled)
|
|
57
|
+
return;
|
|
58
|
+
this.monitoringEnabled = true;
|
|
59
|
+
this.lastFrameTime = performance.now();
|
|
60
|
+
// Setup auto-export
|
|
61
|
+
if (this.exporters.length > 0) {
|
|
62
|
+
this.exportInterval = setInterval(() => {
|
|
63
|
+
this.exportMetrics();
|
|
64
|
+
}, this.exportIntervalMs);
|
|
65
|
+
}
|
|
66
|
+
console.log('Performance monitoring started');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Stop performance monitoring
|
|
70
|
+
*/
|
|
71
|
+
stopMonitoring() {
|
|
72
|
+
if (!this.monitoringEnabled)
|
|
73
|
+
return;
|
|
74
|
+
this.monitoringEnabled = false;
|
|
75
|
+
if (this.exportInterval) {
|
|
76
|
+
clearInterval(this.exportInterval);
|
|
77
|
+
this.exportInterval = null;
|
|
78
|
+
}
|
|
79
|
+
console.log('Performance monitoring stopped');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Record frame timing
|
|
83
|
+
*/
|
|
84
|
+
recordFrame(cpuTime, gpuTime, renderTime, logicTime) {
|
|
85
|
+
if (!this.monitoringEnabled)
|
|
86
|
+
return;
|
|
87
|
+
const now = performance.now();
|
|
88
|
+
const frameDuration = now - this.lastFrameTime;
|
|
89
|
+
const fps = Math.round(1000 / frameDuration);
|
|
90
|
+
this.frameTimes.push(frameDuration);
|
|
91
|
+
if (this.frameTimes.length > this.maxFrameHistory) {
|
|
92
|
+
this.frameTimes.shift();
|
|
93
|
+
}
|
|
94
|
+
const timing = {
|
|
95
|
+
frameNumber: this.frameCounter++,
|
|
96
|
+
fps,
|
|
97
|
+
frameDuration,
|
|
98
|
+
cpuTime,
|
|
99
|
+
gpuTime,
|
|
100
|
+
renderTime,
|
|
101
|
+
logicTime,
|
|
102
|
+
timestamp: now,
|
|
103
|
+
};
|
|
104
|
+
this.frameTimings.push(timing);
|
|
105
|
+
// Record metrics
|
|
106
|
+
this.recordMetric({
|
|
107
|
+
name: 'frame_duration',
|
|
108
|
+
type: 'gauge',
|
|
109
|
+
value: frameDuration,
|
|
110
|
+
unit: 'ms',
|
|
111
|
+
timestamp: now,
|
|
112
|
+
});
|
|
113
|
+
this.recordMetric({
|
|
114
|
+
name: 'fps',
|
|
115
|
+
type: 'gauge',
|
|
116
|
+
value: fps,
|
|
117
|
+
timestamp: now,
|
|
118
|
+
});
|
|
119
|
+
this.recordMetric({
|
|
120
|
+
name: 'render_time',
|
|
121
|
+
type: 'gauge',
|
|
122
|
+
value: renderTime,
|
|
123
|
+
unit: 'ms',
|
|
124
|
+
timestamp: now,
|
|
125
|
+
});
|
|
126
|
+
this.checkBudgets(timing);
|
|
127
|
+
this.lastFrameTime = now;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Record custom metric
|
|
131
|
+
*/
|
|
132
|
+
recordMetric(metric) {
|
|
133
|
+
this.metrics.push({
|
|
134
|
+
...metric,
|
|
135
|
+
timestamp: Date.now(),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Record memory snapshot
|
|
140
|
+
*/
|
|
141
|
+
recordMemorySnapshot() {
|
|
142
|
+
if (!this.monitoringEnabled)
|
|
143
|
+
return;
|
|
144
|
+
const perf = performance.memory;
|
|
145
|
+
if (!perf) {
|
|
146
|
+
console.warn('Memory profiling not available');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const snapshot = {
|
|
150
|
+
usedJSHeapSize: perf.usedJSHeapSize,
|
|
151
|
+
totalJSHeapSize: perf.totalJSHeapSize,
|
|
152
|
+
jsHeapSizeLimit: perf.jsHeapSizeLimit,
|
|
153
|
+
objectCount: 0, // Would require additional instrumentation
|
|
154
|
+
gcEventsSinceLastSnapshot: 0,
|
|
155
|
+
timestamp: Date.now(),
|
|
156
|
+
};
|
|
157
|
+
this.memorySnapshots.push(snapshot);
|
|
158
|
+
// Record as metrics
|
|
159
|
+
this.recordMetric({
|
|
160
|
+
name: 'heap_used',
|
|
161
|
+
type: 'gauge',
|
|
162
|
+
value: snapshot.usedJSHeapSize,
|
|
163
|
+
unit: 'bytes',
|
|
164
|
+
timestamp: snapshot.timestamp,
|
|
165
|
+
});
|
|
166
|
+
this.recordMetric({
|
|
167
|
+
name: 'heap_total',
|
|
168
|
+
type: 'gauge',
|
|
169
|
+
value: snapshot.totalJSHeapSize,
|
|
170
|
+
unit: 'bytes',
|
|
171
|
+
timestamp: snapshot.timestamp,
|
|
172
|
+
});
|
|
173
|
+
// Check memory budget
|
|
174
|
+
const budget = this.budgets.get('heap_used');
|
|
175
|
+
if (budget && budget.enabled && snapshot.usedJSHeapSize > budget.maxValue) {
|
|
176
|
+
this.emitBudgetViolation('heap_used', snapshot.usedJSHeapSize, budget.maxValue, budget.severity);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check frame metrics against budgets
|
|
181
|
+
*/
|
|
182
|
+
checkBudgets(timing) {
|
|
183
|
+
// Check frame duration budget
|
|
184
|
+
const frameBudget = this.budgets.get('frame_duration');
|
|
185
|
+
if (frameBudget &&
|
|
186
|
+
frameBudget.enabled &&
|
|
187
|
+
timing.frameDuration > frameBudget.maxValue) {
|
|
188
|
+
this.emitBudgetViolation('frame_duration', timing.frameDuration, frameBudget.maxValue, frameBudget.severity);
|
|
189
|
+
}
|
|
190
|
+
// Check render time budget
|
|
191
|
+
const renderBudget = this.budgets.get('render_time');
|
|
192
|
+
if (renderBudget &&
|
|
193
|
+
renderBudget.enabled &&
|
|
194
|
+
timing.renderTime > renderBudget.maxValue) {
|
|
195
|
+
this.emitBudgetViolation('render_time', timing.renderTime, renderBudget.maxValue, renderBudget.severity);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Emit budget violation warning
|
|
200
|
+
*/
|
|
201
|
+
emitBudgetViolation(metric, actual, budget, severity) {
|
|
202
|
+
const message = `Budget violation: ${metric} = ${actual.toFixed(2)} (budget: ${budget.toFixed(2)})`;
|
|
203
|
+
if (severity === 'critical') {
|
|
204
|
+
console.error(`❌ ${message}`);
|
|
205
|
+
}
|
|
206
|
+
else if (severity === 'warning') {
|
|
207
|
+
console.warn(`⚠️ ${message}`);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
console.log(`ℹ️ ${message}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Set or update performance budget
|
|
215
|
+
*/
|
|
216
|
+
setBudget(budget) {
|
|
217
|
+
this.budgets.set(budget.metricName, budget);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Get average FPS over recent frames
|
|
221
|
+
*/
|
|
222
|
+
getAverageFPS() {
|
|
223
|
+
if (this.frameTimes.length === 0)
|
|
224
|
+
return 0;
|
|
225
|
+
const avgFrameTime = this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length;
|
|
226
|
+
return Math.round(1000 / avgFrameTime);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get memory usage stats
|
|
230
|
+
*/
|
|
231
|
+
getMemoryStats() {
|
|
232
|
+
if (this.memorySnapshots.length === 0) {
|
|
233
|
+
return { used: 0, total: 0, limit: 0, percentage: 0 };
|
|
234
|
+
}
|
|
235
|
+
const latest = this.memorySnapshots[this.memorySnapshots.length - 1];
|
|
236
|
+
return {
|
|
237
|
+
used: latest.usedJSHeapSize,
|
|
238
|
+
total: latest.totalJSHeapSize,
|
|
239
|
+
limit: latest.jsHeapSizeLimit,
|
|
240
|
+
percentage: (latest.usedJSHeapSize / latest.jsHeapSizeLimit) * 100,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get recent frame timings
|
|
245
|
+
*/
|
|
246
|
+
getRecentFrameTimings(count = 60) {
|
|
247
|
+
return this.frameTimings.slice(-count);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Add analytics exporter
|
|
251
|
+
*/
|
|
252
|
+
addExporter(exporter) {
|
|
253
|
+
this.exporters.push(exporter);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Export all metrics to registered exporters
|
|
257
|
+
*/
|
|
258
|
+
async exportMetrics() {
|
|
259
|
+
if (this.metrics.length === 0)
|
|
260
|
+
return;
|
|
261
|
+
const metricsToExport = [...this.metrics];
|
|
262
|
+
this.metrics = []; // Clear after export
|
|
263
|
+
for (const exporter of this.exporters) {
|
|
264
|
+
try {
|
|
265
|
+
await exporter.export(metricsToExport);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
console.error('Failed to export metrics:', error);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Generate performance report
|
|
274
|
+
*/
|
|
275
|
+
generateReport() {
|
|
276
|
+
const avgFps = this.getAverageFPS();
|
|
277
|
+
const memStats = this.getMemoryStats();
|
|
278
|
+
const recentFrames = this.getRecentFrameTimings(60);
|
|
279
|
+
let report = '=== Performance Report ===\n\n';
|
|
280
|
+
report += `Average FPS: ${avgFps}\n`;
|
|
281
|
+
report += `Recent Frame Count: ${recentFrames.length}\n`;
|
|
282
|
+
if (recentFrames.length > 0) {
|
|
283
|
+
const avgFrameTime = recentFrames.reduce((sum, f) => sum + f.frameDuration, 0) /
|
|
284
|
+
recentFrames.length;
|
|
285
|
+
const maxFrameTime = Math.max(...recentFrames.map((f) => f.frameDuration));
|
|
286
|
+
const minFrameTime = Math.min(...recentFrames.map((f) => f.frameDuration));
|
|
287
|
+
report += `Frame Time: min=${minFrameTime.toFixed(2)}ms, avg=${avgFrameTime.toFixed(2)}ms, max=${maxFrameTime.toFixed(2)}ms\n`;
|
|
288
|
+
}
|
|
289
|
+
report += `\nMemory Usage:\n`;
|
|
290
|
+
report += ` Used: ${(memStats.used / 1024 / 1024).toFixed(2)} MB\n`;
|
|
291
|
+
report += ` Total: ${(memStats.total / 1024 / 1024).toFixed(2)} MB\n`;
|
|
292
|
+
report += ` Limit: ${(memStats.limit / 1024 / 1024).toFixed(2)} MB\n`;
|
|
293
|
+
report += ` Percentage: ${memStats.percentage.toFixed(1)}%\n`;
|
|
294
|
+
report += `\nMetrics Recorded: ${this.metrics.length}\n`;
|
|
295
|
+
report += `Memory Snapshots: ${this.memorySnapshots.length}\n`;
|
|
296
|
+
return report;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Dispose and cleanup
|
|
300
|
+
*/
|
|
301
|
+
dispose() {
|
|
302
|
+
this.stopMonitoring();
|
|
303
|
+
this.metrics = [];
|
|
304
|
+
this.frameTimings = [];
|
|
305
|
+
this.memorySnapshots = [];
|
|
306
|
+
this.frameTimes = [];
|
|
307
|
+
this.budgets.clear();
|
|
308
|
+
this.exporters = [];
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Singleton instance
|
|
313
|
+
*/
|
|
314
|
+
let telemetryInstance = null;
|
|
315
|
+
/**
|
|
316
|
+
* Get or create telemetry instance
|
|
317
|
+
*/
|
|
318
|
+
export function getPerformanceTelemetry() {
|
|
319
|
+
if (!telemetryInstance) {
|
|
320
|
+
telemetryInstance = new PerformanceTelemetry();
|
|
321
|
+
}
|
|
322
|
+
return telemetryInstance;
|
|
323
|
+
}
|