Я использую V8 для выполнения некоторого пользовательского кода JavaScript, выставляя OnUpdate
функционировать в мире JS. В целом код работает нормально, но в настоящее время я обеспокоен производительностью приведенного ниже кода — нужно ли его захватывать v8::Locker
для выполнения любой пользовательской функции? Instruments.app
показывает код здесь проводит слишком много времени в v8::Locker
конструктор и деструктор —
90 мс (в реальном исполнении кода) против ~ 4000 мс (по Locker
& ~Locker
) — это абсурд, и я чувствую, что могу делать что-то не так.
Итак, мой основной вопрос, действительно ли нужно схватить v8::Locker
выполнить v8::Function::Call
? В текущем состоянии, если я закомментирую v8::Locker
Я получаю сообщение об ошибке ниже:
# Fatal error in HandleScope::HandleScope
# Entering the V8 API without proper locking in place
Фрагмент кода:
int Bucket::send_doc_update_bucket(const char *msg) {
Locker locker(GetIsolate());
Isolate::Scope isolate_scope(GetIsolate());
HandleScope handle_scope(GetIsolate());
Local<Context> context = Local<Context>::New(GetIsolate(), context_);
Context::Scope context_scope(context);
TryCatch try_catch;
Local<Value> args[1];
args[0] = String::NewFromUtf8(GetIsolate(), msg);
assert(!try_catch.HasCaught());
Handle<Value> val;
if(!context->Global()->Get(context,
createUtf8String(GetIsolate(),
"OnUpdate")).ToLocal(&val) ||
!val->IsFunction()) {
return 3;
}
Handle<Function> on_doc_update = Handle<Function>::Cast(val);
on_doc_update->Call(context, context->Global(), 1, args);
if (try_catch.HasCaught()) {
//w->last_exception = ExceptionString(GetIsolate(), &try_catch);
return 2;
}
return 0;
}
Если вы не используете многопоточность, вам никогда не нужно трогать v8 :: Locker. Однако, как только вы это сделаете, это должно быть повсюду.
V8 :: Locker должен остановить одновременное выполнение нескольких v8 :: Context из одного и того же v8 :: Isolate.
Если вы хотите несколько одновременных потоков выполнения, каждый контекст должен быть создан в отдельной изоляции.
Других решений пока нет …