super-workers
Intro
Features
Installation
Flow-diagram
API
Usage
Live demo

Super Workers

Distribute load on client-side via parallelism
LIVE DEMO

Features


  • Run multipe tasks parallely without blocking the main thread.

  • Configure task(set priority, time-to-live) and Priority Task Queue Management System(PTQMS) will take care of the queue handling and execution.

  • On-demand initialization of web-workers based on task-queue size. Configure minimum and maximum number of web-workers or let library smartly decide based on hardware concurrency number.

  • Termination of idle(non-used) web-workers for better performance(can be opt-out while configuring). Set minimum number of web-workers to restrict their termination when idle, so that they remain present for future needs.

  • Fully fledged API to get all the information regarding tasks and workers at any given point of time.

  • Promise based execution of tasks i.e. perform different actions on success or failure. Useful for re-attempting failed task.

  • Define callbacks to be get triggered at various events. Eg. on successful execution of task, on exceeding the time limit of task execution, etc.

  • Exports in a UMD format i.e. library works everywhere.

Installation



Using npm

                        $ npm install super-workers
                    
                


Using yarn

                        $ yarn install super-workers
                    


Using bower

                        $ bower install super-workers
                    


Download
Download Source

                        <script type="text/javascript" src="super-workers/dist/super-workers.min.js"></script>
                    

Flow diagram

Explanation of diagram


