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

Task API for running background tasks in the libuv thread pool #214

Merged
merged 3 commits into from
Aug 21, 2017
Merged

Conversation

dherman
Copy link
Collaborator

@dherman dherman commented Jun 29, 2017

No description provided.

}

void complete() {
Nan::HandleScope scope;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should enter an Isolate::Scope and Context::Scope here:

v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);  // Or Nan::HandleScope
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
// ...

Store the context when the task is created because it can change.

Using v8::Isolate::GetCurrentContext() in this method is not sound because it's possible no context has been entered or it's a different one from the one that created the task.

}

v8::Local<v8::Function> callback = v8::Local<v8::Function>::New(isolate_, callback_);
callback->Call(isolate_->GetCurrentContext(), v8::Null(isolate_), 2, argv);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If try_catch.HasCaught() is true, there is still an exception pending here and you can't call into the VM. If you scope the TryCatch in curly braces, it will have been cleared.

Whether it's a good idea to catch exceptions and continue is up for debate, though.

}

~Task() {
callback_.Reset();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly necessary, ~Persistent() does that by default.

};

void execute_task(uv_work_t *request) {
Task *task = static_cast<Task*>(request->data);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, we use a container_of-like macro for that in libuv and node.js. Saves one level of pointer indirection.

@jedireza
Copy link
Contributor

Nice! When this lands... we'll really be cooking with 🔥.

A couple things that crossed my mind:

  • Should we include "async" in any of the naming so it's crystal clear that this is indeed off the main thread? Maybe docs will suffice.
  • A JavaScript test/example would be great to see.

@dherman
Copy link
Collaborator Author

dherman commented Jun 30, 2017

@bnoordhuis @jedireza Thank you both so much! I'll make sure to incorporate all your feedback before merging.

@jedireza jedireza mentioned this pull request Jul 3, 2017
Dave Herman added 2 commits July 8, 2017 15:53
- eliminate redundant resetting of `Persistent` members in destructor
- save the context (ie realm) at the time the task is created
- create an `Isolate::Scope` and `Context::Scope` on the stack before calling the callback
- scope the `TryCatch` so it clears the pending exception before calling the callback
argv[1] = v8::Undefined(isolate_);

{
v8::TryCatch trycatch(isolate_);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to always use try catch?
It can cause a big performance hit with some callback since V8 cannot jit complile the functions in the try catch stack. https://news.ycombinator.com/item?id=3797822
Perhaps a flag could be passed so there is a way to control this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refer to my note about try catch performance.
Would love to hear your thoughts about this issue

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try/catch no longer deoptimizes in recent versions of V8. But even if it did, it wouldn't matter because this is C++ code, not JS code - the performance pitfall only applied to JS functions with a try/catch statement.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry my bad,didn't notice the try catch was only before the callback, thanks for the answer. Anything I could do to help get this pull request accepted asap?
I really need async support and would gladly contribute if needed

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry my bad,didn't notice the try catch was only before the callback, thanks for the answer. Anything I could do to help get this pull request accepted asap?
I really need async support and would gladly contribute if needed

@dherman
Copy link
Collaborator Author

dherman commented Aug 21, 2017

Thanks to a bunch of debugging, we should be back in a state where this can build. Should be able to merge soon!

I'm re-running the CI builds now to see what's left to fix.

@dherman dherman merged commit 81de207 into master Aug 21, 2017
@dherman dherman deleted the task branch August 21, 2017 14:55
@dherman
Copy link
Collaborator Author

dherman commented Aug 21, 2017

AppVeyor is being very suspiciously flakey lately but I'm pretty confident the builds hanging are AppVeyor's fault since we haven't seen them happen at all on multiple machines. And there were no runtime test failures.

So once I reran the CI build a few times and got all green I felt confident enough to merge. I'll reach out to AppVeyor to see what's going wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants