Skip to content
Merged
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
67 changes: 67 additions & 0 deletions bench/vector-filter.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
;; vector-filter 性能基准测试
;; 测试当前实现的性能,为后续优化提供基准数据

(import (liii timeit)
(liii vector)
(scheme base)
)

;; 运行单次 benchmark
(define (bench name stmt number)
(let ((elapsed (timeit stmt '() number)))
(display name)
(display ": ")
(display elapsed)
(display " 秒 (")
(display number)
(display " 次)\n")
)
)

;; 性能测试
(define (run-benchmarks)
(display "=== vector-filter 性能测试 ===\n\n")

;; 空向量
(let ((empty #( )))
(bench "空向量 "
(lambda () (vector-filter (lambda (x) #t) empty))
100000)
)

;; 小向量 (10 元素),全部匹配
(let ((small #(1 2 3 4 5 6 7 8 9 10)))
(bench "小向量(10)全匹配"
(lambda () (vector-filter (lambda (x) #t) small))
100000)
)

;; 小向量 (10 元素),匹配一半
(let ((small #(1 2 3 4 5 6 7 8 9 10)))
(bench "小向量(10)半匹配"
(lambda () (vector-filter even? small))
100000)
)

;; 中向量 (100 元素),匹配一半
(let ((medium (list->vector (iota 100))))
(bench "中向量(100)半匹配"
(lambda () (vector-filter even? medium))
100000)
)

;; 大向量 (1000 元素),匹配一半
(let ((large (list->vector (iota 1000))))
(bench "大向量(1000)半匹配"
(lambda () (vector-filter even? large))
10000)
)

;; 超大向量 (10000 元素),匹配一半
(let ((xlarge (list->vector (iota 10000))))
(bench "超大向量(10000) "
(lambda () (vector-filter even? xlarge))
1000))
)

(run-benchmarks)
70 changes: 70 additions & 0 deletions devel/0025.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# [0025] 优化 vector-filter 性能(perf/033)

## 任务相关的代码文件
- `goldfish/liii/vector.scm`
- `bench/vector-filter.scm`
- `tests/liii/vector/vector-filter-test.scm`

## 如何测试
```bash
# 1. 构建
xmake b goldfish

# 2. 运行功能测试
bin/gf tests/liii/vector/vector-filter-test.scm

# 3. 运行性能基准测试
bin/gf bench/vector-filter.scm
```

## 2026-05-11 优化 vector-filter 性能

### What
1. 新增 `bench/vector-filter.scm` 性能基准测试,覆盖空向量、小向量(10 元素)、中向量(100 元素)、大向量(1000 元素)、超大向量(10000 元素)等场景。
2. 优化 `vector-filter` 实现,将 `vector-fold` + `length` + 反向 `vector-set!` 替换为 `vector-fold-right` + `list->vector`。
3. 功能测试全部通过(5 correct, 0 failed)。

### Why
原始实现存在以下性能问题:
- `vector-fold` 从左到右遍历,`cons` 累积产生倒序列表
- 需要额外调用 `length` 计算结果长度
- 最后通过 Scheme 层循环从末尾反向 `vector-set!` 填充结果向量

新实现利用 `vector-fold-right` 从右到左遍历,`cons` 自然产生正序列表,再经 C 层 `list->vector` 一次性转换,消除了 `length` 遍历和反向填充循环。

### How

**优化前实现:**
```scheme
(define (vector-filter pred vec)
(let* ((result-list (vector-fold (lambda (elem acc)
(if (pred elem) (cons elem acc) acc))
'() vec))
(result-length (length result-list))
(result-vec (make-vector result-length)))
(let loop ((i (- result-length 1)) (lst result-list))
(if (null? lst)
result-vec
(begin
(vector-set! result-vec i (car lst))
(loop (- i 1) (cdr lst)))))))
```

**优化后实现:**
```scheme
(define (vector-filter pred vec)
(list->vector (vector-fold-right (lambda (elem acc)
(if (pred elem) (cons elem acc) acc))
'() vec)))
```

**性能对比:**

| 测试场景 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| 空向量 (10万次) | 0.0345s | 0.0228s | 34% |
| 小向量(10)全匹配 (10万次) | 0.1755s | 0.1206s | 31% |
| 小向量(10)半匹配 (10万次) | 0.1465s | 0.1096s | 25% |
| 中向量(100)半匹配 (10万次) | 1.1292s | 0.9248s | 18% |
| 大向量(1000)半匹配 (1万次) | 1.1055s | 0.8814s | 20% |
| 超大向量(10000) (1千次) | 1.2926s | 0.9898s | 23% |
18 changes: 1 addition & 17 deletions goldfish/liii/vector.scm
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,7 @@
(begin

(define (vector-filter pred vec)
(let* ((result-list (vector-fold (lambda (elem acc) (if (pred elem) (cons elem acc) acc)) '() vec)
) ;result-list
(result-length (length result-list))
(result-vec (make-vector result-length))
) ;
(let loop
((i (- result-length 1)) (lst result-list))
(if (null? lst)
result-vec
(begin
(vector-set! result-vec i (car lst))
(loop (- i 1) (cdr lst))
) ;begin
) ;if
) ;let
) ;let*
) ;define
(list->vector (vector-fold-right (lambda (elem acc) (if (pred elem) (cons elem acc) acc)) '() vec)))

(define (vector-contains? vec elem . args)
(let ((cmp (if (null? args) equal? (car args))))
Expand Down
Loading