Setting the workers configuration
Lets have the following worker configuration:
  • minimum number of workers always available to execute tasks - minWorkers = 1
  • maximum number of workers that should be spwaned irrespective of the number of tasks in the queue - maxWorkers = 3. This number will restrict registering of workers more than this number. We can not set this number randomly since it depend on the number of cores in a machine. By default, the library will pick it for you using navigator.hardwareConcurrency or it's polyfill. Setting it too high will not boost queue processing as it becomes constant after the threshold(totally depends upon the hardware configuration).

  • Task Queue Process Management
  • Initially the task queue(TQ) is empty.
  • Task T1, T2, and T3 arrive in the same order but with different priorities.
  • Task T1 is of medium priority.
  • T1 is pushed into queue and Task Queue Process Management reorders the TQ based on tasks' prioriies.
  • After proper ordering of tasks, task is ready to be executed by the web-worker tasks

  • Web worker Execution
  • Firstly, availability of workers is checked.
  • If there is no worker available, there are two cases.
    i) All workers are busy i.e. maxWorkers number has been reached, so, tasks need to be in queue for more time before they can be picked up for execution.
    ii) No worker has been spwaned yet and maxNumbers is greater than the number of spawned workers.
  • If the condition for spwaning a new worker passes, a web-worker is registered and the task is removed from the TQ and is executed.
  • Worker(s) execute(s) the task(s) and return a promise.
  • After completion of task, the process is re-run to execute next pending tasks in the TQ.

  • API

    Create an instance / reference before using.
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js'
    });
    Contructor accepts a configurable Object.
    Config keys Default Accepts
    url - path of worker script
    maxWorkers Depends on CPU cores(hardwareConcurrency) Number
    minWorkers 1 Number
    killWorkersAfterJob true Boolean
    Note: killWorkersAfterJob will kill all idle workers except one.

    Examples:

    Url of the worker script is mandatory
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js'
    });
    
    Setting maxWorkers to restrict the spawning of web-workers after a limit
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js',
        maxWorkers: 3
    });
    
    Setting minWorkers so that we always have that many web-workers always ready to work
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js',
        minWorkers: 2
    });
    
    Configuring setting so that idle workers would be terminated once they are done with thier job. One worker will remain always there even if it's idle.
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js',
        killWorkersAfterJob: true
    });
    

    Main thread Methods

    exec
    Executes a task based on the task configuration. Following types of JavaScript objects are supported:
    • Function
    • String
    Parameter Description
    function/string Function which needs to be executes(either onload or offload a method)
    params Array of params the task-function requires
    task config Setting priority, name, etc. of a task.
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js'
    });
    
    // This method is not isnide the worker-script
    // "Onloading of method
    
    function add (a, b) {
        return a + b;
    }
    
    sp.exec(add, [1,2], {
        priority: 'low',
        name: 'add-me'
    }).then(function (val) {
        console.log(val);
    }).catch(function (err) {
        console.log(err)
    });
    
    // ________my-worker.js____________
    // This method SHOULD be inside the worker-script
    // "Offloading of method"
    /* function add (a, b) {
        return a + b;
    } */
    
    // _________index.js________________
    
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js'
    });
    
    sp.exec('add', [1,2], {
        priority: 'low',
        name: 'add-me'
    }).then(function (val) {
        console.log(val);
    }).catch(function (err) {
        console.log(err)
    });
    
    getAllWorkers
    Returns the list of all the workers.
    sp.getAllWorkers();
    getActiveWorkers
    Returns the list of all active workers.
    sp.getActiveWorkers();
    getIdleWorkers
    Returns the list of all idle workers.
    sp.getIdleWorkers();
    getTerminatedWorkers
    Returns the list of all the terminated workers.
    sp.getTerminatedWorkers();
    terminateAllWorkers
    Termiates all the workers irrespective of the status.
    sp.terminateAllWorkers();
    terminateWorker
    Terminated a particular worker by passing the worker-id.
    Parameter Description
    id id of the worker to be terminated
    sp.terminateWorker('57cd47da-d98e-4a2d-814c-9b07cb51059c');
    broadCastAll
    Sends a same message to all the active workers (Message would be sent via postMessage API)
    Parameter Description
    id id of the worker to be terminated
    sp.broadCastAll('Hello my dear Child! A greeting from Parent.'});
    broadCastTo
    Sends a message to a particular active worker (Message would be sent via postMessage API)
    Parameter Description
    id id of the worker to be terminated
    msg msg to be sent
    sp.broadCastTo('57cd47da-d98e-4a2d-814c-9b07cb51059c', 'Hey! Can you run the script: worker.js? Thanks!');

    Child(Worker) thread Methods

    sendMessage
    Sends a message to Main thread.
    Parameter Description Accepts
    msg msg to be sent Object
    origin origin String
    child.sendMessage(obj, '*');
    exposeMethods
    It works as a proxy. Methods which needs to be onloaded should be exposed before they can used in main thread.
    Parameter Description Accepts
    methods list of all functions Object
    child.exposeMethods({
        add: function (a, b) {
          return a + b;
        }
      });

    Task Queue Methods

    get
    Returns the task.
    Parameter Description
    id id of the task
    sp.taskQueue.get('34cd47da-d98e-4a2d-814c-9b07cb510578');
    getAll
    Returns the list of all tasks.
    sp.getAll();
    getActive
    Returns the list of all active tasks.
    sp.getActive();
    getCompleted
    Returns the list of all completed tasks.
    sp.getCompleted();
    getFailed
    Returns the list of all the failed tasks.
    sp.getFailed();
    tasks and allTasks
    Returns tasks which are in queue.
    sp.taskQueue.tasks
    Returns all the tasks i.e. pending, queued, active and completed/failed.
    sp.taskQueue.allTasks

    Usage

    Instantiating the library with config
    Example 1: With default settings
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js'
    });
    
    Example 2: Restricting min and max number of workers manually
    // `maxWorkers` depends on CPU cores.
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js',
        maxWorkers: 3,
        minWorkers: 1
    });
    
    Example 3: Terminating workers if idle
    var sp = new SuperWorkers.MainThread({
        url: 'js/my-worker.js',
        maxWorkers: 3, // hardwareConcurrency
        minWorkers: 1,
        killWorkersAfterJob: true
    });
    
    Executing tasks
    Example 1: Execute a task defined outside of worker script(Offloading a function)
    function add(a, b) {
        return a + b;
    }
    
    sp.exec(add, [1,2], {
        priority: 'low',
        name: 'run-add'
    }).then(function (val) {
        console.log(val);
    }).catch(function (err) {
        console.log(err)
    });
    
    Example 2: Execute a task defined inside of worker script and of somewhat medium priority(Onlading a function)
    sp.exec('add', [1,2], {
        priority: 'medium',
        name: 'run-add-as-medium'
    }).then(function (val) {
        console.log(val);
    }).catch(function (err) {
        console.log(err)
    });
    
    Example 3: Execute a task with utmost(high) priority
    function fibonacci(n) {
       return n < 1 ? 0
            : n <= 2 ? 1
            : fibonacci(n - 1) + fibonacci(n - 2);
    }
    
    sp.exec(fibonacci, [5], {
        priority: 'high',
        name: 'run-fibonacci-as-soon-as'
    }).then(function (val) {
        console.log(val);
    }).catch(function (err) {
        console.log(err)
    });
    

    Live Demo

    Workers Configuration
    Input is not a number!
    Input is not a number!
    Available Tasks
    {{ task.name }} - {{ task.label }}
    of {{ task.priority }} priority
    should output {{ task.output }}.
    Please click on above tasks.
    Some points to remember:
  • Clicking a task will push it into a queue and based on the config defined above i.e. minWorkers and maxWorkers, the library will display the statistics accordingly.
  • MaxWorkers is the number which decided how many parallel workers can be spawned. Each new woker means a new CPU thread, therefore, the speed and time of task execution is in direct proportion to the machine hardware configuration.
  • Please use the maxWorkers number wisely while using this library in a real project.
  • Task Queue
    {{ task.status === 'completed' ? 'check_circle' : task.status === 'queued' ? 'queue' : task.status === 'failed' ? 'error_outline' : '' }}
    {{ task.name }}
    {{ task.name }} Name
    {{ task.priority }} Priority
    {{ task.status }} Status
    {{ task.id }} Id
    {{ task.runningOnWorkerId }} Running on worker
    Tasks Info
    Task {{task.name}} is {{ task.status }}
    Output - {{ task.output }}
    Workers Info
    {{ worker.id }} - {{ worker.status }}
    Tasks running on Workers
    Task Id: {{ task.id }}
    Name: {{ task.name }}
    Priority: {{ task.priority }}
    RunningOnWorker: {{ task.runningOnWorkerId || '...' }}
    Status: {{ task.status }}