2016-06-25 15 views
0

Ich benutze V8, um einige benutzerdefinierte Javascript-Code ausführen, OnUpdate Funktion JS Welt ausgesetzt. Gesamtcode funktioniert gut, aber zur Zeit bin ich besorgt über die Leistung von unter Code - ist es erforderlich, v8::Locker für die Ausführung einer benutzerdefinierten Funktion greifen? Instruments.app zeigt hier Code viel zu viel Zeit in v8::Locker und Destruktor verbringt -Muss v8 :: Locker vor dem Aufruf von v8 :: Function :: Call abgerufen werden?

v8 profile

90 ms (in der Ausführung eigentlichen Code) vs ~ 4000ms (von Locker & ~Locker) - das absurd ist und ich glaube, ich könnte etwas falsch machen.

Also meine grundlegende Frage ist es wirklich notwendig, v8::Locker greifen, um eine v8::Function::Call auszuführen? Im aktuellen Zustand, wenn ich auf Kommentar v8::Locker ich unten Fehlermeldung:

# Fatal error in HandleScope::HandleScope 
# Entering the V8 API without proper locking in place 

-Code-Schnipsel:

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; 
} 
+1

Wenn der Code irgendeine Art von Multithreading hat, erhalten häufig locking apis hohe Nutzungsbeträge, einfach weil sie den Thread blockieren, wenn ein anderer sie hält, nicht weil sie teuer sind, sondern weil sie ihre Arbeit machen. – Yakk

+0

Yakk, I verstehe deinen Standpunkt - aber es ist nicht klar, ob das hier der Fall ist. In diesem Fall ist 'v8 :: Locker 'an jede' v8 :: Isolate'-Instanz gebunden, die mehrere parallele Code-Ausführungen mit' v8 :: Context 'erlaubt, aber ich glaube, dass ich v8 verwende - nur ein Context läuft pro Isolat. Link zum Repo - https://github.com/abhi-bit/eventing/ – Abhi

+0

Sie müssen nur v8 :: Locker Objekte erstellen und zerstören, wenn Sie tatsächlich zwischen Threads wechseln. Wenn Sie zu jeder Zeit auf das V8-Isolat von demselben Betriebssystem-Thread zugreifen, können Sie ein Locker erstellen und es für eine lange Zeit aktiv lassen. Ich denke, GetIsolate() ist immer noch ein ziemlich teurer Anruf, und Sie möchten möglicherweise das Ergebnis in einer lokalen Variablen zwischenspeichern, wenn Sie es mehrmals aufrufen. –

Antwort

0

Wenn Sie gar kein Multithreading zu tun, die Sie nie v8 :: Locker berühren müssen. Sobald du das tust, musst du es überall haben.

Ein v8 :: Locker soll mehrere v8 :: Context's vom selben v8 :: Isolate gleichzeitig stoppen.

Wenn mehrere Ausführungsthreads gleichzeitig ausgeführt werden sollen, muss jeder Kontext in einem anderen Isolat erstellt werden.