Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Worker pool? #31

Open
ronag opened this issue May 18, 2018 · 7 comments
Open

Worker pool? #31

ronag opened this issue May 18, 2018 · 7 comments
Labels
has fix question Further information is requested

Comments

@ronag
Copy link

ronag commented May 18, 2018

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

@developit
Copy link
Owner

developit commented May 29, 2018

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 developit added the question Further information is requested label May 29, 2018
@developit
Copy link
Owner

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);
}

@imedadel
Copy link

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}`)
    }
  }
})

@developit
Copy link
Owner

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

@imedadel
Copy link

@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 :) )

@developit
Copy link
Owner

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.

@imedadel
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has fix question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants