Author: Austin K. Smith
Website: Hamsters.io
Description: 100% Vanilla Javascript Multithreading & Parallel Execution Library
License: Artistic License 2.0
- All major browsers IE9+
- Inside of existing web workers (threads inside threads)
- Javascript shell environments
- React Native
- Node.js
Obtain a copy of the library by using one of the options below,
HTML
- Download a copy of the latest release version, or clone the repo locally
- Upload the contents of the
src
directory to your server and add the script to your project as described below
<!-- HTML4 and (x)HTML -->
<script type="text/javascript" src="path/to/hamsters.js">
<!-- HTML5 -->
<script src="path/to/hamsters.js"></script>
React Native
- Download a copy of the latest relase version, or clone the repo locally
- Add the contents of the
src
directory to your project and import the library like below
import hamsters from 'path/to/hamsters';
Node.js
It's important to note that Node.js does not ship with a native worker implementation out of the box and the library will therefore make use of the legacy fallback mode in versions 4.1.0 and lower, newer versions will allow you to pass a Worker
object into the initialization options for the library to use allowing you to use any third party web worker implementation.
- Use npm to install hamsters.js
npm install --save hamsters.js
- Use npm to install webworker-threads
npm install webworker-threads
- Import Hamsters.js into your
app.js
file like below
var hamsters = require('hamsters.js');
Other Environments
You can also use bower or normal npm to install the library in other environments though support is not guaranteed, submit a ticket if you encounter problems.
Bower
bower install WebHamsters
NPM
npm install hamsters.js
Once you've downloaded and added the library to your project you should have a variable named hamsters available, this variable is the core of the library. Do not create any globally scoped variables with the same name or you will risk causing compatibility issues. Now that you've successfully added the library to your project, let's get started below.
Starting in version 4.1.0 the library will no longer automatically initialize when your application loads, in order to allow for more fine tuned control over the library operation you can now pass an optional startOptions
configuration object to control library behavior.
var startOptions = {
maxThreads: integer,
cache: boolean,
debug: booealn,
persistence: boolean
};
hamsters.init(startOptions);
At the moment only the above configuration options are available for your control, in later releases more options will be exposed.
Hamsters.js attempts to mimic exactly how you would normally make functions in JavaScript in order to make threading your functions feel as natural as possible to your everyday work flow. The library is traditionally invoked by calling a function named hamsters.run
this function takes several arguments that are paramount to making multi-threading easy on you. These arguments are described below and will be important to understand moving forward.
hamsters.run(object, function, function, integer, boolean, string, boolean, string);
- This required argument is our parameters object, this object is going to contain everything we want accessible within our execution context. Since threads are sand-boxed environments we cannot share scope with the main thread, it's important we add everything we need.
var params = {
array: [1,2,3,4,5,6,7,8,9,10],
foo: ....,
bar: ....
};
-
This required argument is going to be the function we want executed within our thread, any logic contained here will be sent to an available thread and executed there. It's important to note that in order to make things as simple as possible, the parameters object you passed previously can be accessed within this function from a internal
params
variable like sovar foo = params.bar;
. -
This required argument is going to be our callback function which will return our final output from the previous function, this function takes only one argument which is simply your result and can be accessed like so
var result = arguments[0];
. -
This optional argument will tell the library how many threads to execute the function declared previously across, this allows on a very easy level to change how many threads you are executing across. If you do not supply a value here the library defaults to a value of
1
. -
This optional argument will tell the library whether or not we want to aggregate our individual thread outputs together after execution, this is only relevant if you are executing across multiple threads and defaults to
false
. -
This optional argument will inform the library that our data array is one of JavaScript's Typed Arrays, when making use of this argument the library can make use of transferable objects which can provide a dramatic performance improvement compared to serialization. This value is
null
by default and should only be used when needed. -
This optional argument is intended to be used in conjunction with memoization mode, when memoization mode is enabled this argument allows one to control on an individual function level whether or not the results from that function are cached, this has a default value of
false
. -
This optional argument will tell the library to automatically sort our final output either alphabetically or numerically, this argument has a default value of
null
and can be configured using the sorting options.
In order to enable the library to automatically manage your data and execution across many threads there are a few conventions that were chosen that you will need to follow when making use of the library.
- When using multiple threads the library needs a consistent place to look at the data supplied to control which pieces of your input data go to which threads, to accomplish this the library expects any array that you want executed across multiple threads must have the index of
array
. Any arrays you pass inside your parameters object that does not have the index ofarray
will be copied to all threads.
var params = {
array: [1,2,3,4,5,6,7,8,9,10]
};
- Similiar to the above, the library needs a consistent way to handle outputs from threads, this is accomplished by an internal
rtn
object, inside of your function body you should pass any and all output data into thertn.data
array. You can also simply makertn.data
your output however it's recommended you simply push your output into the existingrtn.data
array as it will already match your input array type.
hamsters.run(params, function() {
rtn.data.push("Hamsters");
}, function(result) {
alert(result + " are awesome");
});
- The same parameters object mentioned above is also accessible within your execution scope with a
params
object, this object will contain everything you included.
var params = {
array: [1,2,3,4,5,6,7,8,9,10],
animal: 'Hamster'
};
hamsters.run(params, function() {
if(params.animal === 'Hamster') {
rtn.data.push("Hamsters are awesome");
}
}, function(result) {
alert(result);
});
Imagine we have a sequential function that loops through several items and performs operations on them, traditionally this would be written like below.
function() {
var array = [0,1,2,3,4,5,6,7,8,9];
var output = new Array(array.length);
array.forEach(function(item) {
output.push((item * 120)/10);
});
return output;
}
Now we can put this task onto its own thread like so
//1 thread and do not aggregate thread results (only one thread output)
function() {
var params = {
'array':[0,1,2,3,4,5,6,7,8,9]
};
hamsters.run(params, function() {
var arr = params.array;
arr.forEach(function(item) {
rtn.data.push((item * 120)/10);
});
}, function(output) {
return output;
}, 1, false);
}
Alternatively we can split this task among 2 threads for paralell execution like so
//2 threads and let's aggregate our individual thread results into one final output
function() {
var params = {'array':[0,1,2,3,4,5,6,7,8,9]};
hamsters.run(params, function() {
var arr = params.array;
arr.forEach(function(item) {
rtn.data.push((item * 120)/10);
});
}, function(output) {
return output;
}, 2, true);
}
We can even define a function to split across all available threads like so
//All threads and let's aggregate our individual thread results into one final output
function() {
var params = {'array':[0,1,2,3,4,5,6,7,8,9]};
hamsters.run(params, function() {
var arr = params.array;
arr.forEach(function(item) {
rtn.data.push((item * 120)/10);
});
}, function(output) {
return output;
}, hamsters.maxThreads, true);
}
You can find more information on how to make use of the library on the wiki links below.
Your support makes projects like this possible, please consider supporting this project by visiting our page on patreon.com!