Wird eine JavaScript-Umgebung eventuell wiederhergestellt, nachdem der [[Prototyp]] eines Objekts geändert wurde?

9

Also, ich habe die MDN Disclaimer und Warnungen gelesen , ich habe eine große Antwort gelesen zu dem Thema , aber ich möchte noch etwas wissen. Diese Frage kam tatsächlich von einer Antwort, die ich einer anderen Frage, hier , gab.

Sagen wir, ich entscheide mich für die schmutzige Tat. Etwas, das ich für den Rest meines Lebens bereuen werde. Etwas, das mich für immer beschämt und meinen Familiennamen entehrt. Ein gezieltes, bewusstes Ende von -

Okay, genug davon. Wie auch immer, hier ist es:

%Vor%

Im Grunde genommen habe ich den Prototyp von Function.prototype geändert, ein Objekt, das praktisch jeden JavaScript-Code beeinflusst, den Sie schreiben könnten. Dann änderte ich es zurück.

Ich wollte eine große Veränderung in der Prototyp-Kette veranschaulichen, die eine Menge Code beeinflussen und eine Menge Optimierungen verursachen würde, um den Bach runter zu gehen. Ich erwarte nicht, dass ich etwas ändern würde, wenn ich etwas ändere (wenn überhaupt, erwarte ich, dass es die Leistung schlechter machen würde). Ich würde gerne wissen, ob es das wollte oder nicht, aber wenn, dann war das nicht meine Absicht.

Ich möchte nur wissen, ob sich die JavaScript-Umgebung nach einer solchen Änderung wieder zu erholen beginnt und die Dinge wieder optimiert? Oder wird es einfach für immer aufgeben und alles im nicht optimierten Modus laufen lassen? Gibt es Optimierungen, die dadurch nie erreicht werden? Kann ich darauf vertrauen, dass es nach einer gewissen Zeit der Wiederherstellung in seinen regulären Zustand zurückkehrt?

Für den Kontext spreche ich über Engines wie die neueste Version von V8, nicht über den primitiven Mist, der von Dingen wie Internet Explorer verwendet wird. Ich verstehe, dass die Antwort in verschiedenen Systemen anders sein könnte, aber ich hoffe, dass es einige Gemeinsamkeiten zwischen ihnen gibt.

    
GregRos 14.02.2018, 20:05
quelle

1 Antwort

5

V8 Entwickler hier. Diese Frage hat keine einfache Antwort.

Die meisten Optimierungen werden "zurückkommen" (natürlich auf Kosten zusätzlicher CPU-Zeit). Zum Beispiel wird optimierter Code, der weggeworfen werden muss, irgendwann neu kompiliert.

Einige Optimierungen bleiben für immer deaktiviert. Zum Beispiel überspringt V8 bestimmte Checks, wenn (und solange) es weiß, dass die Prototypketten nicht mucked sind. Wenn es sieht, dass eine App die Ketten eines Prototyps verändert, spielt es von da an sicher.

Um die Dinge noch komplizierter zu machen, können und werden sich die Details im Laufe der Zeit ändern. (Deshalb ist es nicht sehr sinnvoll, hier spezifische Umstände aufzuführen, tut mir leid.)

Hintergrund:

Es gibt viele Stellen in JavaScript, wo Code eine bestimmte Sache tun könnte, nach der die JavaScript-Engine suchen muss, aber der meiste Code tut es nicht. (Nehmen wir zum Beispiel fehlende Elemente aus dem Prototyp eines Arrays: ['a', ,'c'][1] gibt fast immer undefined zurück, außer wenn jemand Array.prototype[1] = 'b' oder Object.prototype[1] = 'b' verwendet hat.) Also beim Erzeugen von optimiertem Code für Eine Funktion, die Engine muss zwischen zwei Optionen entscheiden:

(A) Überprüfen Sie immer die fragliche Sache (im Beispiel: Gehen Sie die Prototypkette des Arrays durch und prüfen Sie jeden Prototyp, um zu sehen, ob ein Element an diesem Index vorhanden ist). Angenommen, das Ausführen dieses Codes dauert 2 Zeiteinheiten.

(B) Sei optimistisch davon ausgegangen, dass Array-Prototypen keine Elemente haben, und überspringe den Check (im Beispiel: schau nicht einmal auf Prototypen, gib einfach undefined zurück). Nehmen wir an, das bringt die Ausführungszeit auf 1 Zeiteinheit (doppelt so schnell, yay!). Um jedoch korrekt zu sein, muss die Engine nun die Prototypketten aller Arrays genau im Auge behalten, und wenn irgendwelche Elemente irgendwo auftauchen, muss der gesamte auf dieser Annahme basierende Code gefunden und weggeworfen werden, was 1000 kostet Zeiteinheiten.

Angesichts dieser Abwägung macht es Sinn, dass die Engine zuerst der schnellen, aber riskanten Strategie (B) folgt, aber wenn diese auch nur einmal fehlschlägt, wechselt sie zur sichereren Strategie (A), um das zu vermeiden Risiko, die 1000-Zeiteinheitstrafe erneut zu bezahlen.

Sie können argumentieren, ob "nur einmal" die beste Schwelle ist, oder ob eine Seite 2, 3 oder noch mehr Freikarten erhalten soll, bevor Sie (B) aufgeben, aber das ändert nichts am grundsätzlichen Kompromiss.

    
jmrk 14.02.2018, 23:45
quelle