MCP HubMCP Hub
SKILL·C848DC

go-performance-review

eduardo-sl
Обновлено 27 days ago
7 просмотров
69
9
69
Посмотреть на GitHub
Разработкаgeneral

О программе

Этот навык выявляет узкие места в производительности и возможности оптимизации в коде на Go, фокусируясь на аллокациях, работе со строками и использовании структур данных. Он предоставляет конкретные техники, такие как предварительное выделение срезов, использование sync.Pool и рекомендации по профилированию с помощью pprof. Используйте его, когда вам необходимо провести бенчмаркинг, профилирование или оптимизацию горячих участков в ваших Go-приложениях.

Быстрая установка

Claude Code

Рекомендуется
Основной
npx skills add eduardo-sl/go-agent-skills -a claude-code
Команда плагинаАльтернативный
/plugin add https://github.com/eduardo-sl/go-agent-skills
Git клонированиеАльтернативный
git clone https://github.com/eduardo-sl/go-agent-skills.git ~/.claude/skills/go-performance-review

Скопируйте и вставьте эту команду в Claude Code для установки этого навыка

Документация

Go Performance Review

Profile first, optimize second. Never optimize without a benchmark proving the problem.

1. Allocation Reduction

Prefer strconv over fmt for primitive conversions:

// ✅ Good — zero allocations for simple conversions
s := strconv.Itoa(42)
s := strconv.FormatFloat(3.14, 'f', 2, 64)

// ❌ Bad — fmt.Sprintf allocates
s := fmt.Sprintf("%d", 42)

Avoid unnecessary string-to-byte conversions:

// ✅ Good — use strings.Builder for concatenation
var b strings.Builder
for _, s := range parts {
    b.WriteString(s)
}
result := b.String()

// ❌ Bad — repeated concatenation allocates on every +
result := ""
for _, s := range parts {
    result += s
}

Preallocate slices and maps when size is known:

// ✅ Good — single allocation
users := make([]User, 0, len(ids))
for _, id := range ids {
    users = append(users, getUser(id))
}

// ✅ Good — map with capacity hint
lookup := make(map[string]User, len(users))

// ❌ Bad — repeated growing
var users []User // starts at 0, grows via doubling

Use sync.Pool for frequently allocated, short-lived objects:

var bufPool = sync.Pool{
    New: func() interface{} {
        return new(bytes.Buffer)
    },
}

func process(data []byte) string {
    buf := bufPool.Get().(*bytes.Buffer)
    defer func() {
        buf.Reset()
        bufPool.Put(buf)
    }()

    buf.Write(data)
    return buf.String()
}

2. Hot Path Optimizations

Avoid interface conversions in tight loops:

// ✅ Good — concrete type in loop
func sum(vals []int64) int64 {
    var total int64
    for _, v := range vals {
        total += v
    }
    return total
}

// ❌ Bad — interface{} causes boxing/unboxing
func sum(vals []interface{}) int64 { ... }

Avoid reflect in performance-critical paths:

If you need reflection-like behavior at scale, use code generation (go generate, stringer, protocol buffers).

Reduce pointer chasing:

// ✅ Good — contiguous memory, cache-friendly
type Points struct {
    X []float64
    Y []float64
}

// ❌ Slower — pointer chasing per element
type Points []*Point

3. Map Performance

// ✅ Use capacity hints
m := make(map[string]int, expectedSize)

// ✅ For read-heavy concurrent access, use sync.Map
// But ONLY when keys are stable — sync.Map has higher overhead
// for writes than a mutex-protected map.

// ✅ For fixed key sets, consider using a slice with index mapping
// instead of a map.

4. Benchmarking

ALWAYS write benchmarks before and after optimization:

func BenchmarkFoo(b *testing.B) {
    // Setup outside the loop
    input := generateInput()

    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        result = Foo(input) // assign to package-level var to prevent elision
    }
}

// Package-level var prevents compiler from eliminating the call
var result string

Run benchmarks with memory profiling:

go test -bench=BenchmarkFoo -benchmem -count=5 ./...

Compare before/after with benchstat:

go test -bench=. -count=10 > old.txt
# make changes
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txt

5. Profiling

CPU profiling:

go test -cpuprofile=cpu.prof -bench=BenchmarkFoo .
go tool pprof cpu.prof

Memory profiling:

go test -memprofile=mem.prof -bench=BenchmarkFoo .
go tool pprof -alloc_space mem.prof

HTTP server profiling (import net/http/pprof):

import _ "net/http/pprof"

// Access at http://localhost:6060/debug/pprof/
go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

6. High-Throughput Logging

log/slog is the right default for most services. But when benchmarks show logging is a bottleneck (high-frequency hot paths, >100k log lines/sec), consider zero-allocation loggers.

When slog is not enough:

// slog allocates per log call — fine for most services
slog.Info("request handled",
    slog.String("method", method),
    slog.Int("status", status),
)

// In hot paths where benchmarks prove logging is a bottleneck,
// use zap's zero-allocation core:
logger, _ := zap.NewProduction()
logger.Info("request handled",
    zap.String("method", method),
    zap.Int("status", status),
)
// zap avoids allocations by using a field pool and typed fields

