6

Piszę funkcję porównywania ciągów stałych (dla node.js) i chciałbym wyłączyć kompilator optymalizujący V8 dla tej pojedynczej funkcji; używanie flag linii poleceń nie wchodzi w grę.Jak wyłączyć kompilator optymalizujący V8

wiem, że przy użyciu with{} (lub try/catch) blok będzie wyłączyć kompilatora teraz, ale obawiam się, że to „funkcja” (błąd) zostanie rozwiązany w przyszłych wersjach.

Czy istnieje niezmienny (i udokumentowany) sposób wyłączenia kompilatora optymalizacji V8?


przykład funkcja:

function constantTimeStringCompare(a, b) { 
    // By adding a `with` block here, we disable v8's optimizing compiler. 
    // Using Object.create(null) ensures we don't have any object prototype properties getting in our way.our way. 
    with (Object.create(null)){ 
     var valid = true, 
      length = Math.max(a.length, b.length); 
     while (length--) { 
      valid &= a.charCodeAt(length) === b.charCodeAt(length); 
     } 
     // returns true if valid == 1, false if valid == 0 
     return !!valid; 
    } 
} 

I perf test tylko dla zabawy.

+0

Porównanie czasu stałego z pętlą 'while' w nim ... ಠ_ಠ (może to nie jest prawdziwe podejście?) – Pointy

+0

... także jak" poprawny "byłby kiedykolwiek czymś innym niż boolowskim? Być może zwracam zbyt dużą uwagę na kod :) – Pointy

+0

Część "stała" odnosi się do długości łańcuchów wejściowych. Być może powinienem po prostu zwrócić false, jeśli długości nie pasują. Nie widzę problemu z pętlą 'while'. –

Odpowiedz

8

Jeśli chcesz solidny sposób, aby to zrobić, trzeba uruchomić węzeł z --allow-natives-syntax flagi i nazywają to:

%NeverOptimizeFunction(constantTimeStringCompare); 

Zauważ, że należy zgłosić to przed nazwali constantTimeStringCompare, jeśli ta funkcja jest już zoptymalizowane to narusza asercję.

W przeciwnym wypadku stwierdzenie, że dokonanie optymalizacji byłoby absolutnym szaleństwem, podczas gdy wspieranie try/catch byłoby rozsądne. Nie trzeba go mieć wpływ na swój kod choć będzie to wystarczająca:

function constantTimeStringCompare(a, b) { 
    with({}); 

    var valid = true, 
     length = Math.max(a.length, b.length); 
    while (length--) { 
     valid &= a.charCodeAt(length) === b.charCodeAt(length); 
    } 
    // returns true if valid == 1, false if valid == 0 
    return !!valid; 

} 

Tylko wspomnieć with oświadczenie psuje całą zawierający funkcję - optymalizacje są wykonywane w funkcji poziomu szczegółowości, a nie na rachunku.

+0

Używanie flag niestety nie jest opcją. Wydaje mi się, że optymalizujący kompilator V8 może zoptymalizować pustą blokadę 'with' z jednego dnia. Czy nie widzisz tej optymalizacji jako potencjalnej, jeśli nie, dlaczego? –

+0

@DavidMurdoch Nie wykonano żadnych optymalizacji, takich jak usuwanie martwego kodu, ponieważ funkcja wyłączyła optymalizacje, wymieniając 'with'. Zanim taka optymalizacja mogłaby się zdarzyć, musieliby zacząć wspierać 'with' w swoim kompilatorze optymalizacyjnym, który, jak już powiedziałem, byłby obłędem, ponieważ filozofią jest wspieranie rozsądnego kodu. 'with' jest czystym złem, a nawet błędem składni w trybie ścisłym, nie jest rozsądnym kodem, który ludzie będą śpieszyć, aby zoptymalizować. Ale najlepiej jest, jeśli nie chcesz używać flag. – Esailija

+0

'with ({});' nie działa w trybie ścisłym. – vitalets

1

Aby rzeczywiście sprawdzić, czy funkcja jest zoptymalizowana przez konkretną wersję Node.js, można zapoznać się z wiki of bluebird: Optimization Killers.
Sprawdziłem 3 rozwiązania na węźle 7.2:

  1. with({}) - Funkcja jest optymalizowany przez Turbofan
  2. try {} catch(e) {} - Funkcja jest optymalizowany przez Turbofan
  3. eval(''); - funkcja nie jest zoptymalizowana

Aby zagwarantować wyłączenie optymalizacji V8, należy dodać eval('') do treści funkcji.