初始化仓库
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
//go:build performance
|
||||
|
||||
// Package performance contains benchmark tests for cc-connect.
|
||||
// These tests measure latency, throughput, and resource usage.
|
||||
//
|
||||
// Run with: go test -bench=. -benchmem -tags=performance ./tests/performance/...
|
||||
package performance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chenhg5/cc-connect/core"
|
||||
"github.com/chenhg5/cc-connect/tests/mocks/fake"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-400: Single Message Latency
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_SingleMessageLatency(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
agent := fake.NewFakeAgent("bench-agent")
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sess, _ := agent.StartSession(ctx, "bench-session")
|
||||
sess.Send("Hello", nil, nil)
|
||||
for e := range sess.Events() {
|
||||
if e.Done {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-401: Concurrent Throughput
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_ConcurrentThroughput(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
numAgents := 10
|
||||
|
||||
// Create multiple agents with sessions
|
||||
agents := make([]struct {
|
||||
agent *fake.FakeAgent
|
||||
sess core.AgentSession
|
||||
}, numAgents)
|
||||
for i := 0; i < numAgents; i++ {
|
||||
agent := fake.NewFakeAgent("bench-agent")
|
||||
sess, _ := agent.StartSession(ctx, "bench-session")
|
||||
agents[i] = struct {
|
||||
agent *fake.FakeAgent
|
||||
sess core.AgentSession
|
||||
}{agent: agent, sess: sess}
|
||||
}
|
||||
|
||||
var totalMessages int64
|
||||
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
idx := 0
|
||||
for pb.Next() {
|
||||
a := &agents[idx%numAgents]
|
||||
a.sess.Send("Concurrent message", nil, nil)
|
||||
atomic.AddInt64(&totalMessages, 1)
|
||||
idx++
|
||||
}
|
||||
})
|
||||
|
||||
b.StopTimer()
|
||||
msgsPerSec := float64(totalMessages) / b.Elapsed().Seconds()
|
||||
b.ReportMetric(msgsPerSec, "msgs/sec")
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-402: Session Switch Latency
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_SessionSwitch(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
agent := fake.NewFakeAgent("bench-agent")
|
||||
|
||||
// Pre-create multiple sessions
|
||||
const numSessions = 10
|
||||
sessions := make([]core.AgentSession, numSessions)
|
||||
for i := 0; i < numSessions; i++ {
|
||||
sess, _ := agent.StartSession(ctx, "session-switch")
|
||||
sessions[i] = sess
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sess := sessions[i%numSessions]
|
||||
sess.Send("Switch test", nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-403: Memory Usage During Message Processing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_MemoryUsage(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
agent := fake.NewFakeAgent("bench-agent")
|
||||
sess, _ := agent.StartSession(ctx, "bench-session")
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportMetric(float64(b.N)*32, "bytes/op") // baseline estimate
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
sess.Send("Memory test message", nil, nil)
|
||||
// Consume events
|
||||
for e := range sess.Events() {
|
||||
if e.Done {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-404: Rate Limiter Performance
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_RateLimiter(b *testing.B) {
|
||||
rl := core.NewRateLimiter(1000, time.Second)
|
||||
defer rl.Stop()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
rl.Allow("bench-user")
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-405: Message Deduplication Performance
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_MessageDedup(b *testing.B) {
|
||||
dedup := &core.MessageDedup{}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
msgID := "bench-msg"
|
||||
dedup.IsDuplicate(msgID)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-406: Command Registry Lookup
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_CommandRegistryLookup(b *testing.B) {
|
||||
registry := core.NewCommandRegistry()
|
||||
|
||||
// Add commands
|
||||
for i := 0; i < 50; i++ {
|
||||
registry.Add("cmd", "Command", "{{1}}", "", "", "bench")
|
||||
}
|
||||
registry.Add("target", "Target command", "{{1}}", "", "", "bench")
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
registry.Resolve("target")
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-407: Card Rendering Performance
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_CardRendering(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
card := core.NewCard().
|
||||
Title("Benchmark Card", "blue").
|
||||
Markdown("## Section\nSome content here.").
|
||||
Markdown("- Item 1\n- Item 2\n- Item 3").
|
||||
Divider().
|
||||
Buttons(
|
||||
core.PrimaryBtn("Confirm", "act:/confirm"),
|
||||
core.DefaultBtn("Cancel", "act:/cancel"),
|
||||
core.DangerBtn("Delete", "act:/delete"),
|
||||
).
|
||||
Note("Footnote text").
|
||||
Build()
|
||||
|
||||
_ = card.RenderText()
|
||||
_ = card.CollectButtons()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-408: Cron Store Operations
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_CronStoreOperations(b *testing.B) {
|
||||
tmpDir := b.TempDir()
|
||||
store, _ := core.NewCronStore(tmpDir)
|
||||
|
||||
// Pre-populate
|
||||
for i := 0; i < 20; i++ {
|
||||
store.Add(&core.CronJob{
|
||||
ID: "bench-cron",
|
||||
Description: "Bench",
|
||||
Prompt: "Run",
|
||||
CronExpr: "0 9 * * *",
|
||||
Enabled: true,
|
||||
})
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
jobs := store.List()
|
||||
_ = len(jobs)
|
||||
store.SetEnabled("bench-cron", true)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-409: Session Creation Overhead
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_SessionCreation(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
agent := fake.NewFakeAgent("bench-agent")
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = agent.StartSession(ctx, "bench-session")
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-410: Session Send/Receive Overhead
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_SessionSendReceive(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
agent := fake.NewFakeAgent("bench-agent")
|
||||
sess, _ := agent.StartSession(ctx, "bench-session")
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sess.Send("Bench message", nil, nil)
|
||||
for e := range sess.Events() {
|
||||
if e.Done {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-411: Role Manager Resolution
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_RoleManagerResolution(b *testing.B) {
|
||||
manager := core.NewUserRoleManager()
|
||||
manager.Configure("viewer", []core.RoleInput{
|
||||
{Name: "admin", UserIDs: []string{"admin1", "admin2"}},
|
||||
{Name: "developer", UserIDs: []string{"dev1", "dev2"}},
|
||||
{Name: "viewer", UserIDs: []string{"*"}},
|
||||
})
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
manager.ResolveRole("admin1")
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-412: Concurrent Rate Limiter Access
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_ConcurrentRateLimiter(b *testing.B) {
|
||||
rl := core.NewRateLimiter(10000, time.Second)
|
||||
defer rl.Stop()
|
||||
|
||||
var counter int64
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
if rl.Allow("bench-user") {
|
||||
atomic.AddInt64(&counter, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.ReportMetric(float64(counter), "allowed")
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// T-413: Multi-Agent Coordination
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Benchmark_MultiAgentCoordination(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
numAgents := 5
|
||||
|
||||
agents := make([]*fake.FakeAgent, numAgents)
|
||||
for i := 0; i < numAgents; i++ {
|
||||
agents[i] = fake.NewFakeAgent("bench-agent")
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var wg sync.WaitGroup
|
||||
for j := 0; j < numAgents; j++ {
|
||||
wg.Add(1)
|
||||
go func(a *fake.FakeAgent) {
|
||||
defer wg.Done()
|
||||
sess, _ := a.StartSession(ctx, "coord-session")
|
||||
sess.Send("Coordinated message", nil, nil)
|
||||
}(agents[j])
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user