GithubHelp home page GithubHelp logo

jiayihu / sinergia Goto Github PK

View Code? Open in Web Editor NEW
162.0 3.0 4.0 117 KB

⚒️ Cooperative expensive tasks at 60fps via ES6 generators

Home Page: https://jiayihu.github.io/sinergia/

License: MIT License

TypeScript 26.97% JavaScript 73.03%
generators expensive-tasks requestanimationframe 60fps

sinergia's Introduction

Sinergia

npm travis

sinergia is a tiny (1KB gzipped) library to run cooperative expensive tasks without blocking the UI during the computations and keeping 60fps frame rate.

Demo

A live example is available at https://jiayihu.github.io/sinergia/, with an animated box which should remain smooth at 60fps.

There are 2 examples:

  1. Long running loop: Running an expensive function (with a 2mln iterations loop) with each item of an iterable

  2. Long merge sort: Running a common merge sort with an array of 100k items

It's possible to play with the demo locally cloning the repo and running:

cd demo # Go to demo folder
npm install # Or `yarn install`
npm start

Installation

npm install sinergia --save

Usage

The following examples use co to consume the generator functions.

In this example work runs a long loop for every item, but every 100000 iterations it interrupts and gives the control to sinergia, which will resume the execution of work when more suitable.

Execution tasks are by definition cooperative because they decide when to yield the control of the execution.

By using yield inside your work you can decide the priority of the execution. Yielding often will run the task smoothly chunk by chunk but it will complete in more time. On the other hand yielding fewer times it will complete the task sooner but it will block more the main thread. Yielding zero times is equal to running the task synchronously.

import co from 'co';
import { sinergia } from 'sinergia';

function* work() {
  const iterable = 'Absent gods.'.split('');
  let result = '';

  for (let item of iterable) {
    let x = 0;

    while (x < 2000000) {
      x = x + 1;

      // Tell sinergia when the task can be interrupted and resumed later
      if (x % 100000 === 0) yield result;
    }

    result += item; // Simple result of task
    console.log(`Result of iteration:`, result);
  }

  yield result; // Yield latest result
}

const execute = co(function* () {
  return yield* sinergia(work);
});
execute.then((result) => {
  // If the work wasn't interrupted
  if (result) console.log(`Result: ${result.value}`);
});

Abort execution

Since sinergia is just a generator, you can use the returned object to abort the execution using .return() method of generators.

The method will return { value: any } with the value of the result computed on the latest item before aborting.

import co from 'co';
import { sinergia } from 'sinergia';

function* work() {
  const iterable = 'Absent gods.'.split('');
  let result = '';

  for (let item of iterable) {
    let x = 0;

    while (x < 2000000) {
      x = x + 1;

      // Tell sinergia when the task can be interrupted and resumed later
      if (x % 100000 === 0) yield result;
    }

    result += item; // Simple result of task
    console.log(`Result of iteration:`, result);
  }

  yield result; // Yield latest result
}

let iterator;

const execute = co(function* () {
  iterator = sinergia(work);
  return yield* iterator;
});
execute.then((result) => {
  // If the work wasn't interrupted
  if (result) console.log(`Result: ${result.value}`);
});

window.setTimeout(() => {
  const result = iterator.return();
  console.log('Interrupted result', result.value);
}, 5000);

API

sinergia(work: GeneratorFunction): Generator

It runs asynchronously the work function in not blocking way. Returns the Generator object.

Browser support

sinergia requires polyfills for:

  1. Promise like es6-promise or core-js Promise. If you use babel-polyfill it's already included.

  2. requestAnimationFrame/cancelAnimationFrame. See this gist as example.

Credits

Ispiration comes largely from @LucaColonnello and @cef62.

sinergia's People

Contributors

bfred-it avatar jiayihu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sinergia's Issues

Add more examples

We should add more examples with real world use cases of expensive use cases.

Consider Web Worker usage

It could be an idea also to use Web Workers to execute the computations in parallel.

Advantages

  1. It's really in background and in a separate thread. So the task doesn't even need to yield I think and should be more efficient than requestAnimationFrame
  2. Could be simpler for the user since the task doesn't need to be a generator or to yield

Disadvantages

  1. You cannot pass object references so it requires object serialization and it could be a bottleneck
  2. Browser support starts from IE10. Not dramatic but could an issue for someone, whereas requestAnimationFrame can be polyfilled with setTimeout. We could add an option to specify how to run the tasks.
  3. Cannot be used if the computation requires access to DOM, but I don't think it's a frequent case with data manipulation.
  4. Much harder to setup. Web Workers require separate JS file whereas inline solutions seem tricky.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.