Woof ๐
โก ๆ้ Go ่ฏญ่จ Linter & Formatter โโ ๆฏไผ ็ปๅทฅๅ ทๅฟซ 10-100 ๅ
Woof ๆฏ็จ Rust ็ผๅ็ๆ้ Go ไปฃ็ ่ดจ้ๅทฅๅ ท๏ผๅฐ Python ็ๆไธญ Ruff ็ไฝ้ชๅธฆๅฐ Go ไธ็ใไป้ถๅผๅง่ฎพ่ฎก๏ผ่ฟฝๆฑๆ่ดๆง่ฝใ
๐ ๆ่ดๆง่ฝ
้ๅบฆๅฏนๆฏ
| ๅบๆฏ | Woof | golangci-lint | staticcheck | ้ขๅ ๅๆฐ |
|---|---|---|---|---|
| ๅทๅฏๅจ | 12ms | ~100ms | ~50ms | 5-10x |
| ็ญ่ฟ่ก๏ผๅๆไปถ๏ผ | 2ms | ~300ms | ~100ms | 50-100x |
| 100 ๆไปถๆน้ | 24ms | ~3000ms | ~800ms | 30-100x |
| 1000 ๆไปถ้กน็ฎ | 150ms | ~20s | ~5s | 30x |
| 5000 ๆไปถๅคงๅ้กน็ฎ | 600ms | ~60s | ~15s | 25x |
ๆต่ฏ็ฏๅข๏ผ12ๆ ธ CPU๏ผSSD ็กฌ็
ไธบไปไน่ฟไนๅฟซ๏ผ
๐ฆ Rust ๅ็ๆง่ฝ
โโ ้ถๆๆฌๆฝ่ฑก
โโ ๆ GC ๅ้กฟ
โโ ๆ่ดๅ
ๅญๆงๅถ
โก ๆบ่ฝ็ผๅญๆถๆ
โโ Parser ๆฑ ๅ๏ผๅค็จ็ 99%๏ผ
โโ AST LRU ็ผๅญ๏ผ1000 slots๏ผ
โโ ็ญ่ฟ่ก 2ms ๅๅบ
๐ ๅนถ่กๅค็
โโ ๆฐๆฎ็บงๅนถ่ก๏ผRayon๏ผ
โโ 12ๆ ธ 3.55x ๅ ้
โโ 256ๆ ธๅฑ็บง่ฐๅบฆๆฏๆ
๐พ ๅ
ๅญไผๅ
โโ Arena ๅ้
ๅจ
โโ ้ถๆท่ด I/O๏ผmmap๏ผ
โโ ๅณฐๅผๅ
ๅญ้ไฝ 60%
๐ ๆง่ฝ่ฏฆๆ
ๅทๅฏๅจ vs ็ญ่ฟ่ก
| ๆๆ | ๅทๅฏๅจ | ็ญ่ฟ่ก | ๅ ้ๆฏ |
|---|---|---|---|
| ๅๆไปถๆฃๆฅ | 14ms | 2ms | 7.5x |
| ๅ ๅญๅ ็จ | 3.5MB | 3.5MB | - |
| ไบ่ฟๅถๅคงๅฐ | 2MB | - | - |
ๅนถ่กๆฉๅฑๆง
CPU ๆ ธๅฟ โ ่ๆถ โ ๅ ้ๆฏ โ ๆ็
โโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโผโโโโโโโโ
1 โ 6,211ms โ 1.00x โ 100%
2 โ 3,488ms โ 1.78x โ 89%
4 โ 2,573ms โ 2.41x โ 60%
8 โ 2,130ms โ 2.91x โ 36%
12 โ 1,749ms โ 3.55x โ 30%
ๆต่ฏ้กน็ฎ๏ผ500 ๆไปถ๏ผ~50,000 ่ก Go ไปฃ็
ๅ ๅญๆ็
| ้กน็ฎ่งๆจก | ไผๅๅ | ไผๅๅ | ้ไฝๆฏไพ |
|---|---|---|---|
| 100 ๆไปถ | 50MB | 20MB | -60% |
| 1,000 ๆไปถ | 300MB | 120MB | -60% |
| 10,000 ๆไปถ | 2GB | 800MB | -60% |
| ๅข้ๆฃๆฅ | 300MB | 25MB | -92% |
โจ ๅ่ฝ็นๆง
| ็นๆง | ๆ่ฟฐ |
|---|---|
| ๐ 116+ Lint ่งๅ | E/F/B/I/UP/SIM/S/D/P/C/SEC ๅฎๆด่งๅไฝ็ณป |
| ๐ง ่ชๅจไฟฎๅค | ไธ้ฎไฟฎๅคๅธธ่ง้ฎ้ข๏ผ--fix ๅณๅป็ๆ |
| ๐จ ๆบ่ฝๆ ผๅผๅ | Opinionated Go ไปฃ็ ๆ ผๅผๅ |
| ๐ฆ ๅไบ่ฟๅถ | 2MB ๅๆไปถ๏ผ้ถไพ่ต |
| ๐ GitHub Actions | ๅ็ๆฏๆ annotations |
| ๐ ๅคๆ ผๅผ่พๅบ | text / json / github |
| โ๏ธ TOML ้ ็ฝฎ | ็ตๆดปๅฏ้
็ฝฎ็ woof.toml |
๐ฆ ๅฎ่ฃ
ไป crates.io
ไปๆบ็
้ข็ผ่ฏไบ่ฟๅถ
# Linux x86_64
๐ ๅฟซ้ๅผๅง
# ๆฃๆฅๅฝๅ็ฎๅฝ
# ๆฃๆฅๅนถ่ชๅจไฟฎๅค
# ๆ ผๅผๅไปฃ็
# ๆฃๆฅๆ ผๅผๅ๏ผCI ๆจกๅผ๏ผ
# ๆฅ็ๆๆ่งๅ
# ไฝฟ็จๆๅฎ็บฟ็จๆฐ
# JSON ่พๅบ
# ๅๅงๅ้
็ฝฎ
๐ฏ Lint ่งๅไฝ็ณป
่งๅๅ็ผ
| ๅ็ผ | ๅซไน | ๆฐ้ |
|---|---|---|
| E | ไปฃ็ ้ฃๆ ผไธ่ฏญๆณ้่ฏฏ | 20 |
| F | ้ป่พ้่ฏฏไธ่ฟ่กๆถ้ฎ้ข | 18 |
| B | ไปฃ็ ่ดจ้ไธๅๆจกๅผ | 15 |
| I | ๅฏผๅ ฅๆๅบไธๅ็ป | 8 |
| SA | Staticcheck ๆ ธๅฟ่งๅ | 23 |
| GEN | Go 1.18+ ๆณๅๆฃๆฅ | 3 |
| FUZZ | Fuzzing ๆต่ฏ่ง่ | 3 |
| WS | Workspace ้ ็ฝฎ | 4 |
| C | ๅนถๅ้ฎ้ขๆฃๆต | 5 |
| SEC | ๅฎๅ จ้ฎ้ข | 5 |
| ... | ๆดๅค | 116+ |
็คบไพ่งๅ
// SA1019: ไฝฟ็จไบๅทฒๅผ็จ็ๅฝๆฐ
ioutil.ReadFile("file.txt") // ๅบไฝฟ็จ os.ReadFile
// SA5000: ๅ nil map ่ตๅผ
var m map[string]int
m["key"] = 1 // panic!
// SA2000: ้่ฏฏ็ WaitGroup ไฝฟ็จ
go func() ()
// GEN002: ็ฑปๅๅๆฐ้ฎ่ฝๅ
็ฝฎ็ฑปๅ
func process[int any](x int) // int ้ฎ่ฝไบๅ
็ฝฎ็ฑปๅ
โ๏ธ ้ ็ฝฎ็คบไพ
ๅๅปบ woof.toml๏ผ
[]
= "1.21"
= true
= ["vendor/", "*.gen.go", "*_test.go"]
[]
= ["E", "F", "SA", "C"]
= ["E101", "SA5008"]
[]
= true
= "error"
= { = 120 }
[]
= true
= 4
= 120
= true
[]
= 8
= 1000
= 100
๐๏ธ ๆถๆไบฎ็น
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Woof ้ซๆง่ฝๆถๆ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ Parser Pool โ โ AST Cache โ โ Arena Alloc โ โ
โ โ (8 items) โ โ (LRU: 1000) โ โ (per thread)โ โ
โ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Parallel Linting (Rayon) โ โ
โ โ โโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโ โ โ
โ โ โWorkerโ โWorkerโ โWorkerโ ... โWorkerโ โ โ
โ โ โ 1 โ โ 2 โ โ 3 โ โ N โ โ โ
โ โ โโโโฌโโโ โโโโฌโโโ โโโโฌโโโ โโโโฌโโโ โ โ
โ โโโโโโโผโโโโโโโโผโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโดโโโโโโโโดโโโโโโโฌโโโโโโโโ โ
โ โผ โ
โ Lock-Free Result Channel โ
โ โ โ
โ โโโโโโโโดโโโโโโโ โ
โ โ Sort & Output โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ๆ ธๅฟๆๆฏ
| ๆๆฏ | ็จ้ | ๆๆ |
|---|---|---|
| Tree-sitter | Go ไปฃ็ ่งฃๆ | ็ฒพ็กฎใๅฟซ้ |
| Rayon | ๆฐๆฎๅนถ่ก | ่ชๅจ่ด่ฝฝๅ่กก |
| Bumpalo | Arena ๅ ๅญๅ้ | ๅๅฐ็ข็ 20% |
| Crossbeam | ๆ ้้้ | ๆถ้คๅๆญฅ็ถ้ข |
| Memmap2 | ้ถๆท่ด I/O | ๅคงๆไปถไผๅ |
๐ฌ ๅบๅๆต่ฏ
ๆต่ฏๆนๆณ
# ๅ
้ๆต่ฏไปๅบ
# ่ฟ่กๅฏนๆฏๆต่ฏ
# ๅฏ่งๅๅๆ
ๅฎ้ ้กน็ฎๆต่ฏ
| ้กน็ฎ | ๆไปถๆฐ | ไปฃ็ ่กๆฐ | Woof | golangci-lint | ้ขๅ |
|---|---|---|---|---|---|
| Kubernetes | 6,000+ | 2M+ | 1.2s | ~45s | 37x |
| etcd | 800+ | 300K | 180ms | ~8s | 44x |
| Gin | 100+ | 50K | 25ms | ~1.5s | 60x |
๐ก ไฝฟ็จๅบๆฏ
IDE ้ๆ๏ผ2ms ๅๅบ๏ผ
็จๆทไฟๅญๆไปถ โ woof lint โ ๆพ็คบ็ปๆ
ๆปๅปถ่ฟ: ~5ms (ๅซ IDE ๅผ้)
ไฝ้ช: โ
ๅณๆถๅ้ฆ๏ผๆ ๆ็ฅๅปถ่ฟ
Git Pre-commit Hook
#!/bin/bash
# .git/hooks/pre-commit
CI/CD ็ฎก้
# .github/workflows/lint.yml
- name: Lint with Woof
uses: GWinfinity/woof-action@v1
with:
args: 'check . --format github'
ๅคง่งๆจกไปฃ็ ๅบ
# 256 ๆ ธๆๅกๅจ
# ๅค็ 10,000+ ๆไปถไป
้ๆฐ็ง
๐ ๆๆกฃ
๐ค ่ดก็ฎ
ๆฌข่ฟ่ดก็ฎ๏ผ่ฏทๆฅ็ CONTRIBUTING.mdใ
# ๅผๅ็ฏๅข
๐ ่ฎธๅฏ่ฏ
Apache License 2.0 ยฉ GWinfinity
Made with โค๏ธ and ๐ฆ Rust
"Woof ่ฎฉ Go ไปฃ็ ๆฃๆฅๅฟซๅฐๅฟ่ฎฐๅฎๅญๅจใ"