indicatorts icon indicating copy to clipboard operation
indicatorts copied to clipboard

Use worker threads to calculate every indicator individually

Open Vasile-Peste opened this issue 1 year ago • 6 comments

It would be cool to use https://nodejs.org/api/worker_threads.html To calculate every indicator in a separated thread, maybe by passing a useWorker: true option to every indicator

Regards, Vasile

Vasile-Peste avatar Jun 16 '23 01:06 Vasile-Peste

This is a great idea. I wonder how to do this in a way that it can run on both the browser and the node, meanwhile, without hopefully touching each indicator as they don't currently take any optional parameters. Is there a library that you are using that is doing this well? I can take a look at how they did the api for this to perhaps align on that common approach?

cinar avatar Jun 16 '23 01:06 cinar

Workers are available also on browsers! And the API is quite the same as in Node.js!

I have explored all GitHub public repositories up to date and didn't find anyone using such method. So it would be a great plus here!

I can help if needed, but can't do a whole PR because of lack of time and higher priorities

Regards, Vasile

Vasile-Peste avatar Jun 16 '23 01:06 Vasile-Peste

If you can perhaps make an example of what you are envisioning, I can do my best to apply to all indicators here. If there is a way we can do this without changing the method signature of the indicators but wrapping them somehow, that would be awesome actually. I'm worried about making a breaking change. I'm sure we can find a way around it.

cinar avatar Jun 16 '23 01:06 cinar

Take this issue just as a cool idea, if you don't have time or feel people don't want it, just wait for the right time to implement it, let's go:

This is the example provided in the readme

import { awesomeOscillator, } from "indicatorts";

const highs = [ 10, 20, 30, 40, ];
const lows = [ 1, 2, 3, 4, ];

const ao = awesomeOscillator(highs, lows);

To avoid breaking the API (and also multithreading should be optional) we could do as follows

import { useWorker, } from "indicatorts";

const ao = await useWorker("awesomeOscillator", ...params);

Note the async here, since we are dealing with an external thread this operations is going to be asynchronous and not block our main thread.

The implementation of useWorker would be the following (NOT TESTED yet) which should be pretty cool because it doesn't need external files

const { Worker } = require("node:worker_threads");

export function useWorker (name, ...params) {
    const workerProcess = () => {
        const { parentPort } = require("node:worker_threads");

        self.onmessage = function (message) {
            const directives = JSON.parse(message.data);
            const indicator = require("indicatorts")[directives.name];
            const result = indicator(...directives.params);

            parentPort.postMessage(JSON.stringify(result));
        };
    };

    const worker = new Worker(workerProcess.toString().substr(6), { eval: true, });

    worker.postMessage(JSON.stringify({ name, params, }));

    return new Promise((resolve) => {
        worker.on("message", (message) => {
            worker.terminate();
            resolve(JSON.parse(message));
        });
    });
}

Vasile-Peste avatar Jun 19 '23 15:06 Vasile-Peste

Would it be possible to do the following instead

useWorker(awesomeOscillator, ...params)

otherwise we loose all autocompletion

theolundqvist avatar Oct 20 '23 12:10 theolundqvist

There seems to be enough interest now on having something like this. Let me see if I can add it.

cinar avatar Oct 21 '23 22:10 cinar