新增TimeRuler用于分析游戏平均帧率
This commit is contained in:
Vendored
+79
-9
@@ -18,11 +18,16 @@ declare module es {
|
|||||||
/**
|
/**
|
||||||
* 简化对内部类的全局内容实例的访问
|
* 简化对内部类的全局内容实例的访问
|
||||||
*/
|
*/
|
||||||
static _instance: Core;
|
private static _instance;
|
||||||
/**
|
/**
|
||||||
* 用于确定是否应该使用EntitySystems
|
* 用于确定是否应该使用EntitySystems
|
||||||
*/
|
*/
|
||||||
static entitySystemsEnabled: boolean;
|
static entitySystemsEnabled: boolean;
|
||||||
|
/**
|
||||||
|
* 是否正在debug模式
|
||||||
|
* 仅允许在create时进行更改
|
||||||
|
*/
|
||||||
|
readonly debug: boolean;
|
||||||
_nextScene: Scene;
|
_nextScene: Scene;
|
||||||
/**
|
/**
|
||||||
* 用于凝聚GraphicsDeviceReset事件
|
* 用于凝聚GraphicsDeviceReset事件
|
||||||
@@ -34,9 +39,7 @@ declare module es {
|
|||||||
_globalManagers: GlobalManager[];
|
_globalManagers: GlobalManager[];
|
||||||
_coroutineManager: CoroutineManager;
|
_coroutineManager: CoroutineManager;
|
||||||
_timerManager: TimerManager;
|
_timerManager: TimerManager;
|
||||||
width: number;
|
private constructor();
|
||||||
height: number;
|
|
||||||
constructor(width: number, height: number, enableEntitySystems?: boolean);
|
|
||||||
/**
|
/**
|
||||||
* 提供对单例/游戏实例的访问
|
* 提供对单例/游戏实例的访问
|
||||||
* @constructor
|
* @constructor
|
||||||
@@ -55,6 +58,10 @@ declare module es {
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
static scene: Scene;
|
static scene: Scene;
|
||||||
|
/**
|
||||||
|
* 默认实现创建核心
|
||||||
|
*/
|
||||||
|
static create(debug?: boolean): Core;
|
||||||
/**
|
/**
|
||||||
* 添加一个全局管理器对象,它的更新方法将调用场景前的每一帧。
|
* 添加一个全局管理器对象,它的更新方法将调用场景前的每一帧。
|
||||||
* @param manager
|
* @param manager
|
||||||
@@ -84,6 +91,8 @@ declare module es {
|
|||||||
* @param onTime
|
* @param onTime
|
||||||
*/
|
*/
|
||||||
static schedule(timeInSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer) => void): Timer;
|
static schedule(timeInSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer) => void): Timer;
|
||||||
|
startDebugUpdate(): void;
|
||||||
|
endDebugUpdate(): void;
|
||||||
startDebugDraw(): void;
|
startDebugDraw(): void;
|
||||||
/**
|
/**
|
||||||
* 在一个场景结束后,下一个场景开始之前调用
|
* 在一个场景结束后,下一个场景开始之前调用
|
||||||
@@ -150,10 +159,6 @@ declare module es {
|
|||||||
* 此组件附加的实体
|
* 此组件附加的实体
|
||||||
*/
|
*/
|
||||||
entity: Entity;
|
entity: Entity;
|
||||||
/**
|
|
||||||
* 更新该组件的时间间隔。这与实体的更新间隔无关。
|
|
||||||
*/
|
|
||||||
updateInterval: number;
|
|
||||||
/**
|
/**
|
||||||
* 快速访问 this.entity.transform
|
* 快速访问 this.entity.transform
|
||||||
*/
|
*/
|
||||||
@@ -3237,7 +3242,7 @@ declare module es {
|
|||||||
private initialize;
|
private initialize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare namespace stopwatch {
|
declare namespace es {
|
||||||
/**
|
/**
|
||||||
* 记录时间的持续时间,一些设计灵感来自物理秒表。
|
* 记录时间的持续时间,一些设计灵感来自物理秒表。
|
||||||
*/
|
*/
|
||||||
@@ -3350,6 +3355,71 @@ declare namespace stopwatch {
|
|||||||
readonly duration: number;
|
readonly duration: number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
declare module es {
|
||||||
|
class TimeRuler {
|
||||||
|
/**
|
||||||
|
* 最大条数
|
||||||
|
*/
|
||||||
|
static readonly maxBars: number;
|
||||||
|
/**
|
||||||
|
* 每条的最大样本数
|
||||||
|
*/
|
||||||
|
static readonly maxSamples: number;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static readonly maxNestCall: number;
|
||||||
|
/**
|
||||||
|
* 最大显示帧数
|
||||||
|
*/
|
||||||
|
static readonly maxSampleFrames: number;
|
||||||
|
/**
|
||||||
|
* 拍摄快照的时间(以帧数为单位)
|
||||||
|
*/
|
||||||
|
static readonly logSnapDuration: number;
|
||||||
|
private logs;
|
||||||
|
private prevLog;
|
||||||
|
private curLog;
|
||||||
|
private frameCount;
|
||||||
|
private stopwatch;
|
||||||
|
private markers;
|
||||||
|
private markerNameToIdMap;
|
||||||
|
enabled: boolean;
|
||||||
|
private static _instance;
|
||||||
|
static readonly Instance: TimeRuler;
|
||||||
|
/**
|
||||||
|
* 你想在Game.Update方法的开头调用StartFrame。
|
||||||
|
* 但是当游戏在固定时间步长模式下运行缓慢时,Game.Update会被多次调用。
|
||||||
|
* 在这种情况下,我们应该忽略StartFrame的调用,为了做到这一点,我们只需要跟踪StartFrame的调用次数
|
||||||
|
*/
|
||||||
|
private updateCount;
|
||||||
|
constructor();
|
||||||
|
startFrame(): void;
|
||||||
|
/**
|
||||||
|
* 开始测量时间
|
||||||
|
* @param markerName
|
||||||
|
* @param color
|
||||||
|
* @param barIndex
|
||||||
|
*/
|
||||||
|
beginMark(markerName: string, color: number, barIndex?: number): void;
|
||||||
|
/**
|
||||||
|
* 停止测量
|
||||||
|
* @param markerName
|
||||||
|
* @param barIndex
|
||||||
|
*/
|
||||||
|
endMark(markerName: string, barIndex?: number): void;
|
||||||
|
/**
|
||||||
|
* 获取给定条形指数和标记名称的平均时间
|
||||||
|
* @param barIndex
|
||||||
|
* @param markerName
|
||||||
|
*/
|
||||||
|
getAverageTime(barIndex: number, markerName: string): number;
|
||||||
|
/**
|
||||||
|
* 重置标记记录
|
||||||
|
*/
|
||||||
|
resetLog(): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
/**
|
/**
|
||||||
* 创建这个字典的原因只有一个:
|
* 创建这个字典的原因只有一个:
|
||||||
|
|||||||
+337
-24
@@ -80,7 +80,8 @@ var es;
|
|||||||
* 全局核心类
|
* 全局核心类
|
||||||
*/
|
*/
|
||||||
var Core = /** @class */ (function () {
|
var Core = /** @class */ (function () {
|
||||||
function Core(width, height, enableEntitySystems) {
|
function Core(debug, enableEntitySystems) {
|
||||||
|
if (debug === void 0) { debug = true; }
|
||||||
if (enableEntitySystems === void 0) { enableEntitySystems = true; }
|
if (enableEntitySystems === void 0) { enableEntitySystems = true; }
|
||||||
/**
|
/**
|
||||||
* 全局访问系统
|
* 全局访问系统
|
||||||
@@ -91,14 +92,13 @@ var es;
|
|||||||
this._frameCounterElapsedTime = 0;
|
this._frameCounterElapsedTime = 0;
|
||||||
this._frameCounter = 0;
|
this._frameCounter = 0;
|
||||||
this._totalMemory = 0;
|
this._totalMemory = 0;
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
Core._instance = this;
|
Core._instance = this;
|
||||||
Core.emitter = new es.Emitter();
|
Core.emitter = new es.Emitter();
|
||||||
Core.emitter.addObserver(es.CoreEvents.frameUpdated, this.update, this);
|
Core.emitter.addObserver(es.CoreEvents.frameUpdated, this.update, this);
|
||||||
Core.registerGlobalManager(this._coroutineManager);
|
Core.registerGlobalManager(this._coroutineManager);
|
||||||
Core.registerGlobalManager(this._timerManager);
|
Core.registerGlobalManager(this._timerManager);
|
||||||
Core.entitySystemsEnabled = enableEntitySystems;
|
Core.entitySystemsEnabled = enableEntitySystems;
|
||||||
|
this.debug = debug;
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
Object.defineProperty(Core, "Instance", {
|
Object.defineProperty(Core, "Instance", {
|
||||||
@@ -139,6 +139,16 @@ var es;
|
|||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
/**
|
||||||
|
* 默认实现创建核心
|
||||||
|
*/
|
||||||
|
Core.create = function (debug) {
|
||||||
|
if (debug === void 0) { debug = true; }
|
||||||
|
if (this._instance == null) {
|
||||||
|
this._instance = new es.Core(debug);
|
||||||
|
}
|
||||||
|
return this._instance;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* 添加一个全局管理器对象,它的更新方法将调用场景前的每一帧。
|
* 添加一个全局管理器对象,它的更新方法将调用场景前的每一帧。
|
||||||
* @param manager
|
* @param manager
|
||||||
@@ -186,7 +196,20 @@ var es;
|
|||||||
if (context === void 0) { context = null; }
|
if (context === void 0) { context = null; }
|
||||||
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
|
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
|
||||||
};
|
};
|
||||||
|
Core.prototype.startDebugUpdate = function () {
|
||||||
|
if (!this.debug)
|
||||||
|
return;
|
||||||
|
es.TimeRuler.Instance.startFrame();
|
||||||
|
es.TimeRuler.Instance.beginMark('update', 0x00ff00);
|
||||||
|
};
|
||||||
|
Core.prototype.endDebugUpdate = function () {
|
||||||
|
if (!this.debug)
|
||||||
|
return;
|
||||||
|
es.TimeRuler.Instance.endMark('update');
|
||||||
|
};
|
||||||
Core.prototype.startDebugDraw = function () {
|
Core.prototype.startDebugDraw = function () {
|
||||||
|
if (!this.debug)
|
||||||
|
return;
|
||||||
this._frameCounter++;
|
this._frameCounter++;
|
||||||
this._frameCounterElapsedTime += es.Time.deltaTime;
|
this._frameCounterElapsedTime += es.Time.deltaTime;
|
||||||
if (this._frameCounterElapsedTime >= 1) {
|
if (this._frameCounterElapsedTime >= 1) {
|
||||||
@@ -209,10 +232,11 @@ var es;
|
|||||||
Core.prototype.initialize = function () {
|
Core.prototype.initialize = function () {
|
||||||
};
|
};
|
||||||
Core.prototype.update = function (currentTime) {
|
Core.prototype.update = function (currentTime) {
|
||||||
|
if (currentTime === void 0) { currentTime = -1; }
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
return __awaiter(this, void 0, void 0, function () {
|
||||||
var i;
|
var i;
|
||||||
return __generator(this, function (_a) {
|
return __generator(this, function (_a) {
|
||||||
if (currentTime != null)
|
this.startDebugUpdate();
|
||||||
es.Time.update(currentTime);
|
es.Time.update(currentTime);
|
||||||
if (this._scene != null) {
|
if (this._scene != null) {
|
||||||
for (i = this._globalManagers.length - 1; i >= 0; i--) {
|
for (i = this._globalManagers.length - 1; i >= 0; i--) {
|
||||||
@@ -228,6 +252,7 @@ var es;
|
|||||||
this._scene.begin();
|
this._scene.begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.endDebugUpdate();
|
||||||
this.startDebugDraw();
|
this.startDebugDraw();
|
||||||
return [2 /*return*/];
|
return [2 /*return*/];
|
||||||
});
|
});
|
||||||
@@ -435,10 +460,6 @@ var es;
|
|||||||
*/
|
*/
|
||||||
var Component = /** @class */ (function () {
|
var Component = /** @class */ (function () {
|
||||||
function Component() {
|
function Component() {
|
||||||
/**
|
|
||||||
* 更新该组件的时间间隔。这与实体的更新间隔无关。
|
|
||||||
*/
|
|
||||||
this.updateInterval = 1;
|
|
||||||
this._enabled = true;
|
this._enabled = true;
|
||||||
this._updateOrder = 0;
|
this._updateOrder = 0;
|
||||||
}
|
}
|
||||||
@@ -4148,7 +4169,11 @@ var es;
|
|||||||
function Time() {
|
function Time() {
|
||||||
}
|
}
|
||||||
Time.update = function (currentTime) {
|
Time.update = function (currentTime) {
|
||||||
var dt = (currentTime - this._lastTime) / 1000;
|
if (currentTime == -1)
|
||||||
|
currentTime = Date.now();
|
||||||
|
if (this._lastTime == -1)
|
||||||
|
this._lastTime = currentTime;
|
||||||
|
var dt = currentTime - this._lastTime;
|
||||||
this.totalTime += dt;
|
this.totalTime += dt;
|
||||||
this.deltaTime = dt * this.timeScale;
|
this.deltaTime = dt * this.timeScale;
|
||||||
this.unscaledDeltaTime = dt;
|
this.unscaledDeltaTime = dt;
|
||||||
@@ -4179,7 +4204,7 @@ var es;
|
|||||||
Time.frameCount = 0;
|
Time.frameCount = 0;
|
||||||
/** 自场景加载以来的总时间 */
|
/** 自场景加载以来的总时间 */
|
||||||
Time.timeSinceSceneLoad = 0;
|
Time.timeSinceSceneLoad = 0;
|
||||||
Time._lastTime = 0;
|
Time._lastTime = -1;
|
||||||
return Time;
|
return Time;
|
||||||
}());
|
}());
|
||||||
es.Time = Time;
|
es.Time = Time;
|
||||||
@@ -8116,8 +8141,8 @@ var es;
|
|||||||
}());
|
}());
|
||||||
es.Triangulator = Triangulator;
|
es.Triangulator = Triangulator;
|
||||||
})(es || (es = {}));
|
})(es || (es = {}));
|
||||||
var stopwatch;
|
var es;
|
||||||
(function (stopwatch) {
|
(function (es) {
|
||||||
/**
|
/**
|
||||||
* 记录时间的持续时间,一些设计灵感来自物理秒表。
|
* 记录时间的持续时间,一些设计灵感来自物理秒表。
|
||||||
*/
|
*/
|
||||||
@@ -8282,7 +8307,7 @@ var stopwatch;
|
|||||||
};
|
};
|
||||||
return Stopwatch;
|
return Stopwatch;
|
||||||
}());
|
}());
|
||||||
stopwatch.Stopwatch = Stopwatch;
|
es.Stopwatch = Stopwatch;
|
||||||
var State;
|
var State;
|
||||||
(function (State) {
|
(function (State) {
|
||||||
/** 秒表尚未启动,或已复位。 */
|
/** 秒表尚未启动,或已复位。 */
|
||||||
@@ -8296,10 +8321,298 @@ var stopwatch;
|
|||||||
if (systemTimeGetter === void 0) { systemTimeGetter = Date.now; }
|
if (systemTimeGetter === void 0) { systemTimeGetter = Date.now; }
|
||||||
_defaultSystemTimeGetter = systemTimeGetter;
|
_defaultSystemTimeGetter = systemTimeGetter;
|
||||||
}
|
}
|
||||||
stopwatch.setDefaultSystemTimeGetter = setDefaultSystemTimeGetter;
|
es.setDefaultSystemTimeGetter = setDefaultSystemTimeGetter;
|
||||||
/** 所有新实例的默认“getSystemTime”实现 */
|
/** 所有新实例的默认“getSystemTime”实现 */
|
||||||
var _defaultSystemTimeGetter = Date.now;
|
var _defaultSystemTimeGetter = Date.now;
|
||||||
})(stopwatch || (stopwatch = {}));
|
})(es || (es = {}));
|
||||||
|
var es;
|
||||||
|
(function (es) {
|
||||||
|
var TimeRuler = /** @class */ (function () {
|
||||||
|
function TimeRuler() {
|
||||||
|
//当前帧数
|
||||||
|
this.frameCount = 0;
|
||||||
|
// 测量时间的秒表
|
||||||
|
this.stopwatch = new es.Stopwatch;
|
||||||
|
// 标记信息阵列
|
||||||
|
this.markers = [];
|
||||||
|
// 从标记名称映射到标记ID的词典
|
||||||
|
this.markerNameToIdMap = new Map();
|
||||||
|
this.enabled = true;
|
||||||
|
/**
|
||||||
|
* 你想在Game.Update方法的开头调用StartFrame。
|
||||||
|
* 但是当游戏在固定时间步长模式下运行缓慢时,Game.Update会被多次调用。
|
||||||
|
* 在这种情况下,我们应该忽略StartFrame的调用,为了做到这一点,我们只需要跟踪StartFrame的调用次数
|
||||||
|
*/
|
||||||
|
this.updateCount = 0;
|
||||||
|
this.logs = new Array(2);
|
||||||
|
for (var i = 0; i < this.logs.length; ++i)
|
||||||
|
this.logs[i] = new FrameLog();
|
||||||
|
}
|
||||||
|
Object.defineProperty(TimeRuler, "Instance", {
|
||||||
|
get: function () {
|
||||||
|
if (!this._instance)
|
||||||
|
this._instance = new TimeRuler();
|
||||||
|
return this._instance;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
TimeRuler.prototype.startFrame = function () {
|
||||||
|
if (!es.Core.Instance.debug)
|
||||||
|
return;
|
||||||
|
// 当这个方法被多次调用时,我们跳过复位帧
|
||||||
|
var count = this.updateCount++;
|
||||||
|
if (this.enabled && (1 < count && count < TimeRuler.maxSampleFrames))
|
||||||
|
return;
|
||||||
|
// 更新当前帧记录
|
||||||
|
this.prevLog = this.logs[this.frameCount++ & 0x1];
|
||||||
|
this.curLog = this.logs[this.frameCount & 0x1];
|
||||||
|
var endFrameTime = this.stopwatch.getTime();
|
||||||
|
// 更新标记并创建日志
|
||||||
|
for (var barIdx = 0; barIdx < this.prevLog.bars.length; ++barIdx) {
|
||||||
|
var prevBar = this.prevLog.bars[barIdx];
|
||||||
|
var nextBar = this.curLog.bars[barIdx];
|
||||||
|
// 重新打开前一帧中没有被调用的EndMark的标记
|
||||||
|
for (var nest = 0; nest < prevBar.nestCount; ++nest) {
|
||||||
|
var markerIdx = prevBar.markerNests[nest];
|
||||||
|
prevBar.markers[markerIdx].endTime = endFrameTime;
|
||||||
|
nextBar.markerNests[nest] = nest;
|
||||||
|
nextBar.markers[nest].markerId = prevBar.markers[markerIdx].markerId;
|
||||||
|
nextBar.markers[nest].beginTime = 0;
|
||||||
|
nextBar.markers[nest].endTime = -1;
|
||||||
|
nextBar.markers[nest].color = prevBar.markers[markerIdx].color;
|
||||||
|
}
|
||||||
|
// 更新标记记录
|
||||||
|
for (var markerIdx = 0; markerIdx < prevBar.markCount; ++markerIdx) {
|
||||||
|
var duration = prevBar.markers[markerIdx].endTime - prevBar.markers[markerIdx].beginTime;
|
||||||
|
var markerId = prevBar.markers[markerIdx].markerId;
|
||||||
|
var m = this.markers[markerId];
|
||||||
|
m.logs[barIdx].color = prevBar.markers[markerIdx].color;
|
||||||
|
if (!m.logs[barIdx].initialized) {
|
||||||
|
// 第一帧流程
|
||||||
|
m.logs[barIdx].min = duration;
|
||||||
|
m.logs[barIdx].max = duration;
|
||||||
|
m.logs[barIdx].avg = duration;
|
||||||
|
m.logs[barIdx].initialized = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 第一帧后处理
|
||||||
|
m.logs[barIdx].min = Math.min(m.logs[barIdx].min, duration);
|
||||||
|
m.logs[barIdx].max = Math.min(m.logs[barIdx].max, duration);
|
||||||
|
m.logs[barIdx].avg += duration;
|
||||||
|
m.logs[barIdx].avg *= 0.5;
|
||||||
|
if (m.logs[barIdx].samples++ >= TimeRuler.logSnapDuration) {
|
||||||
|
m.logs[barIdx].snapMin = m.logs[barIdx].min;
|
||||||
|
m.logs[barIdx].snapMax = m.logs[barIdx].max;
|
||||||
|
m.logs[barIdx].snapAvg = m.logs[barIdx].avg;
|
||||||
|
m.logs[barIdx].samples = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextBar.markCount = prevBar.nestCount;
|
||||||
|
nextBar.nestCount = prevBar.nestCount;
|
||||||
|
}
|
||||||
|
this.stopwatch.reset();
|
||||||
|
this.stopwatch.start();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 开始测量时间
|
||||||
|
* @param markerName
|
||||||
|
* @param color
|
||||||
|
* @param barIndex
|
||||||
|
*/
|
||||||
|
TimeRuler.prototype.beginMark = function (markerName, color, barIndex) {
|
||||||
|
if (barIndex === void 0) { barIndex = 0; }
|
||||||
|
if (!es.Core.Instance.debug)
|
||||||
|
return;
|
||||||
|
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
|
||||||
|
throw new Error('barIndex 越位');
|
||||||
|
var bar = this.curLog.bars[barIndex];
|
||||||
|
if (bar.markCount >= TimeRuler.maxSamples) {
|
||||||
|
throw new Error('超出样本数.\n 要么设置更大的数字为TimeRuler.MaxSmpale,要么降低样本数');
|
||||||
|
}
|
||||||
|
if (bar.nestCount >= TimeRuler.maxNestCall) {
|
||||||
|
throw new Error('nestCount超出.\n 要么将大的设置为TimeRuler.MaxNestCall,要么将小的设置为NestCall');
|
||||||
|
}
|
||||||
|
// 获取已注册的标记
|
||||||
|
var markerId = this.markerNameToIdMap.get(markerName);
|
||||||
|
if (markerId == null) {
|
||||||
|
// 如果这个标记没有注册,就注册这个
|
||||||
|
markerId = this.markers.length;
|
||||||
|
this.markerNameToIdMap.set(markerName, markerId);
|
||||||
|
this.markers.push(new MarkerInfo(markerName));
|
||||||
|
}
|
||||||
|
// 开始测量
|
||||||
|
bar.markerNests[bar.nestCount++] = bar.markCount;
|
||||||
|
// 填充标记参数
|
||||||
|
bar.markers[bar.markCount].markerId = markerId;
|
||||||
|
bar.markers[bar.markCount].color = color;
|
||||||
|
bar.markers[bar.markCount].beginTime = this.stopwatch.getTime();
|
||||||
|
bar.markers[bar.markCount].endTime = -1;
|
||||||
|
bar.markCount++;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 停止测量
|
||||||
|
* @param markerName
|
||||||
|
* @param barIndex
|
||||||
|
*/
|
||||||
|
TimeRuler.prototype.endMark = function (markerName, barIndex) {
|
||||||
|
if (barIndex === void 0) { barIndex = 0; }
|
||||||
|
if (!es.Core.Instance.debug)
|
||||||
|
return;
|
||||||
|
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
|
||||||
|
throw new Error('barIndex 越位');
|
||||||
|
var bar = this.curLog.bars[barIndex];
|
||||||
|
if (bar.nestCount <= 0) {
|
||||||
|
throw new Error('在调用结束标记方法之前调用beginMark方法');
|
||||||
|
}
|
||||||
|
var markerId = this.markerNameToIdMap.get(markerName);
|
||||||
|
if (markerId == null) {
|
||||||
|
throw new Error("\u6807\u8BB0" + markerName + "\u6CA1\u6709\u6CE8\u518C\u3002\u8BF7\u786E\u8BA4\u60A8\u6307\u5B9A\u7684\u540D\u79F0\u4E0EBeginMark\u65B9\u6CD5\u4F7F\u7528\u7684\u540D\u79F0\u76F8\u540C");
|
||||||
|
}
|
||||||
|
var markerIdx = bar.markerNests[--bar.nestCount];
|
||||||
|
if (bar.markers[markerIdx].markerId != markerId) {
|
||||||
|
throw new Error('beginMark/endMark方法的调用顺序不正确. beginMark(A), beginMark(B), endMark(B), endMark(A).但你不能像这样叫它 beginMark(A), beginMark(B), endMark(A), endMark(B)');
|
||||||
|
}
|
||||||
|
bar.markers[markerIdx].endTime = this.stopwatch.getTime();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 获取给定条形指数和标记名称的平均时间
|
||||||
|
* @param barIndex
|
||||||
|
* @param markerName
|
||||||
|
*/
|
||||||
|
TimeRuler.prototype.getAverageTime = function (barIndex, markerName) {
|
||||||
|
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
|
||||||
|
throw new Error('barIndex 越位');
|
||||||
|
var result = 0;
|
||||||
|
var markerId = this.markerNameToIdMap.get(markerName);
|
||||||
|
if (markerId != null) {
|
||||||
|
result = this.markers[markerId].logs[barIndex].avg;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 重置标记记录
|
||||||
|
*/
|
||||||
|
TimeRuler.prototype.resetLog = function () {
|
||||||
|
var e_14, _a;
|
||||||
|
if (!es.Core.Instance.debug)
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
for (var _b = __values(this.markers), _c = _b.next(); !_c.done; _c = _b.next()) {
|
||||||
|
var markerInfo = _c.value;
|
||||||
|
for (var i = 0; i < markerInfo.logs.length; ++i) {
|
||||||
|
markerInfo.logs[i].initialized = false;
|
||||||
|
markerInfo.logs[i].snapMin = 0;
|
||||||
|
markerInfo.logs[i].snapMax = 0;
|
||||||
|
markerInfo.logs[i].snapAvg = 0;
|
||||||
|
markerInfo.logs[i].min = 0;
|
||||||
|
markerInfo.logs[i].max = 0;
|
||||||
|
markerInfo.logs[i].avg = 0;
|
||||||
|
markerInfo.logs[i].samples = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
||||||
|
}
|
||||||
|
finally { if (e_14) throw e_14.error; }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 最大条数
|
||||||
|
*/
|
||||||
|
TimeRuler.maxBars = 8;
|
||||||
|
/**
|
||||||
|
* 每条的最大样本数
|
||||||
|
*/
|
||||||
|
TimeRuler.maxSamples = 256;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
TimeRuler.maxNestCall = 32;
|
||||||
|
/**
|
||||||
|
* 最大显示帧数
|
||||||
|
*/
|
||||||
|
TimeRuler.maxSampleFrames = 4;
|
||||||
|
/**
|
||||||
|
* 拍摄快照的时间(以帧数为单位)
|
||||||
|
*/
|
||||||
|
TimeRuler.logSnapDuration = 120;
|
||||||
|
return TimeRuler;
|
||||||
|
}());
|
||||||
|
es.TimeRuler = TimeRuler;
|
||||||
|
/**
|
||||||
|
* 标记信息
|
||||||
|
*/
|
||||||
|
var MarkerInfo = /** @class */ (function () {
|
||||||
|
function MarkerInfo(name) {
|
||||||
|
this.logs = new Array(TimeRuler.maxBars);
|
||||||
|
this.name = name;
|
||||||
|
for (var i = 0; i < TimeRuler.maxBars; ++i)
|
||||||
|
this.logs[i] = new MarkerLog();
|
||||||
|
}
|
||||||
|
return MarkerInfo;
|
||||||
|
}());
|
||||||
|
/**
|
||||||
|
* 标记日志信息
|
||||||
|
*/
|
||||||
|
var MarkerLog = /** @class */ (function () {
|
||||||
|
function MarkerLog() {
|
||||||
|
this.snapMin = 0;
|
||||||
|
this.snapMax = 0;
|
||||||
|
this.snapAvg = 0;
|
||||||
|
this.min = 0;
|
||||||
|
this.max = 0;
|
||||||
|
this.avg = 0;
|
||||||
|
this.samples = 0;
|
||||||
|
this.color = 0x000000;
|
||||||
|
this.initialized = false;
|
||||||
|
}
|
||||||
|
return MarkerLog;
|
||||||
|
}());
|
||||||
|
/**
|
||||||
|
* 帧记录信息
|
||||||
|
*/
|
||||||
|
var FrameLog = /** @class */ (function () {
|
||||||
|
function FrameLog() {
|
||||||
|
this.bars = new Array(TimeRuler.maxBars);
|
||||||
|
for (var i = 0; i < TimeRuler.maxBars; ++i)
|
||||||
|
this.bars[i] = new MarkerCollection();
|
||||||
|
}
|
||||||
|
return FrameLog;
|
||||||
|
}());
|
||||||
|
/**
|
||||||
|
* 收集标记
|
||||||
|
*/
|
||||||
|
var MarkerCollection = /** @class */ (function () {
|
||||||
|
function MarkerCollection() {
|
||||||
|
// 标记收集
|
||||||
|
this.markers = new Array(TimeRuler.maxSamples);
|
||||||
|
this.markCount = 0;
|
||||||
|
this.markerNests = new Array(TimeRuler.maxNestCall);
|
||||||
|
this.nestCount = 0;
|
||||||
|
this.markerNests.fill(0);
|
||||||
|
for (var i = 0; i < TimeRuler.maxSamples; ++i)
|
||||||
|
this.markers[i] = new Marker();
|
||||||
|
}
|
||||||
|
return MarkerCollection;
|
||||||
|
}());
|
||||||
|
/**
|
||||||
|
* 标记结构
|
||||||
|
*/
|
||||||
|
var Marker = /** @class */ (function () {
|
||||||
|
function Marker() {
|
||||||
|
this.markerId = 0;
|
||||||
|
this.beginTime = 0;
|
||||||
|
this.endTime = 0;
|
||||||
|
this.color = 0x000000;
|
||||||
|
}
|
||||||
|
return Marker;
|
||||||
|
}());
|
||||||
|
})(es || (es = {}));
|
||||||
var es;
|
var es;
|
||||||
(function (es) {
|
(function (es) {
|
||||||
/**
|
/**
|
||||||
@@ -10795,7 +11108,7 @@ var linq;
|
|||||||
* 创建一个Set从一个Enumerable.List< T>。
|
* 创建一个Set从一个Enumerable.List< T>。
|
||||||
*/
|
*/
|
||||||
List.prototype.toSet = function () {
|
List.prototype.toSet = function () {
|
||||||
var e_14, _a;
|
var e_15, _a;
|
||||||
var result = new Set();
|
var result = new Set();
|
||||||
try {
|
try {
|
||||||
for (var _b = __values(this._elements), _c = _b.next(); !_c.done; _c = _b.next()) {
|
for (var _b = __values(this._elements), _c = _b.next(); !_c.done; _c = _b.next()) {
|
||||||
@@ -10803,12 +11116,12 @@ var linq;
|
|||||||
result.add(x);
|
result.add(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
catch (e_15_1) { e_15 = { error: e_15_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
||||||
}
|
}
|
||||||
finally { if (e_14) throw e_14.error; }
|
finally { if (e_15) throw e_15.error; }
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -11057,7 +11370,7 @@ var es;
|
|||||||
* 计算可见性多边形,并返回三角形扇形的顶点(减去中心顶点)。返回的数组来自ListPool
|
* 计算可见性多边形,并返回三角形扇形的顶点(减去中心顶点)。返回的数组来自ListPool
|
||||||
*/
|
*/
|
||||||
VisibilityComputer.prototype.end = function () {
|
VisibilityComputer.prototype.end = function () {
|
||||||
var e_15, _a;
|
var e_16, _a;
|
||||||
var output = es.ListPool.obtain();
|
var output = es.ListPool.obtain();
|
||||||
this.updateSegments();
|
this.updateSegments();
|
||||||
this._endPoints.sort(this._radialComparer.compare);
|
this._endPoints.sort(this._radialComparer.compare);
|
||||||
@@ -11096,12 +11409,12 @@ var es;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_15_1) { e_15 = { error: e_15_1 }; }
|
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
||||||
}
|
}
|
||||||
finally { if (e_15) throw e_15.error; }
|
finally { if (e_16) throw e_16.error; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VisibilityComputer._openSegments.clear();
|
VisibilityComputer._openSegments.clear();
|
||||||
@@ -11217,7 +11530,7 @@ var es;
|
|||||||
* 处理片段,以便我们稍后对它们进行分类
|
* 处理片段,以便我们稍后对它们进行分类
|
||||||
*/
|
*/
|
||||||
VisibilityComputer.prototype.updateSegments = function () {
|
VisibilityComputer.prototype.updateSegments = function () {
|
||||||
var e_16, _a;
|
var e_17, _a;
|
||||||
try {
|
try {
|
||||||
for (var _b = __values(this._segments), _c = _b.next(); !_c.done; _c = _b.next()) {
|
for (var _b = __values(this._segments), _c = _b.next(); !_c.done; _c = _b.next()) {
|
||||||
var segment = _c.value;
|
var segment = _c.value;
|
||||||
@@ -11235,12 +11548,12 @@ var es;
|
|||||||
segment.p2.begin = !segment.p1.begin;
|
segment.p2.begin = !segment.p1.begin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
catch (e_17_1) { e_17 = { error: e_17_1 }; }
|
||||||
finally {
|
finally {
|
||||||
try {
|
try {
|
||||||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
||||||
}
|
}
|
||||||
finally { if (e_16) throw e_16.error; }
|
finally { if (e_17) throw e_17.error; }
|
||||||
}
|
}
|
||||||
// 如果我们有一个聚光灯,我们需要存储前两个段的角度。
|
// 如果我们有一个聚光灯,我们需要存储前两个段的角度。
|
||||||
// 这些是光斑的边界,我们将用它们来过滤它们之外的任何顶点。
|
// 这些是光斑的边界,我们将用它们来过滤它们之外的任何顶点。
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+35
-10
@@ -18,12 +18,16 @@ module es {
|
|||||||
/**
|
/**
|
||||||
* 简化对内部类的全局内容实例的访问
|
* 简化对内部类的全局内容实例的访问
|
||||||
*/
|
*/
|
||||||
public static _instance: Core;
|
private static _instance: Core;
|
||||||
/**
|
/**
|
||||||
* 用于确定是否应该使用EntitySystems
|
* 用于确定是否应该使用EntitySystems
|
||||||
*/
|
*/
|
||||||
public static entitySystemsEnabled: boolean;
|
public static entitySystemsEnabled: boolean;
|
||||||
|
/**
|
||||||
|
* 是否正在debug模式
|
||||||
|
* 仅允许在create时进行更改
|
||||||
|
*/
|
||||||
|
public readonly debug: boolean;
|
||||||
public _nextScene: Scene;
|
public _nextScene: Scene;
|
||||||
/**
|
/**
|
||||||
* 用于凝聚GraphicsDeviceReset事件
|
* 用于凝聚GraphicsDeviceReset事件
|
||||||
@@ -35,13 +39,8 @@ module es {
|
|||||||
public _globalManagers: GlobalManager[] = [];
|
public _globalManagers: GlobalManager[] = [];
|
||||||
public _coroutineManager: CoroutineManager = new CoroutineManager();
|
public _coroutineManager: CoroutineManager = new CoroutineManager();
|
||||||
public _timerManager: TimerManager = new TimerManager();
|
public _timerManager: TimerManager = new TimerManager();
|
||||||
public width: number;
|
|
||||||
public height: number;
|
|
||||||
|
|
||||||
constructor(width: number, height: number, enableEntitySystems: boolean = true) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
|
|
||||||
|
private constructor(debug: boolean = true, enableEntitySystems: boolean = true) {
|
||||||
Core._instance = this;
|
Core._instance = this;
|
||||||
Core.emitter = new Emitter<CoreEvents>();
|
Core.emitter = new Emitter<CoreEvents>();
|
||||||
Core.emitter.addObserver(CoreEvents.frameUpdated, this.update, this);
|
Core.emitter.addObserver(CoreEvents.frameUpdated, this.update, this);
|
||||||
@@ -50,6 +49,7 @@ module es {
|
|||||||
Core.registerGlobalManager(this._timerManager);
|
Core.registerGlobalManager(this._timerManager);
|
||||||
Core.entitySystemsEnabled = enableEntitySystems;
|
Core.entitySystemsEnabled = enableEntitySystems;
|
||||||
|
|
||||||
|
this.debug = debug;
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +92,16 @@ module es {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认实现创建核心
|
||||||
|
*/
|
||||||
|
public static create(debug: boolean = true): Core {
|
||||||
|
if (this._instance == null) {
|
||||||
|
this._instance = new es.Core(debug);
|
||||||
|
}
|
||||||
|
return this._instance;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加一个全局管理器对象,它的更新方法将调用场景前的每一帧。
|
* 添加一个全局管理器对象,它的更新方法将调用场景前的每一帧。
|
||||||
* @param manager
|
* @param manager
|
||||||
@@ -142,7 +152,19 @@ module es {
|
|||||||
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
|
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public startDebugUpdate() {
|
||||||
|
if (!this.debug) return;
|
||||||
|
TimeRuler.Instance.startFrame();
|
||||||
|
TimeRuler.Instance.beginMark('update', 0x00ff00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public endDebugUpdate() {
|
||||||
|
if (!this.debug) return;
|
||||||
|
TimeRuler.Instance.endMark('update');
|
||||||
|
}
|
||||||
|
|
||||||
public startDebugDraw() {
|
public startDebugDraw() {
|
||||||
|
if (!this.debug) return;
|
||||||
this._frameCounter++;
|
this._frameCounter++;
|
||||||
this._frameCounterElapsedTime += Time.deltaTime;
|
this._frameCounterElapsedTime += Time.deltaTime;
|
||||||
if (this._frameCounterElapsedTime >= 1) {
|
if (this._frameCounterElapsedTime >= 1) {
|
||||||
@@ -167,8 +189,10 @@ module es {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async update(currentTime?: number) {
|
protected async update(currentTime: number = -1) {
|
||||||
if (currentTime != null) Time.update(currentTime);
|
this.startDebugUpdate();
|
||||||
|
|
||||||
|
Time.update(currentTime);
|
||||||
if (this._scene != null) {
|
if (this._scene != null) {
|
||||||
for (let i = this._globalManagers.length - 1; i >= 0; i--) {
|
for (let i = this._globalManagers.length - 1; i >= 0; i--) {
|
||||||
if (this._globalManagers[i].enabled)
|
if (this._globalManagers[i].enabled)
|
||||||
@@ -188,6 +212,7 @@ module es {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.endDebugUpdate();
|
||||||
this.startDebugDraw();
|
this.startDebugDraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,15 @@ module es {
|
|||||||
public static frameCount = 0;
|
public static frameCount = 0;
|
||||||
/** 自场景加载以来的总时间 */
|
/** 自场景加载以来的总时间 */
|
||||||
public static timeSinceSceneLoad: number = 0;
|
public static timeSinceSceneLoad: number = 0;
|
||||||
private static _lastTime = 0;
|
private static _lastTime = -1;
|
||||||
|
|
||||||
public static update(currentTime: number) {
|
public static update(currentTime: number) {
|
||||||
let dt = (currentTime - this._lastTime) / 1000;
|
if (currentTime == -1)
|
||||||
|
currentTime = Date.now();
|
||||||
|
if (this._lastTime == -1)
|
||||||
|
this._lastTime = currentTime;
|
||||||
|
|
||||||
|
let dt = currentTime - this._lastTime;
|
||||||
this.totalTime += dt;
|
this.totalTime += dt;
|
||||||
this.deltaTime = dt * this.timeScale;
|
this.deltaTime = dt * this.timeScale;
|
||||||
this.unscaledDeltaTime = dt;
|
this.unscaledDeltaTime = dt;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace stopwatch {
|
namespace es {
|
||||||
/**
|
/**
|
||||||
* 记录时间的持续时间,一些设计灵感来自物理秒表。
|
* 记录时间的持续时间,一些设计灵感来自物理秒表。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,315 @@
|
|||||||
|
module es {
|
||||||
|
export class TimeRuler {
|
||||||
|
/**
|
||||||
|
* 最大条数
|
||||||
|
*/
|
||||||
|
public static readonly maxBars: number = 8;
|
||||||
|
/**
|
||||||
|
* 每条的最大样本数
|
||||||
|
*/
|
||||||
|
public static readonly maxSamples: number = 256;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static readonly maxNestCall: number = 32;
|
||||||
|
/**
|
||||||
|
* 最大显示帧数
|
||||||
|
*/
|
||||||
|
public static readonly maxSampleFrames: number = 4;
|
||||||
|
/**
|
||||||
|
* 拍摄快照的时间(以帧数为单位)
|
||||||
|
*/
|
||||||
|
public static readonly logSnapDuration: number = 120;
|
||||||
|
// 每一帧的日志
|
||||||
|
private logs: FrameLog[];
|
||||||
|
// 上一帧日志
|
||||||
|
private prevLog: FrameLog;
|
||||||
|
//目前的日志
|
||||||
|
private curLog: FrameLog;
|
||||||
|
//当前帧数
|
||||||
|
private frameCount: number = 0;
|
||||||
|
// 测量时间的秒表
|
||||||
|
private stopwatch: Stopwatch = new Stopwatch;
|
||||||
|
// 标记信息阵列
|
||||||
|
private markers: MarkerInfo[] = [];
|
||||||
|
// 从标记名称映射到标记ID的词典
|
||||||
|
private markerNameToIdMap: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
public enabled: boolean = true;
|
||||||
|
private static _instance: TimeRuler;
|
||||||
|
|
||||||
|
public static get Instance(): TimeRuler {
|
||||||
|
if (!this._instance)
|
||||||
|
this._instance = new TimeRuler();
|
||||||
|
|
||||||
|
return this._instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 你想在Game.Update方法的开头调用StartFrame。
|
||||||
|
* 但是当游戏在固定时间步长模式下运行缓慢时,Game.Update会被多次调用。
|
||||||
|
* 在这种情况下,我们应该忽略StartFrame的调用,为了做到这一点,我们只需要跟踪StartFrame的调用次数
|
||||||
|
*/
|
||||||
|
private updateCount: number = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.logs = new Array(2);
|
||||||
|
for (let i = 0; i < this.logs.length; ++i)
|
||||||
|
this.logs[i] = new FrameLog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public startFrame() {
|
||||||
|
if (!Core.Instance.debug) return;
|
||||||
|
// 当这个方法被多次调用时,我们跳过复位帧
|
||||||
|
let count = this.updateCount++;
|
||||||
|
if (this.enabled && (1 < count && count < TimeRuler.maxSampleFrames))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 更新当前帧记录
|
||||||
|
this.prevLog = this.logs[this.frameCount++ & 0x1];
|
||||||
|
this.curLog = this.logs[this.frameCount & 0x1];
|
||||||
|
|
||||||
|
let endFrameTime = this.stopwatch.getTime();
|
||||||
|
|
||||||
|
// 更新标记并创建日志
|
||||||
|
for (let barIdx = 0; barIdx < this.prevLog.bars.length; ++barIdx) {
|
||||||
|
let prevBar = this.prevLog.bars[barIdx];
|
||||||
|
let nextBar = this.curLog.bars[barIdx];
|
||||||
|
|
||||||
|
// 重新打开前一帧中没有被调用的EndMark的标记
|
||||||
|
for (let nest = 0; nest < prevBar.nestCount; ++nest) {
|
||||||
|
let markerIdx = prevBar.markerNests[nest];
|
||||||
|
|
||||||
|
prevBar.markers[markerIdx].endTime = endFrameTime;
|
||||||
|
|
||||||
|
nextBar.markerNests[nest] = nest;
|
||||||
|
nextBar.markers[nest].markerId = prevBar.markers[markerIdx].markerId;
|
||||||
|
nextBar.markers[nest].beginTime = 0;
|
||||||
|
nextBar.markers[nest].endTime = -1;
|
||||||
|
nextBar.markers[nest].color = prevBar.markers[markerIdx].color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新标记记录
|
||||||
|
for (let markerIdx = 0; markerIdx < prevBar.markCount; ++markerIdx) {
|
||||||
|
let duration = prevBar.markers[markerIdx].endTime - prevBar.markers[markerIdx].beginTime;
|
||||||
|
let markerId = prevBar.markers[markerIdx].markerId;
|
||||||
|
let m = this.markers[markerId];
|
||||||
|
|
||||||
|
m.logs[barIdx].color = prevBar.markers[markerIdx].color;
|
||||||
|
|
||||||
|
if (!m.logs[barIdx].initialized) {
|
||||||
|
// 第一帧流程
|
||||||
|
m.logs[barIdx].min = duration;
|
||||||
|
m.logs[barIdx].max = duration;
|
||||||
|
m.logs[barIdx].avg = duration;
|
||||||
|
|
||||||
|
m.logs[barIdx].initialized = true;
|
||||||
|
} else {
|
||||||
|
// 第一帧后处理
|
||||||
|
m.logs[barIdx].min = Math.min(m.logs[barIdx].min, duration);
|
||||||
|
m.logs[barIdx].max = Math.min(m.logs[barIdx].max, duration);
|
||||||
|
m.logs[barIdx].avg += duration;
|
||||||
|
m.logs[barIdx].avg *= 0.5;
|
||||||
|
|
||||||
|
if (m.logs[barIdx].samples++ >= TimeRuler.logSnapDuration) {
|
||||||
|
m.logs[barIdx].snapMin = m.logs[barIdx].min;
|
||||||
|
m.logs[barIdx].snapMax = m.logs[barIdx].max;
|
||||||
|
m.logs[barIdx].snapAvg = m.logs[barIdx].avg;
|
||||||
|
m.logs[barIdx].samples = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextBar.markCount = prevBar.nestCount;
|
||||||
|
nextBar.nestCount = prevBar.nestCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stopwatch.reset();
|
||||||
|
this.stopwatch.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始测量时间
|
||||||
|
* @param markerName
|
||||||
|
* @param color
|
||||||
|
* @param barIndex
|
||||||
|
*/
|
||||||
|
public beginMark(markerName: string, color: number, barIndex: number = 0) {
|
||||||
|
if (!Core.Instance.debug) return;
|
||||||
|
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
|
||||||
|
throw new Error('barIndex 越位');
|
||||||
|
|
||||||
|
let bar = this.curLog.bars[barIndex];
|
||||||
|
|
||||||
|
if (bar.markCount >= TimeRuler.maxSamples) {
|
||||||
|
throw new Error('超出样本数.\n 要么设置更大的数字为TimeRuler.MaxSmpale,要么降低样本数');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bar.nestCount >= TimeRuler.maxNestCall) {
|
||||||
|
throw new Error('nestCount超出.\n 要么将大的设置为TimeRuler.MaxNestCall,要么将小的设置为NestCall');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取已注册的标记
|
||||||
|
let markerId = this.markerNameToIdMap.get(markerName);
|
||||||
|
if (markerId == null) {
|
||||||
|
// 如果这个标记没有注册,就注册这个
|
||||||
|
markerId = this.markers.length;
|
||||||
|
this.markerNameToIdMap.set(markerName, markerId);
|
||||||
|
this.markers.push(new MarkerInfo(markerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始测量
|
||||||
|
bar.markerNests[bar.nestCount++] = bar.markCount;
|
||||||
|
|
||||||
|
// 填充标记参数
|
||||||
|
bar.markers[bar.markCount].markerId = markerId;
|
||||||
|
bar.markers[bar.markCount].color = color;
|
||||||
|
bar.markers[bar.markCount].beginTime = this.stopwatch.getTime();
|
||||||
|
|
||||||
|
bar.markers[bar.markCount].endTime = -1;
|
||||||
|
|
||||||
|
bar.markCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止测量
|
||||||
|
* @param markerName
|
||||||
|
* @param barIndex
|
||||||
|
*/
|
||||||
|
public endMark(markerName: string, barIndex: number = 0) {
|
||||||
|
if (!Core.Instance.debug) return;
|
||||||
|
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
|
||||||
|
throw new Error('barIndex 越位');
|
||||||
|
|
||||||
|
let bar = this.curLog.bars[barIndex];
|
||||||
|
|
||||||
|
if (bar.nestCount <= 0) {
|
||||||
|
throw new Error('在调用结束标记方法之前调用beginMark方法');
|
||||||
|
}
|
||||||
|
|
||||||
|
let markerId = this.markerNameToIdMap.get(markerName);
|
||||||
|
if (markerId == null) {
|
||||||
|
throw new Error(`标记${markerName}没有注册。请确认您指定的名称与BeginMark方法使用的名称相同`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let markerIdx = bar.markerNests[--bar.nestCount];
|
||||||
|
if (bar.markers[markerIdx].markerId != markerId) {
|
||||||
|
throw new Error('beginMark/endMark方法的调用顺序不正确. beginMark(A), beginMark(B), endMark(B), endMark(A).但你不能像这样叫它 beginMark(A), beginMark(B), endMark(A), endMark(B)');
|
||||||
|
}
|
||||||
|
|
||||||
|
bar.markers[markerIdx].endTime = this.stopwatch.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取给定条形指数和标记名称的平均时间
|
||||||
|
* @param barIndex
|
||||||
|
* @param markerName
|
||||||
|
*/
|
||||||
|
public getAverageTime(barIndex: number, markerName: string) {
|
||||||
|
if (barIndex < 0 || barIndex >= TimeRuler.maxBars)
|
||||||
|
throw new Error('barIndex 越位');
|
||||||
|
|
||||||
|
let result = 0;
|
||||||
|
let markerId = this.markerNameToIdMap.get(markerName);
|
||||||
|
if (markerId != null) {
|
||||||
|
result = this.markers[markerId].logs[barIndex].avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置标记记录
|
||||||
|
*/
|
||||||
|
public resetLog() {
|
||||||
|
if (!Core.Instance.debug) return;
|
||||||
|
for (let markerInfo of this.markers) {
|
||||||
|
for (let i = 0; i < markerInfo.logs.length; ++i) {
|
||||||
|
markerInfo.logs[i].initialized = false;
|
||||||
|
markerInfo.logs[i].snapMin = 0;
|
||||||
|
markerInfo.logs[i].snapMax = 0;
|
||||||
|
markerInfo.logs[i].snapAvg = 0;
|
||||||
|
|
||||||
|
markerInfo.logs[i].min = 0;
|
||||||
|
markerInfo.logs[i].max = 0;
|
||||||
|
markerInfo.logs[i].avg = 0;
|
||||||
|
|
||||||
|
markerInfo.logs[i].samples = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记信息
|
||||||
|
*/
|
||||||
|
class MarkerInfo {
|
||||||
|
// 标记的名称
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
public logs: MarkerLog[] = new Array(TimeRuler.maxBars);
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
for (let i = 0; i < TimeRuler.maxBars; ++i)
|
||||||
|
this.logs[i] = new MarkerLog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记日志信息
|
||||||
|
*/
|
||||||
|
class MarkerLog {
|
||||||
|
public snapMin: number = 0;
|
||||||
|
public snapMax: number = 0;
|
||||||
|
public snapAvg: number = 0;
|
||||||
|
public min: number = 0;
|
||||||
|
public max: number = 0;
|
||||||
|
public avg: number = 0;
|
||||||
|
public samples: number = 0;
|
||||||
|
public color: number = 0x000000;
|
||||||
|
public initialized: boolean = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帧记录信息
|
||||||
|
*/
|
||||||
|
class FrameLog {
|
||||||
|
public bars: MarkerCollection[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.bars = new Array(TimeRuler.maxBars);
|
||||||
|
for (let i = 0; i < TimeRuler.maxBars; ++i)
|
||||||
|
this.bars[i] = new MarkerCollection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收集标记
|
||||||
|
*/
|
||||||
|
class MarkerCollection {
|
||||||
|
// 标记收集
|
||||||
|
public markers: Marker[] = new Array(TimeRuler.maxSamples);
|
||||||
|
public markCount: number = 0;
|
||||||
|
|
||||||
|
public markerNests: number[] = new Array(TimeRuler.maxNestCall);
|
||||||
|
public nestCount: number = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.markerNests.fill(0);
|
||||||
|
for (let i = 0; i < TimeRuler.maxSamples; ++i)
|
||||||
|
this.markers[i] = new Marker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记结构
|
||||||
|
*/
|
||||||
|
class Marker {
|
||||||
|
public markerId: number = 0;
|
||||||
|
public beginTime: number = 0;
|
||||||
|
public endTime: number = 0;
|
||||||
|
public color: number = 0x000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"experimentalDecorators": false,
|
|
||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"pretty": true,
|
"pretty": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user