laverdet / node-fibers

Fiber/coroutine support for v8 and node.
MIT License
3.56k stars 224 forks source link

Question: Is it possible to force yield outside of a Fiber? #404

Closed tcf909 closed 5 years ago

tcf909 commented 5 years ago

First I want to thank you very much for creating and maintaining Fibers. I'm a huge fan and have been maintaining a branch (and enhancing) of syncho (a project based on Fibers) for a while.

The question I have, of which I think the answer is "no" (but I thought I would check), is:

Given the use of Fibers, can you force a fiber to yield from outside of the fiber to control bad code:

I.E.:


let badActor = Fiber(() => while(true))

setTimeout(() => badActor.yield(), 1000);
``

Any situation where this may be possible? Multiple V8 contexts etc?

thanks
laverdet commented 5 years ago

Hmm right now this isn't possible. It may be possible to add a timeout option to Fiber.run which would yield the fiber after a certain amount of time, that would be major new feature. The possibility depends on if v8's RequestInterupt function is reentrant which isn't actually documented so I would have to experiment with that. It definitely wouldn't be possible to do it with setTimeout or any other callbacks though because of the way the event loop works.

Would the built-in nodejs vm module help? It lets you run a code with a time limit, and it will terminate execution if it runs too long. You wouldn't be able to resume the terminated script though, and I'm not sure if that's important to you in this case.

tcf909 commented 5 years ago

Very interesting. I do use vm a lot for other things precompiled bye code execution etc, but found that the time out option is too rigid.

In an ideal world all I really need to do from the parent fiber is send some sort of load status incrementally and be able to pause and resume as needed. The best I can do right now is if I haven't heard in x ms consider something loaded -- which isn't working out very well because within that window other things are being stacked for execution.

I really see the opportunity for a quality of service task engine as valuable. Kind of like qos on the network but for node function execution.

I've looked at separate workers and potentially process management, but a diminishing return starts to creep in when you tackle serialization and trying to handle system level controls that weren't meant for this level of granularity.

laverdet commented 5 years ago

It seems like a really specific problem that I'm not sure is all that common, and it can probably be tackled with a different design. What I'm gathering is that you have a long-running CPU-bound task running in a nodejs process. This task is using resources that you would rather use for higher priority tasks running in the same process so you'd like to temporarily suspend it to run different things and resume it later?

SIGSTOP and SIGCONT can do what you're asking for at the process level. A different approach is to throw all your low-priority tasks in the same process and run it with a different nice value.

tcf909 commented 5 years ago

It's actually a more generic use case - multi-tenancy + customer provided code.

The long running process was just my idea of getting status out.

The actual workloads are serving random requests in a multi tenant situation. The challenge is I'm running user code for each request. Some code is good, some code is bad and it's all 100% dynamic code (constantly changing) so designing the architecture around the code is impossible.

There is a master cluster of processes that serve as the core platform. The core platform spins up child processes that serve the end user requests. Each spoke serves bits of dynamic code given by the customer (think serverless). Node is awesome at the request processing, but given the customer provided code, I need more control to manage the fiber so that if a request hits a bit of code that is tying up the event loop I can time slice better to make sure the other requests aren't starved for time.

I've tried individual v8 contexts per request, 1 request per process at a time, but the end result is always the overhead being too high to serve a high number of concurrent requests. Like 10x difference.

Basically controlling for situations where you don't control all the code being run - so any business, Enterprise or complex app could fall in to this.

On Wed, Feb 27, 2019, 6:24 PM Marcel Laverdet notifications@github.com wrote:

It seems like a really specific problem that I'm not sure is all that common, and it can probably be tackled with a different design. What I'm gathering is that you have a long-running CPU-bound task running in a nodejs process. This task is using resources that you would rather use for higher priority tasks running in the same process so you'd like to temporarily suspend it to run different things and resume it later?

SIGSTOP and SIGCONT can do what you're asking for at the process level. A different approach is to throw all your low-priority tasks in the same process and run it with a different nice value.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/laverdet/node-fibers/issues/404#issuecomment-468110861, or mute the thread https://github.com/notifications/unsubscribe-auth/ABfZI1sGJbIu2fp7Y7wAy2npSEh2VHTSks5vRz3SgaJpZM4bPQG6 .

laverdet commented 5 years ago

If you're running untrusted/unknown code my other project isolated-vm might be useful to you.

tcf909 commented 5 years ago

Very very nice. I've been using VM2 which is honestly a pain. I'll take a look now.

On Wed, Feb 27, 2019, 7:03 PM Marcel Laverdet notifications@github.com wrote:

If you're running untrusted/unknown code my other project isolated-vm https://github.com/laverdet/isolated-vm might be useful to you.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/laverdet/node-fibers/issues/404#issuecomment-468118711, or mute the thread https://github.com/notifications/unsubscribe-auth/ABfZI7NOmMqdZsrfFNIW2U1TethaPgRCks5vR0bkgaJpZM4bPQG6 .

laverdet commented 5 years ago

Also I don't know if you care but every time you comment on this via email it leaves your personal phone number publicly on the internet. I've been deleting it for you but maybe it's not a big deal.

tcf909 commented 5 years ago

Hah. Thank you. I guess it really doesn't matter, but not something I intended.

On Wed, Feb 27, 2019, 7:04 PM Marcel Laverdet notifications@github.com wrote:

Also I don't know if you care but every time you comment on this via email it leaves your personal phone number publicly on the internet. I've been deleting it for you but maybe it's not a big deal.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/laverdet/node-fibers/issues/404#issuecomment-468119017, or mute the thread https://github.com/notifications/unsubscribe-auth/ABfZIwYkqV9UIeptwg5Pyg4232792YTRks5vR0dEgaJpZM4bPQG6 .

tcf909 commented 5 years ago

Thanks for the info. I believe Isolates are what I'll end up using long term. Out of curiosity, can you use Fibers in an Isolate?

laverdet commented 5 years ago

My fibers and isolates modules aren't compatible with each other.