🎉 Initial commit

This commit is contained in:
2025-03-19 21:10:19 +08:00
commit 86c8755f79
70 changed files with 6915 additions and 0 deletions

209
benchmark/README.md Normal file
View File

@@ -0,0 +1,209 @@
# <div align="center">🚀 PixelNebula 基准测试</div>
[英文](README_EN.md) | 中文
## 📊 简介
本目录包含了 PixelNebula 库的全面基准测试,用于测量和分析库在各种操作场景下的性能表现。这些测试可以帮助我们识别潜在的性能瓶颈,并指导后续的优化工作。
<hr/>
## 🧪 测试内容
<div>
<table>
<tr>
<td align="center" width="20%">
<img src="../assets/example_avatar.svg" width="80" height="80" alt="基本生成" /><br/>
<strong>基本头像生成</strong>
</td>
<td align="center" width="20%">
<img src="../assets/style.svg" width="80" height="80" alt="样式和主题" /><br/>
<strong>样式和主题</strong>
</td>
<td align="center" width="20%">
<img src="../assets/animation.svg" width="80" height="80" alt="动画效果" /><br/>
<strong>动画效果</strong>
</td>
<td align="center" width="20%">
<img src="../assets/cache.svg" width="80" height="80" alt="缓存系统" /><br/>
<strong>缓存系统</strong>
</td>
<td align="center" width="20%">
<img src="../assets/performance.svg" width="80" height="80" alt="并发性能" /><br/>
<strong>并发与内存</strong>
</td>
</tr>
</table>
</div>
基准测试涵盖了 PixelNebula 的以下核心功能:
### 1. 🖼️ 基本头像生成 (`basic_benchmark_test.go`)
- 普通头像生成
- 无环境头像生成
- 不同尺寸头像生成
- 相同ID多次生成
### 2. 🎨 样式和主题 (`style_theme_benchmark_test.go`)
- 不同样式的性能对比
- 不同主题的性能对比
- 自定义主题
- 样式与主题组合
### 3. ✨ 动画效果 (`animation_benchmark_test.go`)
- 旋转动画
- 渐变动画
- 淡入淡出动画
- 变换动画
- 颜色动画
- 多个动画组合
### 4. 💾 缓存系统 (`cache_benchmark_test.go`)
- 无缓存 vs. 默认缓存
- 不同缓存大小
- 缓存压缩效果
- 不同过期时间配置
### 5. ⚡ 并发与内存使用 (`concurrency_memory_benchmark_test.go`)
- 不同并发级别的性能
- 共享实例的并发性能
- 各种操作的内存占用分析
<hr/>
## 🚀 运行基准测试
### 运行所有测试
```bash
cd benchmark
go test -bench=. -benchmem
```
### 运行特定测试组
<div align="center">
<table>
<tr>
<td width="33%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>🏃 基本测试</h4>
<pre>go test -bench=BenchmarkBasic -benchmem</pre>
</div>
</td>
<td width="33%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>💾 缓存测试</h4>
<pre>go test -bench=BenchmarkCache -benchmem</pre>
</div>
</td>
<td width="33%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>✨ 动画测试</h4>
<pre>go test -bench=BenchmarkAnimation -benchmem</pre>
</div>
</td>
</tr>
</table>
</div>
### 高级配置
<div align="center">
<table>
<tr>
<td width="50%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>⚙️ 设置CPU计数</h4>
<pre>go test -bench=. -benchmem -cpu=1,2,4,8</pre>
</div>
</td>
<td width="50%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>⏱️ 设置迭代次数和时间</h4>
<pre>go test -bench=. -benchmem -count=5 -benchtime=5s</pre>
</div>
</td>
</tr>
</table>
</div>
<hr/>
## 📈 测试结果分析
运行测试后,结果会以如下格式显示:
```
BenchmarkBasicAvatarGeneration-8 5000 234567 ns/op 12345 B/op 123 allocs/op
```
<div>
<table>
<tr>
<th align="center">组成部分</th>
<th align="center">描述</th>
</tr>
<tr>
<td align="center"><code>BenchmarkBasicAvatarGeneration-8</code></td>
<td>测试名称8表示使用8个CPU</td>
</tr>
<tr>
<td align="center"><code>5000</code></td>
<td>测试运行的迭代次数</td>
</tr>
<tr>
<td align="center"><code>234567 ns/op</code></td>
<td>每次操作的平均耗时(纳秒)</td>
</tr>
<tr>
<td align="center"><code>12345 B/op</code></td>
<td>每次操作的平均内存分配(字节)</td>
</tr>
<tr>
<td align="center"><code>123 allocs/op</code></td>
<td>每次操作的平均内存分配次数</td>
</tr>
</table>
</div>
<hr/>
## 📝 添加基准测试
在添加新功能时,建议同时添加相应的基准测试:
1. **创建测试函数**:为特定功能创建新的测试函数,命名为 `BenchmarkXXX`
2. **重置计时器**:使用 `b.ResetTimer()` 在准备工作完成后重置计时器
3. **创建子测试**:使用 `b.Run()` 创建子测试以对比不同变量
4. **使用迭代计数**:使用 `b.N` 作为迭代次数以确保统计准确性
<div>
<p><strong>示例:</strong></p>
```go
func BenchmarkMyFeature(b *testing.B) {
// 准备代码
pn := pixelnebula.NewPixelNebula()
// 在实际基准测试前重置计时器
b.ResetTimer()
// 运行基准测试
for i := 0; i < b.N; i++ {
// 要测试的代码
pn.MyFeature()
}
}
```
</div>
<hr/>
<div align="center">
<p><em>更多信息,请查看 PixelNebula 文档和示例。</em></p>
<p>© 2024 landaiqing</p>
</div>

