Add Profiler events to Runtime, Sequencer and execute

This commit is contained in:
Michael "Z" Goddard 2017-11-09 17:27:49 -05:00
parent a5b55a5128
commit 516d4f6f30
No known key found for this signature in database
GPG key ID: 762CD40DD5349872
3 changed files with 154 additions and 0 deletions
src/engine

View file

@ -2,6 +2,42 @@ const Timer = require('../util/timer');
const Thread = require('./thread');
const execute = require('./execute.js');
/**
* Profiler frame name for stepping a single thread.
* @const {string}
*/
const stepThreadProfilerFrame = 'Sequencer.stepThread';
/**
* Profiler frame name for the inner loop of stepThreads.
* @const {string}
*/
const stepThreadsInnerProfilerFrame = 'Sequencer.stepThreads#inner';
/**
* Profiler frame name for execute.
* @const {string}
*/
const executeProfilerFrame = 'execute';
/**
* Profiler frame ID for stepThreadProfilerFrame.
* @type {number}
*/
let stepThreadProfilerId = -1;
/**
* Profiler frame ID for stepThreadsInnerProfilerFrame.
* @type {number}
*/
let stepThreadsInnerProfilerId = -1;
/**
* Profiler frame ID for executeProfilerFrame.
* @type {number}
*/
let executeProfilerId = -1;
class Sequencer {
constructor (runtime) {
/**
@ -47,6 +83,13 @@ class Sequencer {
numActiveThreads > 0 &&
this.timer.timeElapsed() < WORK_TIME &&
(this.runtime.turboMode || !this.runtime.redrawRequested)) {
if (this.runtime.profiler !== null) {
if (stepThreadsInnerProfilerId === -1) {
stepThreadsInnerProfilerId = this.runtime.profiler.idByName(stepThreadsInnerProfilerFrame);
}
this.runtime.profiler.start(stepThreadsInnerProfilerId);
}
numActiveThreads = 0;
// Attempt to run each thread one time.
for (let i = 0; i < this.runtime.threads.length; i++) {
@ -69,7 +112,16 @@ class Sequencer {
if (activeThread.status === Thread.STATUS_RUNNING ||
activeThread.status === Thread.STATUS_YIELD) {
// Normal-mode thread: step.
if (this.runtime.profiler !== null) {
if (stepThreadProfilerId === -1) {
stepThreadProfilerId = this.runtime.profiler.idByName(stepThreadProfilerFrame);
}
this.runtime.profiler.start(stepThreadProfilerId);
}
this.stepThread(activeThread);
if (this.runtime.profiler !== null) {
this.runtime.profiler.stop();
}
activeThread.warpTimer = null;
if (activeThread.isKilled) {
i--; // if the thread is removed from the list (killed), do not increase index
@ -82,6 +134,10 @@ class Sequencer {
// We successfully ticked once. Prevents running STATUS_YIELD_TICK
// threads on the next tick.
ranFirstTick = true;
if (this.runtime.profiler !== null) {
this.runtime.profiler.stop();
}
}
// Filter inactive threads from `this.runtime.threads`.
numActiveThreads = 0;
@ -129,7 +185,23 @@ class Sequencer {
// Execute the current block.
// Save the current block ID to notice if we did control flow.
currentBlockId = thread.peekStack();
if (this.runtime.profiler !== null) {
if (executeProfilerId === -1) {
executeProfilerId = this.runtime.profiler.idByName(executeProfilerFrame);
}
// The method commented below has its code inlined underneath to
// reduce the bias recorded for the profiler's calls in this
// time sensitive stepThread method.
//
// this.runtime.profiler.start(executeProfilerId, null);
this.runtime.profiler.records.push(
this.runtime.profiler.START, executeProfilerId, null, performance.now());
}
execute(this, thread);
if (this.runtime.profiler !== null) {
// this.runtime.profiler.stop();
this.runtime.profiler.records.push(this.runtime.profiler.STOP, performance.now());
}
thread.blockGlowInFrame = currentBlockId;
// If the thread has yielded or is waiting, yield to other threads.
if (thread.status === Thread.STATUS_YIELD) {