gomog/internal/engine/benchmark_test.go

367 lines
9.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package engine
import (
"fmt"
"testing"
"git.kingecg.top/kingecg/gomog/pkg/types"
)
// ========== 辅助函数:生成测试数据 ==========
func generateDocuments(count int) map[string]types.Document {
docs := make(map[string]types.Document)
for i := 0; i < count; i++ {
docs[fmt.Sprintf("doc%d", i)] = types.Document{
ID: fmt.Sprintf("doc%d", i),
Data: map[string]interface{}{
"name": fmt.Sprintf("Item%d", i),
"value": float64(i),
"category": fmt.Sprintf("cat%d", i%10),
"status": map[string]interface{}{"active": true, "priority": float64(i % 5)},
},
}
}
return docs
}
// ========== 聚合管道基准测试 ==========
// BenchmarkAggregationPipeline_Simple 简单聚合管道性能测试
func BenchmarkAggregationPipeline_Simple(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
// 准备 100 个文档
CreateTestCollectionForTesting(store, "benchmark_simple", generateDocuments(100))
pipeline := []types.AggregateStage{
{Stage: "$match", Spec: map[string]interface{}{"status.active": true}},
{Stage: "$limit", Spec: float64(10)},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("benchmark_simple", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkAggregationPipeline_Group 分组聚合性能测试
func BenchmarkAggregationPipeline_Group(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
// 生成 1000 个文档
docs := make(map[string]types.Document)
for i := 0; i < 1000; i++ {
docs[fmt.Sprintf("doc%d", i)] = types.Document{
ID: fmt.Sprintf("doc%d", i),
Data: map[string]interface{}{
"category": fmt.Sprintf("cat%d", i%10), // 10 个类别
"value": float64(i),
},
}
}
CreateTestCollectionForTesting(store, "benchmark_group", docs)
pipeline := []types.AggregateStage{
{Stage: "$group", Spec: map[string]interface{}{
"_id": "$category",
"total": map[string]interface{}{"$sum": "$value"},
"count": map[string]interface{}{"$sum": float64(1)},
}},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("benchmark_group", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkAggregationPipeline_Complex 复杂聚合管道性能测试
func BenchmarkAggregationPipeline_Complex(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
// 主集合500 个订单
mainDocs := make(map[string]types.Document)
for i := 0; i < 500; i++ {
mainDocs[fmt.Sprintf("main%d", i)] = types.Document{
ID: fmt.Sprintf("main%d", i),
Data: map[string]interface{}{
"user_id": float64(i % 100),
"amount": float64(i * 10),
"status": "completed",
},
}
}
CreateTestCollectionForTesting(store, "orders", mainDocs)
// 关联集合100 个用户
userDocs := make(map[string]types.Document)
for i := 0; i < 100; i++ {
userDocs[fmt.Sprintf("user%d", i)] = types.Document{
ID: fmt.Sprintf("user%d", i),
Data: map[string]interface{}{
"_id": float64(i),
"name": fmt.Sprintf("User%d", i),
"department": fmt.Sprintf("Dept%d", i%5),
},
}
}
CreateTestCollectionForTesting(store, "users", userDocs)
pipeline := []types.AggregateStage{
{Stage: "$match", Spec: map[string]interface{}{"status": "completed"}},
{Stage: "$lookup", Spec: map[string]interface{}{
"from": "users",
"localField": "user_id",
"foreignField": "_id",
"as": "user_info",
}},
{Stage: "$unwind", Spec: "$user_info"},
{Stage: "$group", Spec: map[string]interface{}{
"_id": "$user_info.department",
"total_sales": map[string]interface{}{"$sum": "$amount"},
}},
{Stage: "$sort", Spec: map[string]interface{}{"total_sales": -1}},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("orders", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// ========== 查询操作符基准测试 ==========
// BenchmarkQuery_Expr 表达式查询性能测试
func BenchmarkQuery_Expr(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
docs := make(map[string]types.Document)
for i := 0; i < 1000; i++ {
docs[fmt.Sprintf("doc%d", i)] = types.Document{
ID: fmt.Sprintf("doc%d", i),
Data: map[string]interface{}{
"score": float64(i),
"name": fmt.Sprintf("item%d", i),
},
}
}
CreateTestCollectionForTesting(store, "benchmark_expr", docs)
pipeline := []types.AggregateStage{
{Stage: "$match", Spec: map[string]interface{}{
"$expr": map[string]interface{}{
"$gt": []interface{}{"$score", float64(500)},
},
}},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("benchmark_expr", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// BenchmarkQuery_JsonSchema JSON Schema 验证性能测试
func BenchmarkQuery_JsonSchema(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
docs := make(map[string]types.Document)
for i := 0; i < 500; i++ {
docs[fmt.Sprintf("doc%d", i)] = types.Document{
ID: fmt.Sprintf("doc%d", i),
Data: map[string]interface{}{
"name": fmt.Sprintf("item%d", i),
"price": float64(i * 10),
"stock": float64(i),
},
}
}
CreateTestCollectionForTesting(store, "benchmark_schema", docs)
schema := map[string]interface{}{
"properties": map[string]interface{}{
"price": map[string]interface{}{
"bsonType": "number",
"minimum": float64(100),
},
},
}
pipeline := []types.AggregateStage{
{Stage: "$match", Spec: map[string]interface{}{
"$jsonSchema": schema,
}},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("benchmark_schema", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// ========== 类型转换基准测试 ==========
// BenchmarkTypeConversion_ToString 字符串转换性能测试
func BenchmarkTypeConversion_ToString(b *testing.B) {
engine := &AggregationEngine{}
data := map[string]interface{}{"value": float64(12345)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = engine.toString("$value", data)
}
}
// BenchmarkTypeConversion_Bitwise 位运算性能测试
func BenchmarkTypeConversion_Bitwise(b *testing.B) {
engine := &AggregationEngine{}
operand := []interface{}{float64(12345), float64(67890)}
data := map[string]interface{}{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = engine.bitAnd(operand, data)
}
}
// ========== 投影基准测试 ==========
// BenchmarkProjection_ElemMatch 数组元素匹配性能测试
func BenchmarkProjection_ElemMatch(b *testing.B) {
data := map[string]interface{}{
"scores": []interface{}{
map[string]interface{}{"subject": "math", "score": float64(85)},
map[string]interface{}{"subject": "english", "score": float64(92)},
map[string]interface{}{"subject": "science", "score": float64(78)},
},
}
spec := map[string]interface{}{
"$elemMatch": map[string]interface{}{
"score": map[string]interface{}{"$gte": float64(90)},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = projectElemMatch(data, "scores", spec)
}
}
// BenchmarkProjection_Slice 数组切片性能测试
func BenchmarkProjection_Slice(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
docs := make(map[string]types.Document)
for i := 0; i < 100; i++ {
docs[fmt.Sprintf("doc%d", i)] = types.Document{
ID: fmt.Sprintf("doc%d", i),
Data: map[string]interface{}{
"tags": []interface{}{"tag1", "tag2", "tag3", "tag4", "tag5"},
},
}
}
CreateTestCollectionForTesting(store, "slice_bench", docs)
pipeline := []types.AggregateStage{
{Stage: "$project", Spec: map[string]interface{}{
"tags": map[string]interface{}{"$slice": float64(3)},
}},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("slice_bench", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// ========== UnionWith 基准测试 ==========
// BenchmarkUnionWith_Simple 集合并集性能测试(无 pipeline
func BenchmarkUnionWith_Simple(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
CreateTestCollectionForTesting(store, "union_main", generateDocuments(100))
CreateTestCollectionForTesting(store, "union_other", generateDocuments(100))
pipeline := []types.AggregateStage{
{Stage: "$unionWith", Spec: "union_other"},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("union_main", pipeline)
if err != nil {
b.Fatal(err)
}
}
}
// ========== Redact 基准测试 ==========
// BenchmarkRedact_LevelBased 基于层级的文档红黑性能测试
func BenchmarkRedact_LevelBased(b *testing.B) {
store := NewMemoryStore(nil)
engine := NewAggregationEngine(store)
docs := make(map[string]types.Document)
for i := 0; i < 200; i++ {
docs[fmt.Sprintf("doc%d", i)] = types.Document{
ID: fmt.Sprintf("doc%d", i),
Data: map[string]interface{}{
"level": float64(i % 10),
"secret": "classified",
"public": "visible",
},
}
}
CreateTestCollectionForTesting(store, "redact_bench", docs)
spec := map[string]interface{}{
"$cond": map[string]interface{}{
"if": map[string]interface{}{
"$gte": []interface{}{"$level", float64(5)},
},
"then": "$$KEEP",
"else": "$$PRUNE",
},
}
pipeline := []types.AggregateStage{
{Stage: "$redact", Spec: spec},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := engine.Execute("redact_bench", pipeline)
if err != nil {
b.Fatal(err)
}
}
}