209
benchmark/README_EN.md Normal file
View File

@@ -0,0 +1,209 @@
# <div align="center">🚀 PixelNebula Benchmarks</div>
[中文](README.md) | English
## 📊 Introduction
This directory contains comprehensive benchmark tests for the PixelNebula library, designed to measure and analyze performance across various operational scenarios. These tests help identify potential performance bottlenecks and guide subsequent optimization efforts.
<hr/>
## 🧪 Test Content
<div>
<table>
<tr>
<td align="center" width="20%">
<img src="../assets/example_avatar.svg" width="80" height="80" alt="Basic Generation" /><br/>
<strong>Basic Avatar Generation</strong>
</td>
<td align="center" width="20%">
<img src="../assets/style.svg" width="80" height="80" alt="Styles & Themes" /><br/>
<strong>Styles & Themes</strong>
</td>
<td align="center" width="20%">
<img src="../assets/animation.svg" width="80" height="80" alt="Animations" /><br/>
<strong>Animation Effects</strong>
</td>
<td align="center" width="20%">
<img src="../assets/cache.svg" width="80" height="80" alt="Cache System" /><br/>
<strong>Cache System</strong>
</td>
<td align="center" width="20%">
<img src="../assets/performance.svg" width="80" height="80" alt="Concurrency" /><br/>
<strong>Concurrency & Memory</strong>
</td>
</tr>
</table>
</div>
The benchmarks cover the following core functionalities of PixelNebula:
### 1. 🖼️ Basic Avatar Generation (`basic_benchmark_test.go`)
- Regular avatar generation
- No-environment avatar generation
- Avatar generation with different sizes
- Multiple generations with the same ID
### 2. 🎨 Styles and Themes (`style_theme_benchmark_test.go`)
- Performance comparison between different styles
- Performance comparison between different themes
- Custom themes
- Style and theme combinations
### 3. ✨ Animation Effects (`animation_benchmark_test.go`)
- Rotation animation
- Gradient animation
- Fade-in/out animation
- Transform animation
- Color animation
- Multiple animation combinations
### 4. 💾 Cache System (`cache_benchmark_test.go`)
- No cache vs. default cache
- Different cache sizes
- Cache compression effects
- Different expiry time configurations
### 5. ⚡ Concurrency and Memory Usage (`concurrency_memory_benchmark_test.go`)
- Performance at different concurrency levels
- Concurrent performance with shared instances
- Memory usage analysis for various operations
<hr/>
## 🚀 Running Benchmarks
### Run All Tests
```bash
cd benchmark
go test -bench=. -benchmem
```
### Run Specific Test Groups
<div>
<table>
<tr>
<td width="33%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>🏃 Basic Tests</h4>
<pre>go test -bench=BenchmarkBasic -benchmem</pre>
</div>
</td>
<td width="33%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>💾 Cache Tests</h4>
<pre>go test -bench=BenchmarkCache -benchmem</pre>
</div>
</td>
<td width="33%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>✨ Animation Tests</h4>
<pre>go test -bench=BenchmarkAnimation -benchmem</pre>
</div>
</td>
</tr>
</table>
</div>
### Advanced Configuration
<div align="center">
<table>
<tr>
<td width="50%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>⚙️ Set CPU Count</h4>
<pre>go test -bench=. -benchmem -cpu=1,2,4,8</pre>
</div>
</td>
<td width="50%" align="center">
<div style="padding: 15px; border-radius: 10px;">
<h4>⏱️ Set Iteration Count and Duration</h4>
<pre>go test -bench=. -benchmem -count=5 -benchtime=5s</pre>
</div>
</td>
</tr>
</table>
</div>
<hr/>
## 📈 Test Result Analysis
After running the tests, results will be displayed in the following format:
```
BenchmarkBasicAvatarGeneration-8 5000 234567 ns/op 12345 B/op 123 allocs/op
```
<div>
<table>
<tr>
<th align="center">Component</th>
<th align="center">Description</th>
</tr>
<tr>
<td align="center"><code>BenchmarkBasicAvatarGeneration-8</code></td>
<td>Test name, 8 indicates using 8 CPUs</td>
</tr>
<tr>
<td align="center"><code>5000</code></td>
<td>Number of iterations the test ran</td>
</tr>
<tr>
<td align="center"><code>234567 ns/op</code></td>
<td>Average time per operation (nanoseconds)</td>
</tr>
<tr>
<td align="center"><code>12345 B/op</code></td>
<td>Average memory allocation per operation (bytes)</td>
</tr>
<tr>
<td align="center"><code>123 allocs/op</code></td>
<td>Average number of memory allocations per operation</td>
</tr>
</table>
</div>
<hr/>
## 📝 Adding Benchmark Tests
When adding new features, it's recommended to add corresponding benchmark tests:
1. **Create a Test Function**: Create a new test function for the specific feature, named `BenchmarkXXX`
2. **Reset Timer**: Use `b.ResetTimer()` to reset the timer after setup work is complete
3. **Create Sub-tests**: Use `b.Run()` to create sub-tests for comparing different variables
4. **Use Iteration Count**: Use `b.N` as the iteration count to ensure statistical accuracy
<div>
<p><strong>Example:</strong></p>
```go
func BenchmarkMyFeature(b *testing.B) {
// Setup code
pn := pixelnebula.NewPixelNebula()
// Reset timer before the actual benchmark
b.ResetTimer()
// Run the benchmark
for i := 0; i < b.N; i++ {
// Code to benchmark
pn.MyFeature()
}
}
```
</div>
<hr/>
<div align="center">
<p><em>For more information, check out the PixelNebula documentation and examples.</em></p>
<p>© 2024 landaiqing</p>
</div>

