From 0cecfe61fd03f117e3d3a9c35842bde37c337477 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Sat, 19 Dec 2020 13:53:04 +0100 Subject: [PATCH] added code-documentation for the WARP/timestamp optimization --- HISTORY.md | 3 +++ snap.html | 2 +- src/threads.js | 25 ++++++++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7f897a2b..22fb65bb 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,6 +9,9 @@ * fixed a bug in hyperblocks * fixed keyboard formula entry for subtraction +### 2020-12-19 +* added code-documentation for the WARP/timestamp optimization + ### 2020-12-18 * threads: optimized scheduler, reduced system calls to Date.now(), 25 % speed-up for reporters, WARP and TURBO * threads: fixed a typo in hyperDyadic() diff --git a/snap.html b/snap.html index 3b1c75f3..46d9997a 100755 --- a/snap.html +++ b/snap.html @@ -9,7 +9,7 @@ - + diff --git a/src/threads.js b/src/threads.js index e25a9f97..e120c63c 100644 --- a/src/threads.js +++ b/src/threads.js @@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy, Map, isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, BLACK, TableFrameMorph, ColorSlotMorph, isSnapObject, newCanvas, Symbol, SVG_Costume*/ -modules.threads = '2020-December-18'; +modules.threads = '2020-December-19'; var ThreadManager; var Process; @@ -583,10 +583,10 @@ function Process(topBlock, receiver, onComplete, yieldFirst) { this.httpRequest = null; this.isPaused = false; this.pauseOffset = null; - this.currentTime = Date.now(); - this.frameCount = 0; - this.stepFrameCount = 0; - this.yieldCount = 0; + this.currentTime = Date.now(); // keeping track of time between yields + this.frameCount = 0; // only used for profiling and debugging + this.stepFrameCount = 0; // keeping track of when to keep time + this.yieldCount = 0; // only used for profiling and debugging this.exportResult = false; this.onComplete = onComplete || null; this.procedureCount = 0; @@ -626,6 +626,13 @@ Process.prototype.runStep = function (deadline) { this.readyToYield = false; this.isInterrupted = false; + // repeatedly evaluate the next context (stack frame) until + // it's time to yield. In case of WARP or infinite recursive + // reporters (or long HOFs) emergency-yield every 500 ms. + // Since looking up the current time at every stack frame puts + // an amazing strain on performance, only check the system time + // every n (=100) contexts. + // This is happens over at evaluateContext(). while (!this.readyToYield && !this.isInterrupted && this.context && (this.currentTime - this.lastYield < this.timeout) @@ -712,6 +719,14 @@ Process.prototype.pauseStep = function () { Process.prototype.evaluateContext = function () { var exp = this.context.expression; + // keep track of overall frames for profiling purposes. + // also keep track of frames inside the current atomic step. + // In order to let Snap! behave similarly on a wide range of + // differently performant hardware decide when to yield inside + // a WARPed script or an infinitely recursive reporter + // by how much time has elapsed since the last yield, but since + // looking up the system time is surprisingly costly only look it + // up every 100 frames. this.frameCount += 1; this.stepFrameCount += 1; if (this.stepFrameCount > 100) {