Pārlūkot izejas kodu

🚀 performance improvement

xuty 5 gadi atpakaļ
vecāks
revīzija
b43c71212d

+ 12 - 12
lib/buffer/buffer.dart

@@ -54,7 +54,7 @@ class Buffer {
     final cell = line.getCell(_cursorX);
     cell.setCodePoint(codePoint);
     cell.setWidth(cellWidth);
-    cell.setAttr(terminal.cellAttr.copy());
+    cell.setAttr(terminal.cellAttr.value);
 
     if (_cursorX < terminal.viewWidth) {
       _cursorX++;
@@ -141,7 +141,7 @@ class Buffer {
     eraseLineFromCursor();
 
     for (var i = _cursorY + 1; i < terminal.viewHeight; i++) {
-      getViewLine(i).erase(terminal.cellAttr.copy(), 0, terminal.viewWidth);
+      getViewLine(i).erase(terminal.cellAttr.value, 0, terminal.viewWidth);
     }
   }
 
@@ -149,36 +149,36 @@ class Buffer {
     eraseLineToCursor();
 
     for (var i = 0; i < _cursorY; i++) {
-      getViewLine(i).erase(terminal.cellAttr.copy(), 0, terminal.viewWidth);
+      getViewLine(i).erase(terminal.cellAttr.value, 0, terminal.viewWidth);
     }
   }
 
   void eraseDisplay() {
     for (var i = 0; i < terminal.viewHeight; i++) {
       final line = getViewLine(i);
-      line.erase(terminal.cellAttr.copy(), 0, terminal.viewWidth);
+      line.erase(terminal.cellAttr.value, 0, terminal.viewWidth);
     }
   }
 
   void eraseLineFromCursor() {
-    currentLine.erase(terminal.cellAttr.copy(), _cursorX, terminal.viewWidth);
+    currentLine.erase(terminal.cellAttr.value, _cursorX, terminal.viewWidth);
   }
 
   void eraseLineToCursor() {
-    currentLine.erase(terminal.cellAttr.copy(), 0, _cursorX);
+    currentLine.erase(terminal.cellAttr.value, 0, _cursorX);
   }
 
   void eraseLine() {
-    currentLine.erase(terminal.cellAttr.copy(), 0, terminal.viewWidth);
+    currentLine.erase(terminal.cellAttr.value, 0, terminal.viewWidth);
   }
 
   void eraseCharacters(int count) {
     final start = _cursorX;
     for (var i = start; i < start + count; i++) {
       if (i >= currentLine.length) {
-        currentLine.add(Cell(attr: terminal.cellAttr.copy()));
+        currentLine.add(Cell(attr: terminal.cellAttr.value));
       } else {
-        currentLine.getCell(i).erase(terminal.cellAttr.copy());
+        currentLine.getCell(i).erase(terminal.cellAttr.value);
       }
     }
   }
@@ -330,7 +330,7 @@ class Buffer {
   }
 
   void saveCursor() {
-    _savedCellAttr = terminal.cellAttr.copy();
+    _savedCellAttr = terminal.cellAttr.value;
     _savedCursorX = _cursorX;
     _savedCursorY = _cursorY;
     charset.save();
@@ -338,7 +338,7 @@ class Buffer {
 
   void restoreCursor() {
     if (_savedCellAttr != null) {
-      terminal.cellAttr = _savedCellAttr.copy();
+      terminal.cellAttr.use(_savedCellAttr);
     }
 
     if (_savedCursorX != null) {
@@ -394,7 +394,7 @@ class Buffer {
 
   void insertBlankCharacters(int count) {
     for (var i = 0; i < count; i++) {
-      final cell = Cell(attr: terminal.cellAttr.copy());
+      final cell = Cell(attr: terminal.cellAttr.value);
       currentLine.insert(_cursorX + i, cell);
     }
   }

+ 78 - 51
lib/buffer/cell_attr.dart

@@ -1,9 +1,10 @@
 import 'package:meta/meta.dart';
 import 'package:xterm/buffer/cell_color.dart';
+import 'package:xterm/utli/hash_values.dart';
 
 class CellAttr {
   CellAttr({
-    @required this.fgColor,
+    this.fgColor,
     this.bgColor,
     this.bold = false,
     this.faint = false,
@@ -12,53 +13,69 @@ class CellAttr {
     this.blink = false,
     this.inverse = false,
     this.invisible = false,
-  });
-
-  CellColor fgColor;
-  CellColor bgColor;
-  bool bold;
-  bool faint;
-  bool italic;
-  bool underline;
-  bool blink;
-  bool inverse;
-  bool invisible;
-
-  CellAttr copy() {
-    return CellAttr(
-      fgColor: this.fgColor,
-      bgColor: this.bgColor,
-      bold: this.bold,
-      faint: this.faint,
-      italic: this.italic,
-      underline: this.underline,
-      blink: this.blink,
-      inverse: this.inverse,
-      invisible: this.invisible,
-    );
-  }
-
-  void reset({
-    @required fgColor,
-    bgColor,
-    bold = false,
-    faint = false,
-    italic = false,
-    underline = false,
-    blink = false,
-    inverse = false,
-    invisible = false,
-  }) {
-    this.fgColor = fgColor;
-    this.bgColor = bgColor;
-    this.bold = bold;
-    this.faint = faint;
-    this.italic = italic;
-    this.underline = underline;
-    this.blink = blink;
-    this.inverse = inverse;
-    this.invisible = invisible;
-  }
+  }) : hashCode = hashValues(
+          fgColor,
+          bgColor,
+          bold,
+          faint,
+          italic,
+          underline,
+          blink,
+          inverse,
+          invisible,
+        );
+
+  final CellColor fgColor;
+  final CellColor bgColor;
+  final bool bold;
+  final bool faint;
+  final bool italic;
+  final bool underline;
+  final bool blink;
+  final bool inverse;
+  final bool invisible;
+
+  @override
+  final int hashCode;
+
+  @override
+  bool operator ==(Object other) => other.hashCode == hashCode;
+
+  // CellAttr copy() {
+  //   return CellAttr(
+  //     fgColor: this.fgColor,
+  //     bgColor: this.bgColor,
+  //     bold: this.bold,
+  //     faint: this.faint,
+  //     italic: this.italic,
+  //     underline: this.underline,
+  //     blink: this.blink,
+  //     inverse: this.inverse,
+  //     invisible: this.invisible,
+  //   );
+  // }
+
+  // void reset({
+  //   @required fgColor,
+  //   bgColor,
+  //   bold = false,
+  //   faint = false,
+  //   italic = false,
+  //   underline = false,
+  //   blink = false,
+  //   inverse = false,
+  //   invisible = false,
+  // }) {
+  //   this.fgColor = fgColor;
+  //   this.bgColor = bgColor;
+  //   this.bold = bold;
+  //   this.faint = faint;
+  //   this.italic = italic;
+  //   this.underline = underline;
+  //   this.blink = blink;
+  //   this.inverse = inverse;
+  //   this.invisible = invisible;
+  // }
 
   CellAttr copyWith({
     CellColor fgColor,
@@ -86,8 +103,10 @@ class CellAttr {
 }
 
 class CellAttrTemplate {
-  CellAttrTemplate();
-  
+  CellAttrTemplate() {
+    reset();
+  }
+
   CellAttr _attr;
 
   set fgColor(CellColor value) {
@@ -126,5 +145,13 @@ class CellAttrTemplate {
     _attr = _attr.copyWith(invisible: value);
   }
 
-  CellAttr get value {}
+  CellAttr get value => _attr;
+
+  void reset() {
+    _attr = CellAttr();
+  }
+
+  void use(CellAttr attr) {
+    _attr = attr;
+  }
 }

+ 3 - 2
lib/frontend/terminal_view.dart

@@ -17,6 +17,7 @@ import 'package:xterm/frontend/oscillator.dart';
 import 'package:xterm/frontend/cache.dart';
 import 'package:xterm/mouse/position.dart';
 import 'package:xterm/terminal/terminal.dart';
+import 'package:xterm/utli/hash_values.dart';
 
 typedef ResizeHandler = void Function(int width, int height);
 
@@ -459,7 +460,7 @@ class TerminalPainter extends CustomPainter {
 
     final cellColor = cell.attr.inverse
         ? cell.attr.bgColor ?? terminal.colorScheme.background
-        : cell.attr.fgColor;
+        : cell.attr.fgColor ?? terminal.colorScheme.foreground;
 
     var color = Color(cellColor.value);
 
@@ -484,7 +485,7 @@ class TerminalPainter extends CustomPainter {
     );
 
     // final tp = textLayoutCache.getOrPerformLayout(span);
-    final tp = textLayoutCacheV2.getOrPerformLayout(span, cell.codePoint);
+    final tp = textLayoutCacheV2.getOrPerformLayout(span, hashValues(cell.codePoint, cell.attr));
 
     tp.paint(canvas, Offset(offsetX, offsetY));
   }

+ 1 - 1
lib/terminal/sgr.dart

@@ -20,7 +20,7 @@ void sgrHandler(CSI csi, Terminal terminal) {
       case '':
       case '0':
       case '00':
-        terminal.cellAttr.reset(fgColor: terminal.colorScheme.foreground);
+        terminal.cellAttr.reset();
         break;
       case '1':
       case '01':

+ 1 - 1
lib/terminal/terminal.dart

@@ -104,7 +104,7 @@ class Terminal with Observable {
   MouseMode get mouseMode => _mouseMode;
 
   final colorScheme = defaultColorScheme;
-  var cellAttr = CellAttr(fgColor: defaultColorScheme.foreground);
+  final cellAttr = CellAttrTemplate();
 
   final keytab = Keytab.defaultKeytab();
   final selection = Selection();

+ 97 - 0
lib/utli/hash_values.dart

@@ -0,0 +1,97 @@
+
+class _HashEnd { const _HashEnd(); }
+const _HashEnd _hashEnd = _HashEnd();
+
+class _Jenkins {
+  static int combine(int hash, Object o) {
+    assert(o is! Iterable);
+    hash = 0x1fffffff & (hash + o.hashCode);
+    hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
+    return hash ^ (hash >> 6);
+  }
+
+  static int finish(int hash) {
+    hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
+    hash = hash ^ (hash >> 11);
+    return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
+  }
+}
+
+
+int hashValues(
+  Object arg01,            Object arg02,          [ Object arg03 = _hashEnd,
+  Object arg04 = _hashEnd, Object arg05 = _hashEnd, Object arg06 = _hashEnd,
+  Object arg07 = _hashEnd, Object arg08 = _hashEnd, Object arg09 = _hashEnd,
+  Object arg10 = _hashEnd, Object arg11 = _hashEnd, Object arg12 = _hashEnd,
+  Object arg13 = _hashEnd, Object arg14 = _hashEnd, Object arg15 = _hashEnd,
+  Object arg16 = _hashEnd, Object arg17 = _hashEnd, Object arg18 = _hashEnd,
+  Object arg19 = _hashEnd, Object arg20 = _hashEnd ]) {
+  int result = 0;
+  result = _Jenkins.combine(result, arg01);
+  result = _Jenkins.combine(result, arg02);
+  if (!identical(arg03, _hashEnd)) {
+    result = _Jenkins.combine(result, arg03);
+    if (!identical(arg04, _hashEnd)) {
+      result = _Jenkins.combine(result, arg04);
+      if (!identical(arg05, _hashEnd)) {
+        result = _Jenkins.combine(result, arg05);
+        if (!identical(arg06, _hashEnd)) {
+          result = _Jenkins.combine(result, arg06);
+          if (!identical(arg07, _hashEnd)) {
+            result = _Jenkins.combine(result, arg07);
+            if (!identical(arg08, _hashEnd)) {
+              result = _Jenkins.combine(result, arg08);
+              if (!identical(arg09, _hashEnd)) {
+                result = _Jenkins.combine(result, arg09);
+                if (!identical(arg10, _hashEnd)) {
+                  result = _Jenkins.combine(result, arg10);
+                  if (!identical(arg11, _hashEnd)) {
+                    result = _Jenkins.combine(result, arg11);
+                    if (!identical(arg12, _hashEnd)) {
+                      result = _Jenkins.combine(result, arg12);
+                      if (!identical(arg13, _hashEnd)) {
+                        result = _Jenkins.combine(result, arg13);
+                        if (!identical(arg14, _hashEnd)) {
+                          result = _Jenkins.combine(result, arg14);
+                          if (!identical(arg15, _hashEnd)) {
+                            result = _Jenkins.combine(result, arg15);
+                            if (!identical(arg16, _hashEnd)) {
+                              result = _Jenkins.combine(result, arg16);
+                              if (!identical(arg17, _hashEnd)) {
+                                result = _Jenkins.combine(result, arg17);
+                                if (!identical(arg18, _hashEnd)) {
+                                  result = _Jenkins.combine(result, arg18);
+                                  if (!identical(arg19, _hashEnd)) {
+                                    result = _Jenkins.combine(result, arg19);
+                                    if (!identical(arg20, _hashEnd)) {
+                                      result = _Jenkins.combine(result, arg20);
+                                      // I can see my house from here!
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return _Jenkins.finish(result);
+}
+
+int hashList(Iterable<Object> arguments) {
+  int result = 0;
+  if (arguments != null) {
+    for (Object argument in arguments)
+      result = _Jenkins.combine(result, argument);
+  }
+  return _Jenkins.finish(result);
+}