From 142c6358f2f54569acf4a5ae9befc0c85c86e435 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 11 Oct 2026 00:17:49 +0300 Subject: [PATCH] perf(grid): eliminate duplicate 40-row sampling in computeResultGridColumnWidths and distributeResultGridSpareWidth --- .../workspace/grid/grid_column_sizer.dart | 28 ++++++++++++++--- .../workspace/grid/grid_view_builder.dart | 1 + .../workspace/grid/grid_view_layout.dart | 1 + lib/features/workspace/result_grid_view.dart | 1 + test/features/workspace/results_tab_test.dart | 31 +++++++++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lib/features/workspace/grid/grid_column_sizer.dart b/lib/features/workspace/grid/grid_column_sizer.dart index ea56fe3c..e7813ebe 100644 --- a/lib/features/workspace/grid/grid_column_sizer.dart +++ b/lib/features/workspace/grid/grid_column_sizer.dart @@ -81,17 +81,24 @@ class ResultGridColumnWindow { } /// Computes fixed column widths from headers and a sample of [rows]. +/// +/// When provided, [outMaxRowChars] is populated with the maximum content +/// character length for each column across the sampled rows, which can be +/// passed to [distributeResultGridSpareWidth] to eliminate redundant row +/// sampling (#1349). List computeResultGridColumnWidths({ required List columns, required List> rows, double minWidth = ResultGridMetrics.minColumnWidth, double maxWidth = ResultGridMetrics.maxColumnWidth, int sampleRowCount = ResultGridMetrics.columnWidthSampleRows, + List? outMaxRowChars, }) { if (columns.isEmpty) return const []; final widths = List.filled(columns.length, minWidth); final sample = rows.length < sampleRowCount ? rows.length : sampleRowCount; + outMaxRowChars?.clear(); for (var c = 0; c < columns.length; c++) { final headerWidth = columns[c].length * 7.5 + 38.0; @@ -101,6 +108,7 @@ List computeResultGridColumnWidths({ maxRowChars = rows[r][c].length; } } + outMaxRowChars?.add(maxRowChars); final contentWidth = maxRowChars * 7.5 + 24.0; final naturalWidth = math.max(headerWidth, contentWidth); widths[c] = naturalWidth.clamp(minWidth, maxWidth); @@ -114,6 +122,9 @@ int gridCellContextMenuItemsBuiltCount = 0; /// Distributes spare viewport width adaptively to columns that benefit from expansion, /// avoiding artificial stretching of compact columns. +/// +/// If [maxRowChars] is provided (e.g. from [computeResultGridColumnWidths]), +/// it is reused directly to avoid redundant row sampling passes (#1349). List distributeResultGridSpareWidth({ required List columnWidths, required List columns, @@ -121,6 +132,7 @@ List distributeResultGridSpareWidth({ required double availableWidth, double maxColumnWidth = ResultGridMetrics.maxColumnWidth, int sampleRowCount = ResultGridMetrics.columnWidthSampleRows, + List? maxRowChars, }) { if (columnWidths.isEmpty || columns.isEmpty) return columnWidths; @@ -130,16 +142,22 @@ List distributeResultGridSpareWidth({ final sample = rows.length < sampleRowCount ? rows.length : sampleRowCount; final desiredWidths = List.filled(columns.length, 0); + final hasPrecomputedChars = + maxRowChars != null && maxRowChars.length == columns.length; for (var c = 0; c < columns.length; c++) { final headerWidth = columns[c].length * 7.5 + 38.0; - var maxRowChars = 0; - for (var r = 0; r < sample; r++) { - if (c < rows[r].length && rows[r][c].length > maxRowChars) { - maxRowChars = rows[r][c].length; + var rowChars = 0; + if (hasPrecomputedChars) { + rowChars = maxRowChars[c]; + } else { + for (var r = 0; r < sample; r++) { + if (c < rows[r].length && rows[r][c].length > rowChars) { + rowChars = rows[r][c].length; + } } } - final contentWidth = maxRowChars * 7.5 + 24.0; + final contentWidth = rowChars * 7.5 + 24.0; desiredWidths[c] = math.max(headerWidth, contentWidth); } diff --git a/lib/features/workspace/grid/grid_view_builder.dart b/lib/features/workspace/grid/grid_view_builder.dart index 4cf6d1bc..79c03cd7 100644 --- a/lib/features/workspace/grid/grid_view_builder.dart +++ b/lib/features/workspace/grid/grid_view_builder.dart @@ -315,6 +315,7 @@ extension _GridViewBuilder on _VirtualResultGridState { availableWidth: availableWidth, maxColumnWidth: context.scaled(ResultGridMetrics.maxColumnWidth), + maxRowChars: _columnSampleMaxRowChars, ); _distributedWidths = displayWidths; _distributedForColumnWidths = _columnWidths; diff --git a/lib/features/workspace/grid/grid_view_layout.dart b/lib/features/workspace/grid/grid_view_layout.dart index 22f17cfa..a93ac688 100644 --- a/lib/features/workspace/grid/grid_view_layout.dart +++ b/lib/features/workspace/grid/grid_view_layout.dart @@ -173,6 +173,7 @@ extension _GridViewLayout on _VirtualResultGridState { rows: _baseRows, minWidth: context.scaled(ResultGridMetrics.minColumnWidth), maxWidth: context.scaled(ResultGridMetrics.maxColumnWidth), + outMaxRowChars: _columnSampleMaxRowChars, ); } diff --git a/lib/features/workspace/result_grid_view.dart b/lib/features/workspace/result_grid_view.dart index 5b01ef8a..060fb9d9 100644 --- a/lib/features/workspace/result_grid_view.dart +++ b/lib/features/workspace/result_grid_view.dart @@ -76,6 +76,7 @@ class _VirtualResultGridState extends material.State { List _columnWidths = const []; List _columnOffsets = const [0]; + final List _columnSampleMaxRowChars = []; bool _widthsNeedUpdate = true; bool _userHasResized = false; double _scrollOffset = 0; diff --git a/test/features/workspace/results_tab_test.dart b/test/features/workspace/results_tab_test.dart index b6a0df37..12bfbde5 100644 --- a/test/features/workspace/results_tab_test.dart +++ b/test/features/workspace/results_tab_test.dart @@ -143,6 +143,37 @@ void main() { ); expect(result, equals(initial)); }); + + test('reuses precomputed maxRowChars and yields identical distributed widths', () { + final columns = ['app_id', 'country', 'description']; + final rows = [ + ['292030', 'kz', 'x' * 100], + ]; + final maxRowChars = []; + final initialWidths = computeResultGridColumnWidths( + columns: columns, + rows: rows, + outMaxRowChars: maxRowChars, + ); + expect(maxRowChars, [6, 2, 100]); + + final withoutPrecomputed = distributeResultGridSpareWidth( + columnWidths: initialWidths, + columns: columns, + rows: rows, + availableWidth: 1000.0, + ); + + final withPrecomputed = distributeResultGridSpareWidth( + columnWidths: initialWidths, + columns: columns, + rows: rows, + availableWidth: 1000.0, + maxRowChars: maxRowChars, + ); + + expect(withPrecomputed, equals(withoutPrecomputed)); + }); }); group('sortResultGridRows', () {