Parcourir la source

created a simple d.ts wrapper around usertiming.js also wrapped calls to usertiming behind calls in metrics.ts. Also turned on expirmental decorator support in the typescript compiler so that it is possible to annotate a function with @metrics.profileDecorator and have it auto time the function

Shaddock Heath il y a 10 ans
Parent
commit
730c9a1d22

+ 106 - 0
Script/AtomicEditor/modules/metrics.ts

@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+// Wraps the performance API / performance API polyfill
+import performance = require("modules/usertiming");
+
+const METRICS_ENABLED = true;
+
+/**
+ * Decorator to wrap a function with enter/exit profile
+ * @param  {Object} target
+ * @param  {string} propertyKey
+ * @param  {TypedPropertyDescriptor<any>} descriptor
+ * @return {TypedPropertyDesciptor<any>}
+ */
+export function profileDecorator(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
+    const originalMethod = descriptor.value;
+
+    descriptor.value = function(...args: any[]) {
+        let result;
+        start(propertyKey);
+        try {
+            result = originalMethod.apply(this, args);
+        } finally {
+            stop(propertyKey);
+            return result;
+        }
+    };
+
+    return descriptor;
+}
+
+/**
+ * add a start mark to the profiler
+ * @param  {string} key
+ */
+export function start(key: string) {
+    if (METRICS_ENABLED) {
+        performance.mark(key + "_start");
+    }
+}
+
+/**
+ * Add a stop mark to the profiler and capture a measurement
+ * @param  {string} key
+ */
+export function stop(key: string) {
+    if (METRICS_ENABLED) {
+        performance.mark(key + "_stop");
+        performance.measure(key, key + "_start", key + "_stop");
+    }
+
+}
+
+export interface MetricRollup {
+    key: string;
+    timesCalled: number;
+    avgDuration: number;
+    totalDuration: number;
+}
+
+/**
+ * Returns an array of metric rollups
+ * @return {[MetricRollup]}
+ */
+export function getMetricRollups(): MetricRollup[] {
+    if (METRICS_ENABLED) {
+        const metrics = {};
+
+        performance.getEntriesByType("measure").forEach((entry) => {
+            if (!metrics[entry.name]) {
+                metrics[entry.name] = [];
+            }
+            metrics[entry.name].push(entry);
+        });
+        const vals = [];
+        for (let mname in metrics) {
+            let totalduration = 0;
+            let metricBlock = metrics[mname];
+            for (let i = 0; i < metricBlock.length; i++) {
+                totalduration += metricBlock[i].duration;
+            }
+            vals.push({
+                key: mname,
+                timesCalled: metricBlock.length,
+                avgDuration: totalduration / metricBlock.length,
+                totalDuration: totalduration
+            });
+        }
+        return vals;
+    } else {
+        return [];
+    }
+}
+
+/**
+ * Write metrics to the console
+ */
+export function logMetrics() {
+    getMetricRollups().forEach((metric) => {
+        console.log(`${metric.key}  Called: ${metric.timesCalled}, Average Duration:${metric.avgDuration}, Total Duration: ${metric.totalDuration}`);
+    });
+}

+ 32 - 0
Script/AtomicEditor/modules/usertiming.d.ts

@@ -0,0 +1,32 @@
+declare interface PerformanceEntryFilterOptions {
+    // the name of a performance entry.
+    name?: string;
+    // the entry type. The valid entry types are listed in the PerformanceEntry.entryType method.
+    entryType?: string;
+
+    // the type of the initiating resource (for example an HTML element). The values are defined by the
+    initiatorType?: string;
+}
+
+declare interface PerformanceEntry {
+    // A DOMString representing the name of a performance entry when the metric was created.
+    name: string;
+    // A DOMString representing the type of performance metric such as "mark". See entryType for a list of valid values.
+    entryType: string;
+    // A DOMHighResTimeStamp representing the starting time for the performance metric.
+    startTime: Date;
+    // A DOMHighResTimeStamp representing the time value of the duration of the performance event.
+    duration: Number;
+}
+
+declare interface Performance {
+    mark(name: string);
+    measure(name: string, startMark: string, endMark: string);
+    getEntries();
+    getEntries(performanceEntryFilterOptions: PerformanceEntryFilterOptions): PerformanceEntry[];
+    getEntriesByType(entryType:string);
+}
+
+
+declare const performance: Performance;
+export = performance;

+ 4 - 1
Script/tsconfig.json

@@ -8,7 +8,8 @@
         "noLib": false,
         "outDir": "../Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts",
         "moduleResolution": "classic",
-        "sourceMap": true
+        "sourceMap": true,
+        "experimentalDecorators": true
     },
     "filesGlob": [
         "./ToolCore/**/*.ts",
@@ -28,7 +29,9 @@
         "./AtomicEditor/extensionServices/resourceServices/TypescriptLanguageService.ts",
         "./AtomicEditor/extensionServices/ServiceLocator.ts",
         "./AtomicEditor/main.ts",
+        "./AtomicEditor/modules/metrics.ts",
         "./AtomicEditor/modules/typescript.d.ts",
+        "./AtomicEditor/modules/usertiming.d.ts",
         "./AtomicEditor/resources/ProjectTemplates.ts",
         "./AtomicEditor/resources/ResourceOps.ts",
         "./AtomicEditor/ui/EditorStrings.ts",