Skip to content

Releases: austinksmith/Hamsters.js

Hamsters v5.6.2 Released!

24 Sep 13:54
Compare
Choose a tag to compare

This release is a minor change that enhances the functionality of Node.js with Hamsters.js, version 5.6.1 introduced custom scaffolds and response handlers which allowed for things like progress bars etc. However there was a minor limitation in the way these handlers were assigned in Node.js making them impractical for continuous message handling. This is now resolved and you can now send as many messages from your workers to your main thread in Node.js as you desire.

If you would like to see an example of progress bars being updated using Hamsters.js take a look at the 1-billion-row-challenge repo.

Hamsters v5.6.1 Released!

23 Sep 14:10
Compare
Choose a tag to compare

I'm happy to announce the release of Hamsters.js version 5.6.1 while this is a minor bump in versions its actually quite a big leap in feature improvements.

Observable

There is a new feature and class called hamsters.observable, you can use this class as an event emitter to log changes in objects you want to track inside your project, additionally this is now being used inside the library to allow for change monitoring of internal library variables to give better insights into what is taking place behind the scenes when the library is running. Please see the list below of examples on variables you can monitor.

  hamsters.pool.threads.on('change', function(threads) {
    console.log("Thread Pool Threads Changed");
  });

  hamsters.pool.running.on('change', function(runningThreads) {
    console.log("Thread Pool Running Threads Changed");
  });

  hamsters.pool.pending.on('change', function(pendingThreads) {
    console.log("Thread Pool Pending Threads Changed");
  });

  hamsters.distribute.remoteConnections.on('change', function(connections) {
    console.log("Distributed Remote Connections Changed");
  });

  hamsters.distribute.receiveChannels.on('change', function(receiveChannels) {
    console.log("Distributed P2P Receive Channels Changed");
  });

  hamsters.distribute.sendChannels.on('change', function(sendChannels) {
    console.log("Distributed P2P Send Channels Changed");
  });

  hamsters.distribute.clientInfo.on('change', function(clientInfo) {
    console.log("Distributed Connected Client Info Changed");
  });

  hamsters.distribute.pendingPromises.on('change', function(pendingPromises) {
    console.log("Distributed Pending Promises (Tasks) Changed");
  });

Scaffold

In previous releases of Hamsters.js you were confined to making use of the libraries built in web worker scaffolds, as Hamsters.js is meant to be a higher level abstraction to provide universal parallel computing support, pre-defined methods are required to preserve the use of the thread pool, however this presented some limitations in some of the workloads you can complete with Hamsters.js, one of these challenges was the 1 billion row challenge where you must parse a billion rows of sensor measurements from a txt file as fast as possible.

When attempting this in the past using Hamsters.js, there was a problem where since this is a txt file of objects I didn't have an efficient way to ensure that the workers themselves got the data from the file requiring parsing of the data on the main thread and then sending that data through a postMessage to each worker, this was a huge bottleneck resulting in a completion time using 8 threads on an 8th Gen Core i5 processor of 16 minutes and 32 seconds, surely there is a better way right?

Introducing custom scaffold support, you can now initialize Hamsters.js to use a custom scaffold that includes all the libraries you need accessable inside your threads! You will need to define a relative path, absolute path, or url to the worker file you want to use like below.

  hamsters.init({
    scaffold: 'myCustomWorker.js'
  }):

By making use of the scaffold param your threads will make use of your worker file, you can make use of the existing scaffolds the library uses as boilerplate under the src/scaffold folder and the src/common folder as well. Just remember not to remove too many of the libraries methods or you'll lose the benefits of having Hamsters.js in the first place.

Back to that billion row challenge, by using a custom scaffold and moving the file reading into the threads themselves, we can reap the benefits of Hamsters.js parallel computing and features like memoization if we desire. So the results speak for themselves, moving to version 5.6.1 and making the above changes resulted in a processing time of a mere 261.431 seconds! This beats multi-threaded python and concurrent ruby using jRuby which allows for actual parallel processing with ruby. Ruby took 695.027056 seconds, while Python took 446.83 seconds on the same machine.

Making the Hamsters.js approach 165.85% faster than Ruby, and 70.93% faster than python, overall a 279.39% improvement in performance compared to previous releases of Hamsters.js running the same challenge, if you would like to run the challenge yourself or view the source code to see how the custom scaffold was used you can view the repo here.

1-billion-row-challenge

Trainer

