greenlet icon indicating copy to clipboard operation
greenlet copied to clipboard

Worker pool?

Open ronag opened this issue 6 years ago • 7 comments

Creating a new worker for every invocation can be rather slow when dispatching small tasks. How about adding a pool of workers?

ronag avatar May 18 '18 07:05 ronag

This could probably be adapted (and simplified) to suit: https://gist.github.com/developit/65a2212731f6b00a8aaa55d70c594f5c

FWIW, it's best to only invoke greenlet once per function - generally at definition time. Dynamically creating workers to do single tasks will always have a nontrivial performance overhead.

developit avatar May 29 '18 23:05 developit

Just going to clarify for folks finding this issue - Greenlet does re-use the worker thread for all calls, but only if you hoist the greenlet() definition so it's being called one time for the given async function:

// BAD: this creates a new worker every time getPage() is called:
export function getPage(url) {
  const getJson = greenlet(async url => {
    return await (await fetch(url)).json();
  });
  return getJson(url);
}
// GOOD: this uses the same worker for each call to getPage():
const getJson = greenlet(async url => {
  return await (await fetch(url)).json();
});
export function getPage(url) {
  return getJson(url);
}

developit avatar Oct 01 '19 19:10 developit

hey @developit, I wanted to offload some functions to a worker and I was thinking if this 👇 solution is good enough? (the alternative is using those postMessage thingies by hand, which I hate):

let dispatch = greenlet(async (action) => {
  switch (action.type) {
    case 'fetchGH': {
      let url = `https://api.github.com/users/${action.username}`
      let res = await fetch(url)
      let profile = await res.json()
      return profile.name
    }
    case 'sayHi': {
      return "Hi " + action.name
    }
    default: {
      throw new Error(`Unknown action ${action.type}`)
    }
  }
})

imedadel avatar Apr 23 '20 21:04 imedadel

@ImedAdel that works, yup! There's also workerize, which is basically like Greenlet but with support for "exporting" multiple methods from the worker.

developit avatar Apr 23 '20 23:04 developit

@developit I love workerize(-loader)! But it didn't play well with Next.js, so I ended up using worker-plugin (which is also by you? :o) along with comlink.

So, I guess, if anyone is trying to bundle workers in Next.js, use that combo, it works perfectly. Otherwise, stick to greenlet and/or workerize.

(you should probably mark the last 3 comments as off-topic :) )

imedadel avatar Apr 24 '20 12:04 imedadel

Oh I didn't mean the loader - there is a non-loader version of workerize that uses the same internals as Greenlet, works at runtime.

developit avatar Apr 24 '20 17:04 developit

I needed to import the AWS SDK, that's why it wasn't an option :(

PS. If anyone needs to bundle web workers in Next.js, use Parcel (microbundle had a babel-related error) to build your workers to the /public folder. Then use comlink.

Otherwise use greenlet/workerize.

imedadel avatar Apr 24 '20 18:04 imedadel