From 18022e5b28134b6d5e73d7ab925bcbdc99569201 Mon Sep 17 00:00:00 2001 From: SparshithNR Date: Thu, 22 Jun 2017 13:37:26 -0700 Subject: [PATCH] https://github.com/linkedin/spaniel/issues/52: first phase of imporvement, skipped three iteration of the rFA --- src/metal/engine.ts | 19 +++++++++++++------ test/constants.js | 3 ++- test/headless/specs/intersection-observer.js | 14 +++++++------- test/headless/specs/spaniel-observer.spec.js | 4 ++-- test/headless/specs/utilities.js | 8 ++++---- .../specs/watcher/exposed-event.spec.js | 10 +++++----- .../watcher/impression-complete-event.spec.js | 11 ++++++----- .../specs/watcher/impression-event.spec.js | 7 +++---- .../specs/watcher/visible-event.spec.js | 7 ++++--- test/setup/environment.js | 2 +- 10 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/metal/engine.ts b/src/metal/engine.ts index d701057..b4ca5a7 100644 --- a/src/metal/engine.ts +++ b/src/metal/engine.ts @@ -12,10 +12,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import { EngineInterface } from './interfaces'; import W from './window-proxy'; +const NUM_SKIPPED_FRAMES = 3; + export class Engine implements EngineInterface { private reads: Array = []; private work: Array = []; private running: Boolean = false; + private skipCounter: number = NUM_SKIPPED_FRAMES + 1; scheduleRead(callback: Function) { this.reads.unshift(callback); this.run(); @@ -28,14 +31,18 @@ export class Engine implements EngineInterface { if (!this.running) { this.running = true; W.rAF(() => { - this.running = false; - for (let i = 0, rlen = this.reads.length; i < rlen; i++) { - this.reads.pop()(); - } - for (let i = 0, wlen = this.work.length; i < wlen; i++) { - this.work.pop()(); + if (this.skipCounter > NUM_SKIPPED_FRAMES) { + this.skipCounter = 0; + for (let i = 0, rlen = this.reads.length; i < rlen; i++) { + this.reads.pop()(); + } + for (let i = 0, wlen = this.work.length; i < wlen; i++) { + this.work.pop()(); + } } + this.skipCounter++; if (this.work.length > 0 || this.reads.length > 0) { + this.running = false; this.run(); } }); diff --git a/test/constants.js b/test/constants.js index 2a90438..d58fa22 100644 --- a/test/constants.js +++ b/test/constants.js @@ -4,7 +4,8 @@ const constants = { RAF_THRESHOLD : 16, SMALL: 5 }, - ITEM_TO_OBSERVE: 5 + ITEM_TO_OBSERVE: 5, + NUM_SKIPPED_FRAMES: 3 }; diff --git a/test/headless/specs/intersection-observer.js b/test/headless/specs/intersection-observer.js index 276da8a..58c9ffc 100644 --- a/test/headless/specs/intersection-observer.js +++ b/test/headless/specs/intersection-observer.js @@ -24,7 +24,7 @@ testModule('IntersectionObserver', class extends TestClass { }); observer.observe(target); }) - .wait(50) + .wait(100) .getExecution() .evaluate(function() { return window.STATE.impressions; @@ -44,7 +44,7 @@ testModule('IntersectionObserver', class extends TestClass { }); observer.observe(target); }) - .wait(50) + .wait(100) .getExecution() .evaluate(function() { return window.STATE.impressions; @@ -154,7 +154,7 @@ testModule('IntersectionObserver', class extends TestClass { }); window.observer.observe(window.target); }) - .wait(50) + .wait(100) .evaluate(function() { window.observer.unobserve(window.target); }) @@ -184,7 +184,7 @@ testModule('IntersectionObserver', class extends TestClass { window.observer.observe(target2); window.observer.observe(target3); }) - .wait(50) + .wait(100) .evaluate(function() { window.observer.disconnect(); }) @@ -214,15 +214,15 @@ testModule('IntersectionObserver', class extends TestClass { window.observer.observe(target2); window.observer.observe(target3); }) - .wait(50) + .wait(100) .evaluate(function() { window.observer.disconnect(); }) - .wait(50) + .wait(100) .evaluate(function() { window.observer.observe(document.querySelector('.tracked-item[data-id="1"]')); }) - .wait(50) + .wait(100) .scrollTo(500) .wait(50) .scrollTo(0) diff --git a/test/headless/specs/spaniel-observer.spec.js b/test/headless/specs/spaniel-observer.spec.js index 84d3d64..5213c40 100644 --- a/test/headless/specs/spaniel-observer.spec.js +++ b/test/headless/specs/spaniel-observer.spec.js @@ -50,7 +50,7 @@ testModule('SpanielObserver', class extends SpanielObserverTestClass { } ['@test observing a visible element should fire after threshold time has passed']() { return this.setupTest() - .wait(250) + .wait(300) .getExecution() .evaluate(function() { return window.STATE.impressions; @@ -64,7 +64,7 @@ testModule('SpanielObserver', class extends SpanielObserverTestClass { .evaluate(function() { window.observer.unobserve(window.target); }) - .wait(20) + .wait(100) .getExecution() .evaluate(function() { return window.STATE.impressions === 1 && window.STATE.completes === 1; diff --git a/test/headless/specs/utilities.js b/test/headless/specs/utilities.js index f22c145..b9db391 100644 --- a/test/headless/specs/utilities.js +++ b/test/headless/specs/utilities.js @@ -12,7 +12,7 @@ import { import constants from './../../constants.js'; -const { time: { RAF_THRESHOLD }, ITEM_TO_OBSERVE } = constants; +const { time: { RAF_THRESHOLD }, ITEM_TO_OBSERVE, NUM_SKIPPED_FRAMES } = constants; testModule('elementSatisfiesRatio', class extends TestClass { ['@test passes true into callback when ratio satisfied']() { @@ -79,11 +79,11 @@ testModule('Eventing', class extends TestClass { }); }) .scrollTo(10) - .wait(RAF_THRESHOLD * 3) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .scrollTo(20) - .wait(RAF_THRESHOLD * 3) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .getExecution() - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .evaluate(function() { return window.STATE.scrollEvents; }).then(function(result) { diff --git a/test/headless/specs/watcher/exposed-event.spec.js b/test/headless/specs/watcher/exposed-event.spec.js index 67f6b24..335669f 100644 --- a/test/headless/specs/watcher/exposed-event.spec.js +++ b/test/headless/specs/watcher/exposed-event.spec.js @@ -12,7 +12,7 @@ import { import constants from './../../../constants.js'; -const { time: { RAF_THRESHOLD }, ITEM_TO_OBSERVE } = constants; +const { time: { RAF_THRESHOLD }, ITEM_TO_OBSERVE, NUM_SKIPPED_FRAMES } = constants; testModule('Watcher Exposed Event', class extends WatcherTestClass { ['@test should not fire if item is not exposed']() { @@ -40,13 +40,13 @@ testModule('Watcher Exposed Event', class extends WatcherTestClass { ['@test should fire twice if moved in, out, and then back in viewport']() { return this.context.scrollTo(100) .scrollTo(140) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .scrollTo(120) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .scrollTo(0) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .scrollTo(50) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertEvent(ITEM_TO_OBSERVE, 'exposed', 2) .done(); } diff --git a/test/headless/specs/watcher/impression-complete-event.spec.js b/test/headless/specs/watcher/impression-complete-event.spec.js index 6b7fa63..8f2bce9 100644 --- a/test/headless/specs/watcher/impression-complete-event.spec.js +++ b/test/headless/specs/watcher/impression-complete-event.spec.js @@ -12,7 +12,7 @@ import { import constants from './../../../constants.js'; -const { time: { IMPRESSION_THRESHOLD, RAF_THRESHOLD }, ITEM_TO_OBSERVE } = constants; +const { time: { IMPRESSION_THRESHOLD, RAF_THRESHOLD }, ITEM_TO_OBSERVE, NUM_SKIPPED_FRAMES } = constants; testModule('Impression Complete event', class extends WatcherTestClass { ['@test should not fire if item is not exposed']() { @@ -47,6 +47,7 @@ testModule('Impression Complete event', class extends WatcherTestClass { return this.context.scrollTo(200) .wait(IMPRESSION_THRESHOLD + RAF_THRESHOLD * 4) .scrollTo(0) + .wait(RAF_THRESHOLD * 3) .assertOnce(ITEM_TO_OBSERVE, 'impression-complete') .done(); } @@ -55,7 +56,7 @@ testModule('Impression Complete event', class extends WatcherTestClass { return this.context.scrollTo(200) .wait(IMPRESSION_THRESHOLD + RAF_THRESHOLD * 4) .unwatch(ITEM_TO_OBSERVE) - .wait(RAF_THRESHOLD * 2) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertOnce(ITEM_TO_OBSERVE, 'impression-complete') .done(); } @@ -64,9 +65,9 @@ testModule('Impression Complete event', class extends WatcherTestClass { return this.context.scrollTo(150) .wait(IMPRESSION_THRESHOLD * 5) .scrollTo(0) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assert(function(e) { - return e.meta.duration >= 495 && e.meta.duration <= 545 && e.id === 5 && e.e === 'impression-complete'; + return e.meta.duration >= ((IMPRESSION_THRESHOLD * 5) - (RAF_THRESHOLD * NUM_SKIPPED_FRAMES)) && e.meta.duration <= ((IMPRESSION_THRESHOLD * 5) + (RAF_THRESHOLD * NUM_SKIPPED_FRAMES)) && e.id === 5 && e.e === 'impression-complete'; }, 1) .done(); } @@ -90,7 +91,7 @@ testModule('Impression Complete event', class extends WatcherTestClass { .scrollTo(250) .wait(IMPRESSION_THRESHOLD + RAF_THRESHOLD * 4) .scrollTo(0) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertEvent(ITEM_TO_OBSERVE, 'impression-complete', 2) .done(); } diff --git a/test/headless/specs/watcher/impression-event.spec.js b/test/headless/specs/watcher/impression-event.spec.js index e142b76..0ae3fbd 100644 --- a/test/headless/specs/watcher/impression-event.spec.js +++ b/test/headless/specs/watcher/impression-event.spec.js @@ -12,12 +12,12 @@ import { import constants from './../../../constants.js'; -const { time: { IMPRESSION_THRESHOLD, RAF_THRESHOLD, SMALL }, ITEM_TO_OBSERVE } = constants; +const { time: { IMPRESSION_THRESHOLD, RAF_THRESHOLD, SMALL }, ITEM_TO_OBSERVE, NUM_SKIPPED_FRAMES } = constants; testModule('Impression event', class extends WatcherTestClass { ['@test should not fire if item is exposed but not impressed']() { return this.context.scrollTo(50) - .wait(RAF_THRESHOLD * 2) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertOnce(ITEM_TO_OBSERVE, 'exposed') .assertNever(ITEM_TO_OBSERVE, 'impressed') .assertOnce(ITEM_TO_OBSERVE, 'exposed') @@ -34,7 +34,6 @@ testModule('Impression event', class extends WatcherTestClass { return this.context.scrollTo(150) .wait(RAF_THRESHOLD) .scrollTo(250) - .wait(RAF_THRESHOLD) .scrollTo(0) .assertNever(ITEM_TO_OBSERVE, 'impressed').done(); } @@ -66,7 +65,7 @@ testModule('Impression event', class extends WatcherTestClass { .wait(RAF_THRESHOLD) .assertNever(ITEM_TO_OBSERVE, 'impressed') .scrollTo(200) - .wait(IMPRESSION_THRESHOLD + RAF_THRESHOLD) + .wait(IMPRESSION_THRESHOLD + RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertOnce(ITEM_TO_OBSERVE, 'impressed') .done(); } diff --git a/test/headless/specs/watcher/visible-event.spec.js b/test/headless/specs/watcher/visible-event.spec.js index 3cdba9e..7fcf5ec 100644 --- a/test/headless/specs/watcher/visible-event.spec.js +++ b/test/headless/specs/watcher/visible-event.spec.js @@ -12,12 +12,12 @@ import { import constants from './../../../constants.js'; -const { time: { RAF_THRESHOLD }, ITEM_TO_OBSERVE } = constants; +const { time: { RAF_THRESHOLD }, ITEM_TO_OBSERVE, NUM_SKIPPED_FRAMES } = constants; testModule('Visible event', class extends WatcherTestClass { ['@test should not fire if item is exposed but not visible']() { return this.context.scrollTo(50) - .wait(RAF_THRESHOLD * 2) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertOnce(ITEM_TO_OBSERVE, 'exposed') .assertNever(ITEM_TO_OBSERVE, 'visible') .done(); @@ -36,6 +36,7 @@ testModule('Visible event', class extends WatcherTestClass { .scrollTo(300) .wait(RAF_THRESHOLD * 5) .scrollTo(250) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertOnce(ITEM_TO_OBSERVE, 'visible') .done(); } @@ -50,7 +51,7 @@ testModule('Visible event', class extends WatcherTestClass { .scrollTo(10) .wait(RAF_THRESHOLD * 5) .scrollTo(200) - .wait(RAF_THRESHOLD) + .wait(RAF_THRESHOLD * NUM_SKIPPED_FRAMES) .assertEvent(ITEM_TO_OBSERVE, 'visible', 2) .done(); } diff --git a/test/setup/environment.js b/test/setup/environment.js index 723e0d6..82b7d68 100644 --- a/test/setup/environment.js +++ b/test/setup/environment.js @@ -10,7 +10,7 @@ var runTest = function(threshold, options) { } options = options || {}; var thresholds = [threshold]; - var timeout = 50 + (options.timeout || 0); + var timeout = 100 + (options.timeout || 0); var entries = []; var target = options.target || document.createElement('div'); target.style.height = '10px';