Jelajahi Sumber

Cache the rendered cells

Previously, each time it tried to render a table (to check its width), it both re-queried the filesystem and re-formatted the values into coloured strings.

These values are now calculated only once before the table is drawn, and are used repeatedly throughout.

Although it looks as though there's more `clone()`ing going on than before, it used to be recalculating things and storing them as vectors anyway, so the memory would still be used in any case.
Ben S 10 tahun lalu
induk
melakukan
922cd2a188
3 mengubah file dengan 20 tambahan dan 11 penghapusan
  1. 1 1
      src/column.rs
  2. 6 1
      src/output/details.rs
  3. 13 9
      src/output/grid_details.rs

+ 1 - 1
src/column.rs

@@ -57,7 +57,7 @@ impl Column {
 }
 
 
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq, Debug, Clone)]
 pub struct Cell {
     pub length: usize,
     pub text: String,

+ 6 - 1
src/output/details.rs

@@ -197,9 +197,14 @@ impl<U> Table<U> where U: Users {
 
     /// Get the cells for the given file, and add the result to the table.
     pub fn add_file(&mut self, file: &File, depth: usize, last: bool, links: bool) {
+        let cells = self.cells_for_file(file);
+        self.add_file_with_cells(cells, file, depth, last, links)
+    }
+
+    pub fn add_file_with_cells(&mut self, cells: Vec<Cell>, file: &File, depth: usize, last: bool, links: bool) {
         let row = Row {
             depth:    depth,
-            cells:    self.cells_for_file(file),
+            cells:    cells,
             name:     Cell { text: filename(file, &self.colours, links), length: file.file_name_width() },
             last:     last,
             attrs:    file.xattrs.clone(),

+ 13 - 9
src/output/grid_details.rs

@@ -2,7 +2,7 @@ use std::iter::repeat;
 
 use term_grid as grid;
 
-use column::Cell;
+use column::{Column, Cell};
 use dir::Dir;
 use file::File;
 use output::details::{Details, Table};
@@ -16,10 +16,14 @@ pub struct GridDetails {
 
 impl GridDetails {
     pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
-        let mut last_working_table = self.make_grid(1, dir, files);
+        let columns_for_dir = self.details.columns.for_dir(dir);
+        let mut first_table = Table::with_options(self.details.colours, columns_for_dir.clone());
+        let cells: Vec<_> = files.iter().map(|file| first_table.cells_for_file(file)).collect();
+
+        let mut last_working_table = self.make_grid(1, &*columns_for_dir, files, cells.clone());
 
         for column_count in 2.. {
-            let grid = self.make_grid(column_count, dir, files);
+            let grid = self.make_grid(column_count, &*columns_for_dir, files, cells.clone());
 
             if grid.fit_into_columns(column_count).width() <= self.grid.console_width {
                 last_working_table = grid;
@@ -31,22 +35,22 @@ impl GridDetails {
         }
     }
 
-    pub fn make_grid(&self, column_count: usize, dir: Option<&Dir>, files: &[File]) -> grid::Grid {
+    pub fn make_grid(&self, column_count: usize, columns_for_dir: &[Column], files: &[File], cells: Vec<Vec<Cell>>) -> grid::Grid {
         let make_table = || {
-            let mut table = Table::with_options(self.details.colours, self.details.columns.for_dir(dir));
+            let mut table = Table::with_options(self.details.colours, columns_for_dir.into());
             if self.details.header { table.add_header() }
             table
         };
 
         let mut tables: Vec<_> = repeat(()).map(|_| make_table()).take(column_count).collect();
 
-        let mut height = files.len() / column_count;
-        if files.len() % column_count != 0 {
+        let mut height = cells.len() / column_count;
+        if cells.len() % column_count != 0 {
             height += 1;
         }
 
-        for (i, file) in files.iter().enumerate() {
-            tables[i / height].add_file(file, 0, false, false);
+        for (i, (file, row)) in files.iter().zip(cells.into_iter()).enumerate() {
+            tables[i / height].add_file_with_cells(row, file, 0, false, false);
         }
 
         let columns: Vec<_> = tables.iter().map(|t| t.print_table(false, false)).collect();