Similar to the above in previous versions of Hamsters.js there was no way to customize the response handler for when a thread returns a response, this is now possible by passing a trainer parameter at initialization. This enables you to create custom message handlers and implement things like progress bars and status updates into your workflow, ideal for longer running tasks.

    const hamsterTrainer = (index, task, threadId, hamster, resolve, reject) => {
      const onThreadResponse = (message) => {
        if(message.data.type === "log") { //Custom log message type from our worker thread
          console.log(`We have a log from thread id#${threadId}: ${message.data.message}`);
        } else {  // Process with Hamsters.js like normal
          this.hamsters.pool.processReturn(index, message, task);
          if (this.hamsters.habitat.debug) {
            task.scheduler.metrics.threads[threadId].completed_at = Date.now();
          }
          this.hamsters.pool.removeFromRunning(task, threadId);
          if (task.scheduler.workers.length === 0 && task.scheduler.count === task.scheduler.threads) {
            this.hamsters.pool.returnOutputAndRemoveTask(task, resolve);
          }
          if (!this.hamsters.habitat.persistence) {
            hamster.terminate();
          }
          if (this.hamsters.pool.pending.length() !== 0) {
            const queueHamster = this.hamsters.pool.fetchHamster(this.hamsters.pool.running.length());
            this.hamsters.pool.processQueuedItem(queueHamster, this.hamsters.pool.pending.shift());
          }
        }
      };
      this.hamsters.pool.setOnMessage(hamster, onThreadResponse, reject);
    }
    
    hamsters.init({
       trainer: hamsterTrainer
    });

Async

You can now make use of async await inside of your Hamsters.js functions and everything should work seamlessly as if you were using async await on the main thread. Hamsters.js will automatically detect which functions are async and make the appropriate adjustments behind the scenes.

  hamsters.run(params, async function() {
     await longRunningPromise;
  }, function(results) {
    //Do something with results
  });

Notes

This release of Hamsters.js opens up many more possibilities than in the past, I hope they are made use of and they improve your overall experience using the library, thank you for using the library and helping to make the web a more modern experience. If you enjoy Hamsters.js and want to continue to see updates like this please DONATE today.

Hamsters v5.6.0 Released!

25 Aug 14:12
Compare
Choose a tag to compare

I'm happy to announce the release of Hamsters.js version 5.6.0, this release brings a few changes to the overall project structure and upgrades many of the development dependencies the library relies on such as babel and webpack, these have been upgraded to the latest version and the library is now being minified properly when built resulting in a significantly smaller binary file size , now down to less than 30KB.

Release Notes

  • Updated dev dependencies, patching all known security vulnerabilities.
  • Restructured scaffold files for maintainability and proper support for new babel version
  • Switched test cases from using PhantomJS (now deprecated), and Firefox, to using ChromeHeadless

Warnings

  • Explicit support for ES5 is no longer provided, moving forward Hamsters.js will make use of ES6+ features for performance reasons, babel is now configured to target ES6 environments.

Hamsters.js v5.5.9 Released!

10 Aug 12:15
Compare
Choose a tag to compare

This release brings a bug fix, and lays the ground work for new distributed computing features. These features do require the use of a node.js server application that will require some sort of license to use in the future. The details are still being ironed out however you can still use the new version of Hamsters.js with the client side support for these features already baked in (subject to change in future versions). If you do not have the node.js server application setup and running and you do not pass the server relay url as a start option to the library then the distributed and networking related features are disabled and unusable.

This release also should improve performance slightly especially for Node.js.

Bug Fixes

  • Resolved potential race condition when making use of multiple threads being called using
hamsters.promise 

Improvements

  • Node.js is now making use of the new transferable logic introduced in v5.5.8
  • The transferable logic for both Node.js and Web have been updated to improve performance

Features

  • Distributed Computing! - This new feature will allow the distribution of tasks between clients, currently this is limited to using 1 thread at a time so a client can execute a function and have the work be completed on a different clients machine and the results be processed seamlessly as though the work was done on the original clients machine. Future releases will expand on this, alongside the release of the required server side application for this feature to work, the eventual goal is super computing, with a single client having access to the full computing power of every client connected to the same application.

hamstersjs_wallpaper

Hamsters.js v5.5.8 Released!

18 Jun 17:16
Compare
Choose a tag to compare

I'm happy to announce the release of version 5.5.8 of Hamsters.js, this release changes how transferable objects are handled and will now make use of transferable objects in all scenarios where a transferable data type is being sent. Previously only typed arrays were being sent using transferable objects now it can be any of the following.

   const typedArrayTypes = [
      'Int32Array', 'Uint8Array', 'Uint8ClampedArray', 'Int16Array', 
      'Uint16Array', 'Uint32Array', 'Float32Array', 'Float64Array'
    ];
    const otherTransferables = [
      'ArrayBuffer', 'MessagePort', 'ImageBitmap', 'OffscreenCanvas'
    ];

Future releases will expand on this to allow you to handle these as responses better.

Enjoy!

Hamsters v5.5.7 Released!