Decision tree:

ScenarioLogger
General service logginglog/slog (stdlib, zero dependencies)
High-frequency hot path (>100k lines/sec)go.uber.org/zap (zero-alloc)
Extreme throughput with JSONgithub.com/rs/zerolog (zero-alloc JSON)

Best of both worlds — use zap as slog backend:

// Use slog API everywhere, backed by zap's performance
zapLogger, _ := zap.NewProduction()
slogHandler := zapslog.NewHandler(zapLogger.Core(), nil)
logger := slog.New(slogHandler)

// Code uses standard slog API — can swap backend without changing callers
logger.Info("request handled",
    slog.String("method", method),
    slog.Int("status", status),
)

Logging anti-patterns in hot paths:

// ❌ Bad — logging inside tight loop
for _, item := range millions {
    slog.Info("processing item", slog.String("id", item.ID))
    process(item)
}

// ✅ Good — sample or batch log
for i, item := range millions {
    process(item)
    if i%10000 == 0 {
        slog.Info("progress", slog.Int("processed", i), slog.Int("total", len(millions)))
    }
}

// ✅ Good — log summary after loop
slog.Info("batch complete", slog.Int("count", len(millions)))

NEVER switch loggers without a benchmark proving the need. slog is fast enough for the vast majority of Go services.

7. Common Anti-Patterns

Anti-PatternFix
fmt.Sprintf for simple int→stringstrconv.Itoa
String concatenation in loopstrings.Builder
Slice without preallocationmake([]T, 0, n)
Map without capacity hintmake(map[K]V, n)
regexp.Compile inside functionCompile once at package level
json.Marshal in hot pathUse code-gen (easyjson, sonic)
Logging in tight loopBatch or sample
defer in very tight inner loopManual cleanup (rare, benchmark first)

Important Caveat

Most Go code is not performance-critical. Readability and correctness ALWAYS take priority over micro-optimizations. Only apply these patterns when:

  1. A benchmark proves this code path is a bottleneck
  2. The optimization is significant (>10% improvement)
  3. The resulting code remains readable and maintainable

Premature optimization is still the root of all evil, even in Go.

GitHub репозиторий

eduardo-sl/go-agent-skills
Путь: skills/(safety)/go-performance-review
0
FAQ

Часто задаваемые вопросы

Что такое Skill go-performance-review?

go-performance-review — это Claude Skill от eduardo-sl. Skills объединяют инструкции и ресурсы, которые Claude загружает по мере необходимости, чтобы выполнять задачи, связанные с go-performance-review, без дополнительных запросов.

Как установить go-performance-review?

Используйте команды установки на этой странице: добавьте go-performance-review в Claude Code как плагин или клонируйте репозиторий в каталог skills, затем перезапустите Claude, чтобы загрузить Skill.

К какой категории относится go-performance-review?

go-performance-review относится к категории Разработка.

Можно ли использовать go-performance-review бесплатно?

Да. go-performance-review размещён на AIMCP и доступен для бесплатной установки.

Похожие навыки

qmd
Разработка

qmd — это локальный инструмент командной строки для поиска и индексирования, который позволяет разработчикам индексировать и осуществлять поиск по локальным файлам с использованием гибридного поиска, сочетающего BM25, векторные эмбеддинги и реранкинг. Он поддерживает как использование через командную строку, так и режим MCP (Model Context Protocol) для интеграции с Claude. Инструмент использует Ollama для создания эмбеддингов и хранит индексы локально, что делает его идеальным для поиска по документации или кодовой базе прямо из терминала.

Просмотреть навык
subagent-driven-development
Разработка

Этот навык выполняет планы реализации, создавая нового суб-агента для каждой независимой задачи, проводя проверку кода между задачами. Он позволяет быстро итерировать, сохраняя контроль качества через этот процесс ревью. Используйте его при работе в основном с независимыми задачами в рамках одной сессии, чтобы обеспечить непрерывный прогресс со встроенными проверками качества.

Просмотреть навык
mcporter
Разработка

Навык mcporter позволяет разработчикам управлять и вызывать серверы Model Context Protocol (MCP) напрямую из Claude. Он предоставляет команды для вывода списка доступных серверов, вызова их инструментов с аргументами, а также для обработки аутентификации и управления жизненным циклом демона. Используйте этот навык для интеграции и тестирования функциональности серверов MCP в вашем рабочем процессе разработки.

Просмотреть навык
adk-deployment-specialist
Разработка

Этот навык развертывает и оркестрирует агентов Vertex AI ADK с использованием протокола A2A, управляя обнаружением AgentCard, отправкой задач и поддерживая инструменты, такие как песочница для выполнения кода и Memory Bank. Он позволяет создавать мультиагентные системы с последовательными, параллельными или циклическими схемами оркестрации на Python, Java или Go. Используйте его, когда требуется развернуть агентов ADK или оркестрировать рабочие процессы агентов в Google Cloud.

Просмотреть навык