ist jetzt verfügbar! Lesen Sie über die neuen Funktionen und Fehlerbehebungen vom November.

Verbesserungen der Leistung im integrierten Terminal

3. Oktober 2017 Daniel Imms, @Tyriar

Die Rendering-Engine des integrierten Terminals wurde für die kommende Version 1.17 von Visual Studio Code komplett mit Blick auf die Leistung neu geschrieben. In dieser Version gehen wir von einem DOM-basierten Rendering-System weg und verwenden das HTML canvas-Element.

DOM-Rendering

Es ist etwas überraschend, aber das Rendern eines interaktiven Terminals war in einem System möglich, das für die Anzeige statischer Dokumente konzipiert war. Mit der Zeit stellten wir jedoch fest, dass bestimmte vom DOM bereitgestellte Funktionalitäten überschrieben werden mussten, um verschiedene Probleme zu beheben

Auswahl: Es wurde viel gegen das Auswahlsystem des DOM gearbeitet, um den Anwendungsfall des Terminals abzudecken. Da wir immer nur das renderten, was im DOM sichtbar war, konnten Sie keine mehrseitigen Inhalte auswählen, ohne die Auswahl neu zu implementieren. Das Scrollen würde auch dazu führen, dass die Auswahl verworfen wird. Um diese Probleme zu lösen, wurde eine benutzerdefinierte Auswahllogik hinzugefügt.

Fehlausgerichtete Zeichen: Da viele Monospace-Schriftarten für einige Unicode-Zeichen nicht streng Monospace sind, konnte dies zu Situationen wie der auf der rechten Seite des folgenden Bildes führen.

Characters to the right of the terminal could become misaligned when Unicode was used

Eine Problemumgehung hierfür wäre, alle Unicode-Zeichen in Spans mit fester Breite einzubinden. Dies erhöht jedoch die Zeit, die zum Rendern eines Frames benötigt wird.

Übermäßige Garbage Collection: Aufgrund der Anzahl der Elemente, die zum Rendern des Terminals benötigt wurden, musste der Garbage Collector häufig den Speicher bereinigen, was die Renderzeit oft merklich verzögerte. Ein Objektpool wurde eingerichtet, um dieses Problem zu umgehen und DOM-Elemente wiederverwenden zu können.

Leistung: Egal wie sehr wir versuchen, diese Probleme zu lösen, die Leistung wird immer durch die Obergrenze des Layout-Engines begrenzt sein.

Umgehung der Layout-Engine

In einigen Fällen konnte das Zusammensetzen von Elementen und die Durchführung eines Layouts länger dauern als ein Frame (16,6 ms) allein, was inakzeptabel ist, wenn wir im Terminal eine flüssige Bildrate von 60 Bildern pro Sekunde (FPS) aufrechterhalten wollen. Die Lösung dafür war eine neue Canvas-basierte Rendering-Engine.

Das <canvas>-HTML-Element ermöglicht das Zeichnen von Grafiken und Text mithilfe einer JavaScript-API.

Render-Ebenen

Eine Reihe von Canvas-Elementen, bekannt als "Render-Ebenen", wird verwendet, um das Rendern verschiedener Teile des Terminals zu vereinfachen.

Die aktuellen Ebenen in Reihenfolge sind

  1. Text: Hintergrundfarben und Vordergrundtext, diese Ebene ist opak.
  2. Auswahl: Auswahl mit der Maus.
  3. Link: Die Unterstreichung beim Überfahren von Links.
  4. Cursor: Der Cursor des Terminals.

Die Trennung dieser Teile in ihre eigenen kleinen Komponenten hat die Zeichenweise erheblich vereinfacht.

Nur zeichnen, was sich geändert hat

Ein wichtiger Teil des neuen Renderers ist, dass er nur das zeichnet, was sich geändert hat. Dazu wird ein schlankes internes Modell beibehalten, das die minimale Menge an Informationen über den gezeichneten Zustand einer Zelle enthält. Der Zustand wird dann verwendet, um schnell zu prüfen, wann sich eine Zelle ändern muss, bevor die aufwendigere Zeichenaktion ausgeführt wird. Bei der Text-Ebene umfasst dieses Modell einen Verweis auf das Zeichen, Textstile, Vordergrundfarbe und Hintergrundfarbe.

Dies steht im Gegensatz zur vorherigen Rendering-Engine, bei der die gesamte Zeile aus dem DOM entfernt, neu aufgebaut und wieder hinzugefügt wurde, selbst wenn sich nichts geändert hatte.

Only individual character changes are now drawn to the screen

Die grünen Rechtecke im obigen Bild zeigen die Bereiche an, die neu gezeichnet werden.

Das Texture-Atlas

Ein Texture-Atlas wird verwendet, um die Renderzeit noch weiter zu erhöhen. Dahinter verbirgt sich ein ImageBitmap, das alle ASCII-Zeichen in den gängigsten Stilen auf der Standard-Hintergrundfarbe enthält.

Beim Zeichnen dieser Textstile wird der Texture-Atlas anstelle eines regulären Aufrufs von CanvasRenderingContext2D.fillText verwendet. Da das ImageBitmap auf der GPU liegt, verbessert sich die Zeichengeschwindigkeit erheblich.

Behind the scenes an image is maintained containing the most common characters

Erzwungenes Überspringen von Frames

Aufgrund der Geschwindigkeit des Renderings im DOM war es notwendig, zusätzliche Frames zu überspringen, um dem Parser ausreichend CPU-Zeit zu verschaffen. Obwohl dies dazu führte, dass Befehle schneller als zuvor ausgeführt wurden, führte das Streaming vieler Daten durch das Terminal dazu, dass die Bildrate unter 10 FPS fiel.

Mit dem neuen Renderer wurde diese Einschränkung aufgehoben und Sie können nun bis zu 60 FPS im Terminal genießen.

60 frames per second is now possible in the terminal

Die Ergebnisse

Unsere Benchmarks haben ergeben, dass das integrierte Terminal nun **5 bis 45 Mal schneller als zuvor** rendert, je nach Situation. Selbst wenn Sie die erhöhte Reaktionsfähigkeit und Bildrate nicht bemerken, bedeutet schnelleres Rendern auch einen geringeren Akkuverbrauch! Wir hoffen, Sie genießen die Leistungsverbesserungen, sie kommen in wenigen Tagen in Version 1.17 von VS Code und sind bereits jetzt im Insiders Build zum Testen verfügbar.

Sie können auch in die ursprüngliche xterm.js Pull Request springen, der die Funktion hinzugefügt hat, für einen detaillierteren Einblick.

Viel Spaß beim Programmieren!

Daniel Imms, Mitglied des VS Code Teams @Tyriar

© . This site is unofficial and not affiliated with Microsoft.