Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion devel/204_29.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,30 @@
- xmake b table_performance_test
- xmake r table_performance_test

## 2026/02/24 handle_decorations循环优化
### What
- 将四层嵌套循环分解为两个双层循环
- 优化目标是降低常数项与访存开销,不改变最坏复杂度阶数
- 预计算偏移量数组
- 分离空单元格检查
- 本优化主要针对比较极端的使用场景,正常使用下优化不明显

> 复杂度说明:
> `handle_decorations` 的主成本更准确可写为 `O(n² + Σdᵢⱼ² + new_rows·new_cols)`。
> 在常见场景(装饰尺寸较小且稀疏)通常接近 `O(n²)`;在极端构造(装饰尺寸随 n 增长且密集)最坏仍可到 `O(n⁴)`。

## 2026/02/24 表格性能测试补充和调整
- 现在每次测试前都会清空缓存

## 2026/02/22 表格性能测试
## 2026/02/22 实现表格性能测试

### handle_decorations循环优化后 (2026-02-24)
| 测试项 | 中位耗时 (μs) | 归一化指标 | 备注 |
|---|---:|---|---|
| 20×20, d=11, decorations=100 | 296 | us/n²=0.74, us/n⁴=0.00185, us/(n²d²)=0.0061157 | 20×20 → 120×120(较优化前快 16.1%) |
| 30×30, d=15, decorations=225 | 1,553 | us/n²=1.72556, us/n⁴=0.00191728, us/(n²d²)=0.00766914 | 30×30 → 240×240(较优化前快 9.1%) |
| 40×40, d=21, decorations=400 | 4,693 | us/n²=2.93312, us/n⁴=0.0018332, us/(n²d²)=0.00665108 | 40×40 → 440×440(较优化前快 12.1%) |
| 50×50, d=25, decorations=625 | 9,739 | us/n²=3.8956, us/n⁴=0.00155824, us/(n²d²)=0.00623296 | 50×50 → 650×650(较优化前快 11.2%) |

### 性能测试结果 (2026-02-24)

Expand Down
68 changes: 49 additions & 19 deletions src/Typeset/Table/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* MODULE : table.cpp
* DESCRIPTION: Tables and cells of tables
* COPYRIGHT : (C) 1999 Joris van der Hoeven
* 2026 Yuki Lu
*******************************************************************************
* This software falls under the GNU general public license version 3 or later.
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
Expand Down Expand Up @@ -348,6 +349,18 @@ table_rep::handle_decorations () {
for (j= 0, jj= 0; j < nr_cols; jj+= ex_j1[j] + ex_j2[j] + 1, j++)
off_j[j]= jj;

// Precompute row and column bases for faster access
array<int> row_base (nr_rows), row_end (nr_rows);
array<int> col_base (nr_cols), col_end (nr_cols);
for (i= 0; i < nr_rows; i++) {
row_base[i]= off_i[i] + ex_i1[i];
row_end[i] = row_base[i] + 1;
}
for (j= 0; j < nr_cols; j++) {
col_base[j]= off_j[j] + ex_j1[j];
col_end[j] = col_base[j] + 1;
}

/*** compute decorated table ***/
cell** U;
int new_rows= nr_rows, new_cols= nr_cols;
Expand All @@ -359,28 +372,45 @@ table_rep::handle_decorations () {
for (i= 0; i < new_rows; i++)
U[i]= tm_new_array<cell> (new_cols);

for (i= 0; i < nr_rows; i++)
// Step 1: Copy all decorations first
for (i= 0; i < nr_rows; i++) {
for (j= 0; j < nr_cols; j++) {
cell C= T[i][j];
if (!is_nil (C)) {
if ((!is_nil (C->D)) && (C->D->status == 1)) {
for (di= 0; di < C->D->nr_rows; di++)
for (dj= 0; dj < C->D->nr_cols; dj++) {
ii = di + off_i[i] + ex_i1[i] - C->D->i0;
jj = dj + off_j[j] + ex_j1[j] - C->D->j0;
U[ii][jj]= C->D->T[di][dj];
}
C->D= table ();
if (is_nil (C)) continue;
if (is_nil (C->D)) continue;
if (C->D->status != 1) continue;

table dec = C->D;
int base_i= row_base[i] - dec->i0;
int base_j= col_base[j] - dec->j0;
for (di= 0; di < dec->nr_rows; di++) {
int target_i= base_i + di;
cell* src_row = dec->T[di];
cell* dst_row = U[target_i];
for (dj= 0; dj < dec->nr_cols; dj++) {
int target_j = base_j + dj;
dst_row[target_j]= src_row[dj];
}
ii = off_i[i] + ex_i1[i];
jj = off_j[j] + ex_j1[j];
U[ii][jj] = C;
ii = i + C->row_span - 1;
jj = j + C->col_span - 1;
C->row_span= off_i[ii] + ex_i1[ii] + 1 - off_i[i] - ex_i1[i];
C->col_span= off_j[jj] + ex_j1[jj] + 1 - off_j[j] - ex_j1[j];
}
C->D= table ();
}
}

// Step 2: Place all original cells and update spans
for (i= 0; i < nr_rows; i++) {
for (j= 0; j < nr_cols; j++) {
cell C= T[i][j];
if (!is_nil (C)) {
int target_i = row_base[i];
int target_j = col_base[j];
U[target_i][target_j]= C;
int end_i = i + C->row_span - 1;
int end_j = j + C->col_span - 1;
C->row_span = row_end[end_i] - row_base[i];
C->col_span = col_end[end_j] - col_base[j];
}
}
}

/*** replace old table by new one ***/
for (i= 0; i < nr_rows; i++)
Expand All @@ -389,8 +419,8 @@ table_rep::handle_decorations () {
T = U;
nr_rows= new_rows;
nr_cols= new_cols;
i0 = off_i[i0] + ex_i1[i0];
j0 = off_j[j0] + ex_j1[j0];
i0 = row_base[i0];
j0 = col_base[j0];
}

void
Expand Down