15 Jun 14:15
Compare
Choose a tag to compare

This release is a hotfix release and patches support for using SharedArray buffers and not also passing array in your params object.

Hamsters v5.5.6 Released!

15 Jun 13:33
Compare
Choose a tag to compare

We're happy to release version 5.5.6 of Hamsters.js, this release fixes a bug when mixedOutput: true is passed in the params object and also cleans up the library architecture a little by moving hamsters.js tasks into their own class for creation. As well as some improvements to the memoization store, now its a LRU cache with a maximum of 100 entries in the database preventing memory usage from growing infinitely.

See the list below.

Bug Fixes

  1. Fixed issues where final outputs would be erroneous when mixedOutput: true passed in params

Improvements

  1. Moved hamstersjs task creation from being a simple in memory object to being a full fledged class
  2. Memoization store is now a Least Recently Used Cache, with a max of 100 database entries

Hamsters.js Memoization

Hamsters v5.5.5 Released!

14 Jun 23:44
Compare
Choose a tag to compare

We're happy to release version 5.5.5 of Hamsters.js, this release builds fixes several issues and brings back a new feature that was part of Hamsters.js early days.

See the list below.

Bug Fixes

  1. Pool is undefined error when tasks get queued for processing
  2. In situations where the thread pool is maxed out, a new thread will not spawn
  3. Library not starting in Node.js in some instances

Features

  1. Memoization, cache the results of your Hamsters.js functions. You can read more about how to use the new memoize feature here

Hamsters.js now supports memoization

Hamsters v5.5.4 Released!

13 Jun 13:32
Compare
Choose a tag to compare

We're happy to release version 5.5.3 of Hamsters.js, this release builds upon the newly introduced support for Atomic Operations in version 5.5.3 , this is an additional performance optimization that eliminates the overhead of passing the sharedArray to each thread.

In testing this resulted in a performance improvement of between 3.15% to 8.63% , depending on the number of threads being used.

Tested running the Atomic Operations Example with a million integers, comparing v5.5.3 to v5.5.4 using an Ubuntu 22.04 LTS 64-bit test machine with a Core i5-8300H 2.3ghz 4 cores 8 threads, 16GB DDR4 2400mhz dual channel.

Additionally the README and Hamsters.js Wiki have been updated with new information on making use of Atomics!

Hamsters.js supports  even faster Atomic Operations

Hamsters v5.5.3 Released!

12 Jun 04:08
Compare
Choose a tag to compare

We're happy to release version 5.5.3 of Hamsters.js, this release brings the very long coming support for Atomic Operations, allowing us to completely eliminate the majority of thread communication overhead improving performance significantly.

Hamsters.js supports Atomic Operations

We are in the process of updating the wiki documentation for this new feature, When running the new benchmark and comparing the results to our Collatz Conjecture example without SharedArrays, and our Atomic Operations Example which uses SharedArrays && Atomic Operations, we can see performance increases in the table below. The following results were taken on a Core i5 8300H 2.3ghz 4c/8t processor, 16GB of DDR4 2400mhz dual channel, running on Ubuntu 22.04 LTS

FireFox 126.0.1 (64-bit) -

Number of Threads Time Taken (Result Set 1 - No SharedArrays) Time Taken (Result Set 2 - SharedArrays) Time Difference (ms) % Performance Increase
1 9,908ms 9,421.54ms 486.46ms 4.91%
2 5,962ms 5,302.82ms 659.18ms 11.06%
3 4,637ms 3,830.7ms 806.3ms 17.39%
4 4,302ms 4,118.26ms 183.74ms 4.27%
5 3,489ms 3,828.34ms -339.34ms -9.73%
6 3,514ms 3,576.22ms -62.22ms -1.77%
7 3,367ms 3,104.14ms 262.86ms 7.81%
8 3,302ms 3,098.24ms 203.76ms 6.17%
Average 5,060.13ms 4,660.16ms 399.97ms 8.24%

Brave v1.66.118 -

Number of Threads Time Taken (Result Set 1 - No SharedArrays) Time Taken (Result Set 2 - SharedArrays) Time Difference (ms) % Performance Increase
1 66,725ms 58,918ms 7,807ms 11.70%
2 37,278ms 32,366ms 4,912ms 13.18%
3 27,766ms 23,642ms 4,124ms 14.85%
4 23,445ms 19,418ms 4,027ms 17.18%
5 22,886ms 21,160ms 1,726ms 7.54%
6 22,344ms 19,723ms 2,621ms 11.73%
7 24,496ms 18,582ms 5,914ms 24.14%
8 22,486ms 18,965ms 3,521ms 15.66%
Average 30,928.75ms 26,471.63ms 4,457.13ms 14.50%

Enjoy!