View File

@@ -0,0 +1,132 @@
package benchmark
import (
"testing"
"github.com/landaiqing/go-pixelnebula"
"github.com/landaiqing/go-pixelnebula/style"
)
// BenchmarkRotateAnimation 测试旋转动画的性能
func BenchmarkRotateAnimation(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithRotateAnimation("env", 0, 360, 10, 1) // 单次旋转
_, err := pn.Generate("benchmark-rotate", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkGradientAnimation 测试渐变动画的性能
func BenchmarkGradientAnimation(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithGradientAnimation("head", []string{"#ff0000", "#00ff00", "#0000ff"}, 5, 1, true)
_, err := pn.Generate("benchmark-gradient", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkFadeAnimation 测试淡入淡出动画的性能
func BenchmarkFadeAnimation(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithFadeAnimation("eyes", "1", "0.3", 2, 1)
_, err := pn.Generate("benchmark-fade", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkTransformAnimation 测试变换动画的性能
func BenchmarkTransformAnimation(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithTransformAnimation("mouth", "scale", "1 1", "1.1 1.1", 1.5, 1)
_, err := pn.Generate("benchmark-transform", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkColorAnimation 测试颜色变换动画的性能
func BenchmarkColorAnimation(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithColorAnimation("clo", "fill", "#ff0000", "#0000ff", 3, 1)
_, err := pn.Generate("benchmark-color", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkMultipleAnimations 测试多个动画组合的性能
func BenchmarkMultipleAnimations(b *testing.B) {
animationCounts := []int{1, 2, 3, 5}
for _, count := range animationCounts {
b.Run("Animations_"+Itoa(count), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
// 根据数量添加不同的动画
if count >= 1 {
pn.WithRotateAnimation("env", 0, 360, 10, 1)
}
if count >= 2 {
pn.WithFadeAnimation("eyes", "1", "0.3", 2, 1)
}
if count >= 3 {
pn.WithTransformAnimation("mouth", "scale", "1 1", "1.1 1.1", 1.5, 1)
}
if count >= 4 {
pn.WithColorAnimation("clo", "fill", "#ff0000", "#0000ff", 3, 1)
}
if count >= 5 {
pn.WithGradientAnimation("head", []string{"#ff0000", "#00ff00", "#0000ff"}, 5, 1, true)
}
_, err := pn.Generate("benchmark-multi-"+Itoa(count), false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}

View File

@@ -0,0 +1,88 @@
package benchmark
import (
"strconv"
"testing"
"github.com/landaiqing/go-pixelnebula"
"github.com/landaiqing/go-pixelnebula/style"
)
// BenchmarkBasicAvatarGeneration 测试基本头像生成性能
func BenchmarkBasicAvatarGeneration(b *testing.B) {
// 重置计时器
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
// 生成SVG
_, err := pn.Generate("benchmark-id", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkAvatarWithNoEnvironment 测试无环境头像生成性能
func BenchmarkAvatarWithNoEnvironment(b *testing.B) {
// 重置计时器
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
// 生成无环境SVG
_, err := pn.Generate("benchmark-id", true).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkDifferentSizes 测试不同大小头像生成性能
func BenchmarkDifferentSizes(b *testing.B) {
sizes := []int{100, 200, 400, 800}
for _, size := range sizes {
b.Run("Size_"+Itoa(size), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(size, size)
_, err := pn.Generate("benchmark-size-"+Itoa(size), false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}
// BenchmarkIDReuse 测试多次使用相同ID生成头像的性能不使用缓存
func BenchmarkIDReuse(b *testing.B) {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := pn.Generate("fixed-benchmark-id", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// Itoa 简单的整数转字符串函数
func Itoa(n int) string {
return strconv.Itoa(n)
}

View File

@@ -0,0 +1,155 @@
package benchmark
import (
"testing"
"time"
"github.com/landaiqing/go-pixelnebula"
"github.com/landaiqing/go-pixelnebula/cache"
"github.com/landaiqing/go-pixelnebula/style"
)
// BenchmarkDefaultCacheVsNoCache 对比有无默认缓存的性能差异
func BenchmarkDefaultCacheVsNoCache(b *testing.B) {
// 不使用缓存的基准测试
b.Run("NoCache", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
_, err := pn.Generate("benchmark-cache-test", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
// 使用默认缓存的基准测试
b.Run("DefaultCache", func(b *testing.B) {
// 创建一个带默认缓存的实例
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithDefaultCache()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := pn.Generate("benchmark-cache-test", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
// BenchmarkCacheSizes 测试不同缓存大小对性能的影响
func BenchmarkCacheSizes(b *testing.B) {
cacheSizes := []int{10, 100, 1000}
for _, size := range cacheSizes {
b.Run("CacheSize_"+Itoa(size), func(b *testing.B) {
// 创建自定义缓存配置
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithCache(cache.CacheOptions{
Size: size,
Expiration: 3600 * time.Second,
})
// 预热缓存,生成一些不同的头像
for i := 0; i < size/2; i++ {
_, _ = pn.Generate("preload-"+Itoa(i), false).ToSVG()
}
b.ResetTimer()
// 测试缓存命中和未命中的混合场景
for i := 0; i < b.N; i++ {
id := "benchmark-" + Itoa(i%size) // 循环使用ID确保部分缓存命中
_, err := pn.Generate(id, false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}
// BenchmarkCacheCompression 测试缓存压缩对性能的影响
func BenchmarkCacheCompression(b *testing.B) {
compressionLevels := []struct {
name string
level int
}{
{"NoCompression", 0},
{"LowCompression", 3},
{"MediumCompression", 6},
{"HighCompression", 9},
}
for _, cl := range compressionLevels {
b.Run(cl.name, func(b *testing.B) {
// 创建带压缩缓存的实例
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithDefaultCache()
if cl.level > 0 {
pn.WithCompression(cache.CompressOptions{
Enabled: true,
Level: cl.level,
MinSizeBytes: 100,
})
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := pn.Generate("benchmark-compress", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}
// BenchmarkCacheExpiry 测试不同缓存过期时间的性能影响
func BenchmarkCacheExpiry(b *testing.B) {
expiryTimes := []struct {
name string
time time.Duration
}{
{"Short_1m", 1 * time.Minute},
{"Medium_1h", 1 * time.Hour},
{"Long_24h", 24 * time.Hour},
}
for _, et := range expiryTimes {
b.Run(et.name, func(b *testing.B) {
// 创建带自定义过期时间的缓存实例
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithCache(cache.CacheOptions{
Size: 100,
Expiration: et.time,
})
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := pn.Generate("benchmark-expiry", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}

View File

@@ -0,0 +1,138 @@
package benchmark
import (
"sync"
"testing"
"github.com/landaiqing/go-pixelnebula"
"github.com/landaiqing/go-pixelnebula/style"
)
// BenchmarkConcurrentGeneration 测试并发生成头像的性能
func BenchmarkConcurrentGeneration(b *testing.B) {
concurrencyCounts := []int{1, 2, 4, 8, 16}
for _, count := range concurrencyCounts {
b.Run("Concurrent_"+Itoa(count), func(b *testing.B) {
b.ResetTimer()
// 将总迭代次数调整为b.N确保可比较性
b.SetParallelism(count)
b.RunParallel(func(pb *testing.PB) {
counter := 0
for pb.Next() {
counter++
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithDefaultCache()
_, err := pn.Generate("benchmark-concurrent-"+Itoa(counter), false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
})
}
}
// BenchmarkConcurrentWithSharedInstance 测试使用共享实例进行并发生成的性能
func BenchmarkConcurrentWithSharedInstance(b *testing.B) {
concurrencyCounts := []int{1, 2, 4, 8, 16}
for _, count := range concurrencyCounts {
b.Run("SharedInstance_"+Itoa(count), func(b *testing.B) {
// 创建一个共享实例
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithDefaultCache()
// 创建互斥锁保护共享实例
var mu sync.Mutex
b.ResetTimer()
b.SetParallelism(count)
b.RunParallel(func(pb *testing.PB) {
counter := 0
for pb.Next() {
counter++
// 锁定共享实例
mu.Lock()
_, err := pn.Generate("benchmark-shared-"+Itoa(counter), false).ToSVG()
mu.Unlock()
if err != nil {
b.Fatal(err)
}
}
})
})
}
}
// BenchmarkMemoryUsage 测试不同操作的内存使用情况
func BenchmarkMemoryUsage(b *testing.B) {
// 注意: 这个基准测试主要关注内存分配统计,
// Go 的基准测试框架会自动收集并报告内存统计数据
// 测试基本头像生成的内存使用
b.Run("BasicGeneration", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
_, err := pn.Generate("memory-basic", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
// 测试添加动画的内存使用
b.Run("WithAnimations", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithRotateAnimation("env", 0, 360, 10, 1)
pn.WithFadeAnimation("eyes", "1", "0.3", 2, 1)
_, err := pn.Generate("memory-animations", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
// 测试缓存的内存使用
b.Run("WithCache", func(b *testing.B) {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithDefaultCache()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := pn.Generate("memory-cache", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
// 测试大尺寸头像的内存使用
b.Run("LargeSize", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(1000, 1000)
_, err := pn.Generate("memory-large", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}

View File

@@ -0,0 +1,126 @@
package benchmark
import (
"testing"
"github.com/landaiqing/go-pixelnebula"
"github.com/landaiqing/go-pixelnebula/style"
"github.com/landaiqing/go-pixelnebula/theme"
)
// BenchmarkDifferentStyles 测试不同风格的生成性能
func BenchmarkDifferentStyles(b *testing.B) {
styles := []struct {
name string
style style.StyleType
}{
{"GirlStyle", style.GirlStyle},
{"AteamStyle", style.AteamStyle},
{"BlondStyle", style.BlondStyle},
{"FirehairStyle", style.FirehairStyle},
}
for _, s := range styles {
b.Run(s.name, func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(s.style)
pn.WithSize(231, 231)
_, err := pn.Generate("benchmark-style-"+s.name, false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}
// BenchmarkDifferentThemes 测试不同主题的生成性能
func BenchmarkDifferentThemes(b *testing.B) {
// 假设有5个内置主题索引
themeCount := 5
for i := 0; i < themeCount; i++ {
b.Run("Theme_"+Itoa(i), func(b *testing.B) {
b.ResetTimer()
for j := 0; j < b.N; j++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
_, err := pn.Generate("benchmark-theme-"+Itoa(i), false).SetTheme(i).Build().ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}
// BenchmarkCustomTheme 测试自定义主题的性能
func BenchmarkCustomTheme(b *testing.B) {
// 创建一个自定义主题
customTheme := []theme.Theme{
{
theme.ThemePart{
"env": []string{"#f0f0f0", "#e0e0e0"},
"head": []string{"#ffd699"},
"eyes": []string{"#555555", "#ffffff"},
"mouth": []string{"#ff6b6b"},
"top": []string{"#6b5b95", "#6b5b95"},
"clo": []string{"#88b04b"},
},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(style.GirlStyle)
pn.WithSize(231, 231)
pn.WithCustomizeTheme(customTheme)
_, err := pn.Generate("benchmark-custom-theme", false).ToSVG()
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkStyleThemeCombinations 测试不同风格和主题组合的性能
func BenchmarkStyleThemeCombinations(b *testing.B) {
styles := []style.StyleType{style.GirlStyle, style.AsianStyle}
themes := []int{0, 1, 2}
for _, s := range styles {
for _, t := range themes {
styleName := "Unknown"
switch s {
case style.GirlStyle:
styleName = "Girl"
case style.AsianStyle:
styleName = "Asian"
}
b.Run(styleName+"_Theme"+Itoa(t), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
pn := pixelnebula.NewPixelNebula()
pn.WithStyle(s)
pn.WithSize(231, 231)
_, err := pn.Generate("benchmark-combo", false).SetTheme(t).Build().ToSVG()
if err != nil {
b.Fatal(err)
}
}
})
}
}
}