MCP HubMCP Hub
SKILL·C848DC

go-performance-review

eduardo-sl
Actualizado 28 days ago
7 vistas
70
9
70
Ver en GitHub
Desarrollogeneral

Acerca de

Esta habilidad identifica cuellos de botella de rendimiento y oportunidades de optimización en código Go, centrándose en asignaciones de memoria, manejo de cadenas y uso de estructuras de datos. Proporciona técnicas específicas como preasignación de slices, uso de sync.Pool y orientación sobre perfiles pprof. Úsala cuando necesites evaluar, perfilar u optimizar rutas críticas en tus aplicaciones Go.

Instalación rápida

Claude Code

Recomendado
Principal
npx skills add eduardo-sl/go-agent-skills -a claude-code
Comando PluginAlternativo
/plugin add https://github.com/eduardo-sl/go-agent-skills
Git CloneAlternativo
git clone https://github.com/eduardo-sl/go-agent-skills.git ~/.claude/skills/go-performance-review

Copia y pega este comando en Claude Code para instalar esta habilidad

Documentación

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.

Repositorio GitHub

eduardo-sl/go-agent-skills
Ruta: skills/(safety)/go-performance-review
0
FAQ

Preguntas frecuentes

¿Qué es el Skill go-performance-review?

go-performance-review es un Skill de Claude creado por eduardo-sl. Los Skills agrupan instrucciones y recursos que Claude carga cuando los necesita para realizar tareas relacionadas con go-performance-review sin indicaciones adicionales.

¿Cómo instalo go-performance-review?

Usa los comandos de instalación de esta página: añade go-performance-review a Claude Code como plugin o clona su repositorio en tu directorio de skills y reinicia Claude para cargarlo.

¿A qué categoría pertenece go-performance-review?

go-performance-review pertenece a la categoría Desarrollo.

¿Se puede usar go-performance-review gratis?

Sí. go-performance-review aparece en AIMCP y se puede instalar gratis.

Habilidades relacionadas

qmd
Desarrollo

qmd es una herramienta CLI de búsqueda e indexación local que permite a los desarrolladores indexar y buscar en archivos locales mediante búsqueda híbrida que combina BM25, embeddings vectoriales y reranking. Es compatible tanto con uso desde la línea de comandos como con modo MCP (Model Context Protocol) para integración con Claude. La herramienta utiliza Ollama para los embeddings y almacena los índices localmente, lo que la hace ideal para buscar documentación o bases de código directamente desde la terminal.

Ver habilidad
subagent-driven-development
Desarrollo

Esta habilidad ejecuta planes de implementación asignando un nuevo subagente para cada tarea independiente, con revisión de código entre tareas. Permite una iteración rápida mientras mantiene controles de calidad a través de este proceso de revisión. Úsala cuando trabajes en tareas mayormente independientes dentro de la misma sesión para garantizar un progreso continuo con verificaciones de calidad integradas.

Ver habilidad
mcporter
Desarrollo

La habilidad mcporter permite a los desarrolladores gestionar y llamar servidores del Protocolo de Contexto de Modelo (MCP) directamente desde Claude. Proporciona comandos para listar servidores disponibles, llamar a sus herramientas con argumentos, y manejar la autenticación y el ciclo de vida del daemon. Utiliza esta habilidad para integrar y probar la funcionalidad de servidores MCP en tu flujo de trabajo de desarrollo.

Ver habilidad
adk-deployment-specialist
Desarrollo

Esta habilidad despliega y orquesta agentes Vertex AI ADK utilizando el protocolo A2A, gestionando el descubrimiento de AgentCard, el envío de tareas y soportando herramientas como el Sandbox de Ejecución de Código y el Banco de Memoria. Permite construir sistemas multiagente con patrones de orquestación secuencial, paralela o en bucle en Python, Java o Go. Úsela cuando se le solicite desplegar agentes ADK u orquestar flujos de trabajo de agentes en Google Cloud.

Ver habilidad