### Set Up Go Optimization Guide Environment Source: https://github.com/astavonin/go-optimization-guide/blob/main/README.md This script sets up a Python virtual environment and installs all necessary dependencies for building and serving the Go Optimization Guide locally using MkDocs. ```Shell source ./env.sh ``` -------------------------------- ### Serve Go Optimization Guide Locally Source: https://github.com/astavonin/go-optimization-guide/blob/main/README.md Starts a local MkDocs server to preview the Go Optimization Guide. The site will be accessible at http://localhost:8000. ```Shell mkdocs serve ``` -------------------------------- ### Setup Benchmark Environment for Go File I/O Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/zero-copy.md Provides bash commands to install the necessary Go package (golang.org/x/exp/mmap) and create a test file for benchmarking file I/O operations. ```bash go get golang.org/x/exp/mmap mkdir -p testdata dd if=/dev/urandom of=./testdata/largefile.bin bs=1M count=4 ``` -------------------------------- ### Install wrk Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Installs the wrk HTTP benchmarking tool, typically via a package manager like Homebrew. ```bash brew install wrk # or build from source ``` -------------------------------- ### Install k6 using Homebrew Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Command to install the k6 load testing tool using the Homebrew package manager. ```bash brew install k6 ``` -------------------------------- ### Go Runtime Tracing Setup Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/10k-connections.md This Go code snippet demonstrates how to enable runtime tracing. It creates a trace file and starts the trace, ensuring it's stopped and the file is closed when the function exits. ```go import ( "runtime/trace" "os" "log" ) func main() { f, err := os.Create("trace.out") if err != nil { log.Fatal(err) } defer f.Close() trace.Start(f) defer trace.Stop() // server logic ... } ``` -------------------------------- ### Install Vegeta Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Installs the Vegeta HTTP load testing tool using Go's package management. ```bash go install github.com/tsenart/vegeta@latest ``` -------------------------------- ### Go: Structured Logging with Zap Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/connection_observability.md Provides an example of structured logging using Uber's Zap library in Go. It demonstrates logging key-value pairs for better data correlation and easier parsing by log aggregation systems. ```go import ( "go.uber.org/zap" ) var logger, _ = zap.NewProduction() logger.Info("dns", zap.String("host", hostname), zap.Duration("duration", elapsed), zap.Strings("ips", ips), zap.Error(err), ) ``` -------------------------------- ### QUIC 0-RTT Client/Server Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/quic-in-go.md Demonstrates a QUIC client and server setup that utilizes 0-RTT for faster connection establishment on subsequent sessions. Includes code for both the client and server, along with expected console output to verify successful 0-RTT data transmission. ```Go package main import ( "context" "crypto/tls" "fmt" "log" "net" "time" "github.com/quic-go/quic-go" ) const ( serverAddr = "localhost:4242" ) func main() { // Server setup go func() { ln, err := quic.ListenAddr(serverAddr, generateTLSConfig(), &quic.Config{ Enable0RTT: true, }) if err != nil { log.Fatal(err) } defer ln.Close() // Ensure the listener is closed log.Printf("QUIC server listening on %s\n", serverAddr) for { conn, err := ln.Accept(context.Background()) if err != nil { log.Printf("Error accepting connection: %v\n", err) continue } go handleConnection(conn) } }() // Client setup time.Sleep(1 * time.Second) // Give the server a moment to start // First connection (to establish session for 0-RTT) conn1, err := quic.DialAddrEarly(serverAddr, &tls.Config{ InsecureSkipVerify: true, // For testing purposes }, &quic.Config{ Enable0RTT: true, }) if err != nil { log.Fatalf("Client 1 dial error: %v\n", err) } defer conn1.Close() // Ensure the connection is closed stream1, err := conn1.OpenStreamSync(context.Background()) if err != nil { log.Fatalf("Client 1 open stream error: %v\n", err) } defer stream1.Close() // Ensure the stream is closed fmt.Fprintf(stream1, "Hello over 0-RTT\n") log.Printf("Client 1 sent: Hello over 0-RTT\n") // Second connection (should use 0-RTT) conn2, err := quic.DialAddrEarly(serverAddr, &tls.Config{ InsecureSkipVerify: true, // For testing purposes }, &quic.Config{ Enable0RTT: true, }) if err != nil { log.Fatalf("Client 2 dial error: %v\n", err) } defer conn2.Close() // Ensure the connection is closed stream2, err := conn2.OpenStreamSync(context.Background()) if err != nil { log.Fatalf("Client 2 open stream error: %v\n", err) } defer stream2.Close() // Ensure the stream is closed fmt.Fprintf(stream2, "Hello again over 0-RTT\n") log.Printf("Client 2 sent: Hello again over 0-RTT\n") // Keep the main goroutine alive to see server output select {} } func handleConnection(conn quic.Connection) { defer conn.CloseWithError(0, "") // Ensure connection is closed when done for { stream, err := conn.AcceptStream(context.Background()) if err != nil { log.Printf("Error accepting stream: %v\n", err) return } go func(stream quic.Stream) { defer stream.Close() // Ensure stream is closed buf := make([]byte, 1024) n, err := stream.Read(buf) if err != nil { log.Printf("Error reading from stream: %v\n", err) return } log.Printf("Received: %s\n", string(buf[:n])) }(stream) } } func generateTLSConfig() *tls.Config { return &tls.Config{ InsecureSkipVerify: true, // For testing purposes NextProtos: []string{"quic"}, // Indicate QUIC support } } ``` -------------------------------- ### Start Local pprof HTTP Server Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Command to start a local HTTP server for the pprof tool, allowing interactive exploration of profile data. It specifies the output file to analyze. ```bash go tool pprof -http=:7070 cpu.prof ``` -------------------------------- ### Install quic-go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/quic-in-go.md Installs the quic-go library using Go modules. This is the first step to using quic-go in your Go projects. ```bash go get github.com/quic-go/quic-go ``` -------------------------------- ### Go Slice Growth Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/mem-prealloc.md Demonstrates the default growth behavior of a Go slice when elements are appended without preallocation. It prints the length and capacity after each append operation, illustrating how capacity increases. ```go s := make([]int, 0) for i := 0; i < 10_000; i++ { s = append(s, i) fmt.Printf("Len: %d, Cap: %d\n", len(s), cap(s)) } ``` -------------------------------- ### Complete Go Benchmark File Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/zero-copy.md Displays the full content of a Go benchmark file, likely containing various performance tests, including the file I/O benchmarks discussed. ```go package optimization import ( "os" "testing" "golang.org/x/exp/mmap" ) // bench-io-start func BenchmarkReadWithCopy(b *testing.T) { file, _ := os.Open("./testdata/largefile.bin") defer file.Close() buffer := make([]byte, 4*1024*1024) b.SetBytes(int64(len(buffer))) b.ResetTimer() for i := 0; i < b.N; i++ { file.ReadAt(buffer, 0) } } func BenchmarkReadWithMmap(b *testing.T) { file, _ := os.Open("./testdata/largefile.bin") defer file.Close() mappedFile, _ := mmap.Open(file.Name()) defer mappedFile.Unmap() buffer := mappedFile.Bytes(0, mappedFile.Len()) b.SetBytes(int64(len(buffer))) b.ResetTimer() for i := 0; i < b.N; i++ { _ = buffer } } // bench-io-end // bench-interface-start func BenchmarkInterfaceBoxing(b *testing.T) { var i interface{} = 10 for n := 0; n < b.N; n++ { _ = i.(int) } } // bench-interface-end ``` -------------------------------- ### Go Scheduler Trace Output Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/a-bit-more-tuning.md An example of the detailed output generated by Go's scheduler tracing, showing global scheduler state, per-processor (P) statistics, and OS thread (M) information. ```Log SCHED 3024ms: gomaxprocs=14 idleprocs=14 threads=26 spinningthreads=0 needspinning=0 idlethreads=20 runqueue=0 gcwaiting=false nmidlelocked=1 stopwait=0 sysmonwait=false P0: status=0 schedtick=173 syscalltick=3411 m=nil runqsize=0 gfreecnt=6 timerslen=0 ... P13: status=0 schedtick=96 syscalltick=310 m=nil runqsize=0 gfreecnt=2 timerslen=0 M25: p=nil curg=nil mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=nil ... ``` -------------------------------- ### Go UDP Listen Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/efficient-net-use.md Provides an example of listening for UDP packets using `net.ListenUDP` in Go, suitable for fire-and-forget telemetry or high-volume, low-consequence data pipelines. ```go conn, _ := net.ListenUDP("udp", &net.UDPAddr{Port: 9999}) ... ``` -------------------------------- ### Go Lazy Initialization (sync.Once) Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/index.md Delay expensive setup logic until it's actually needed using `sync.Once`. This ensures that initialization code runs exactly once, even when called concurrently. ```go package main import ( "fmt" "sync" "time" ) var config *string var once sync.Once func getConfig() *string { once.Do(func() { // Simulate expensive initialization time.Sleep(2 * time.Second) s := "Initialized Configuration" config = &s fmt.Println("Configuration initialized.") }) return config } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() cfg := getConfig() fmt.Printf("Goroutine %d got config: %s\n", id, *cfg) }(i) } wg.Wait() } ``` -------------------------------- ### Basic HTTP GET Request in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/efficient-net-use.md Demonstrates a simple HTTP GET request using Go's http.Client. It highlights the importance of proper connection handling and potential issues with default configurations under load. ```Go client := &http.Client{ Timeout: 5 * time.Second, } resp, err := client.Get("http://localhost:8080/data") if err != nil { log.Fatal(err) } defer resp.Body.Close() ``` -------------------------------- ### Efficient Slice Appending with Preallocation Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/mem-prealloc.md Demonstrates an efficient method for building a slice by preallocating its capacity using `make`. This avoids intermediate reallocations and copying, improving performance. ```go // Efficient result := make([]int, 0, 10000) for i := 0; i < 10000; i++ { result = append(result, i) } ``` -------------------------------- ### Analyzing Memory Profile Data Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Command to load and analyze a saved memory profile file. The `-http=:7070` flag starts a web server for interactive analysis. ```bash go tool pprof -http=:7070 mem.prof ``` -------------------------------- ### Go net.Conn Listen Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/efficient-net-use.md Demonstrates how to listen for incoming TCP connections using `net.Conn` in Go. This provides raw socket access for custom protocol handling. ```go ln, err := net.Listen("tcp", ":9000") ... ``` -------------------------------- ### Go: Wrap Syscalls with RawConn Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/low-level-optimizations.md Demonstrates how to use `net.ListenConfig` and `syscall.RawConn` in Go to safely execute custom syscalls during socket setup. This ensures options are set at the correct time before the Go runtime manages the socket. ```Go listenerConfig := net.ListenConfig{ Control: func(network, address string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { // Custom syscall here; safely handled means it executes within the correct context, // before the socket is handed over to the Go runtime, with proper error checking and synchronization }) }, } ``` -------------------------------- ### Go: Configurable Log Level with Zap Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/connection_observability.md Demonstrates how to set up a logger with an atomic log level that can be adjusted at runtime. This allows for dynamic control over log verbosity, useful for debugging or reducing noise in production. ```go atomicLevel := zap.NewAtomicLevel() logger := zap.New(zapcore.NewCore( zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), zapcore.AddSync(os.Stdout), atomicLevel, )) // Adjust at runtime atomicLevel.SetLevel(zap.WarnLevel) ``` -------------------------------- ### Common Go Performance Patterns Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/index.md Covers essential performance patterns in Go, including proper use of sync.Pool, reducing allocations, struct layout, efficient error handling, interface usage, and in-place sorting. ```Go import "sync" // Example of using sync.Pool var pool = sync.Pool{ New: func() interface{} { // Create a new item if pool is empty return &MyStruct{} }, } func processItem() { item := pool.Get().(*MyStruct) // Get item from pool // ... use item ... pool.Put(item) // Return item to pool } type MyStruct struct { // ... fields ... } ``` ```Go // Example of reducing unnecessary allocations func processData(data []byte) { // Instead of creating new slices frequently, reuse existing ones or process in place // Example: Avoid data = append(data, newData...) // Consider processing data directly from the input slice if possible. } ``` ```Go // Example of efficient error handling on the fast path func performAction(input int) (int, error) { if input < 0 { // Avoid complex error formatting or logging on the fast path return 0, fmt.Errorf("invalid input: %d", input) } // ... perform action ... return result, nil } ``` ```Go // Example of interface usage without performance penalty // Define an interface type Reader interface { Read(p []byte) (n int, err error) } // Implement the interface with a struct type MyReader struct {} func (r *MyReader) Read(p []byte) (n int, err error) { // ... implementation ... return len(p), nil } // Use the interface func readData(r Reader) { buf := make([]byte, 1024) r.Read(buf) } ``` ```Go // Example of sorting in-place import "sort" func sortSlice(slice []int) { sort.Ints(slice) // Sorts the slice in-place } ``` -------------------------------- ### Efficient Map Population with Preallocation Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/mem-prealloc.md Demonstrates an efficient method for populating a Go map by preallocating its capacity. This helps the runtime allocate sufficient internal storage upfront, reducing rehashing and resizing costs. ```go // Efficient m := make(map[int]string, 10000) for i := 0; i < 10000; i++ { m[i] = fmt.Sprintf("val-%d", i) } ``` -------------------------------- ### Basic QUIC Server Initialization Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/quic-in-go.md Initializes a basic QUIC server by listening on a UDP address. Unlike TCP, QUIC requires TLS configuration from the start as all connections are encrypted. ```go { include-markdown "02-networking/src/quic_server.go" start="// quic-server-init-start" end="// quic-server-init-end" } ``` -------------------------------- ### Efficient Slice Population with Preallocation Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/mem-prealloc.md Shows an efficient way to populate a slice when its final size is known. By creating the slice with the exact size, it avoids bounds checks during assignment, further optimizing performance. ```go // Efficient result := make([]int, 10000) for i := range result { result[i] = i } ``` -------------------------------- ### Go sync.Once for Thread-Safe Initialization Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/lazy-init.md Demonstrates how to use `sync.Once` in Go to ensure a block of code executes exactly once, even in concurrent environments. This is crucial for thread-safe, one-time setup of resources. ```go package main import ( "fmt" "sync" ) var once sync.Once func setup() { fmt.Println("Initialization complete.") } func main() { // Multiple goroutines can call Do, but setup() will only run once. go func() { once.Do(setup) fmt.Println("Goroutine 1 finished.") }() go func() { once.Do(setup) fmt.Println("Goroutine 2 finished.") }() // Keep main running long enough for goroutines to execute var input string fmt.Scanln(&input) } ``` -------------------------------- ### Go: Sampling Logs with Zap Sampler Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/connection_observability.md Illustrates how to use Zap's sampling capabilities to control the rate of log messages. This is useful for reducing log volume under high load by logging only a subset of events. ```go core := zapcore.NewSamplerWithOptions( logger.Core(), time.Second, 100, // first 100 per second 10, // thereafter ) logger := zap.New(core) ``` -------------------------------- ### High-Performance Networking in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/index.md Focuses on building fast and reliable network services in Go, covering efficient use of standard library components like net/http and net.Conn, concurrency management, and transport protocol tuning. ```Go import ( "net/http" "time" ) func createHttpClient() *http.Client { client := &http.Client{ Timeout: 30 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, }, } return client } ``` ```Go import ( "net" "fmt" ) func handleConnection(conn net.Conn) { defer conn.Close() // Read from and write to the connection buffer := make([]byte, 1024) n, err := conn.Read(buffer) if err != nil { fmt.Println("Error reading:", err) return } fmt.Printf("Received: %s\n", buffer[:n]) // ... process data and write response ... } ``` ```Go import "runtime" func tuneScheduler() { // Set the number of operating system threads that can execute Go code simultaneously. // Defaults to the number of logical CPUs. // runtime.GOMAXPROCS(runtime.NumCPU()) // For specific tuning, you might adjust this based on workload. } ``` -------------------------------- ### QUIC in Go: Building Low-Latency Services with quic-go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Explore QUIC as a next-gen transport for real-time and mobile-first systems. Introduce the `quic-go` library, demonstrate setup for secure multiplexed streams, and compare performance against HTTP/2 and TCP. Also covers connection migration and 0-RTT for fast startup. ```Go package main import ( "context" "crypto/tls" "fmt" "io" "log" "time" "github.com/quic-go/quic-go" "github.com/quic-go/quic-go/quic實" ) // --- QUIC Server --- func handleQUICStream(stream quic實.Stream) { defer stream.Close() log.Printf("QUIC Stream opened: %s\n", stream.StreamID()) // Set a read deadline stream.SetReadDeadline(time.Now().Add(5 * time.Minute)) buffer := make([]byte, 1024) for { n, err := stream.Read(buffer) if err != nil { if err == io.EOF { log.Printf("QUIC Stream %s closed by client\n", stream.StreamID()) break } if netErr, ok := err.(net.Error); ok && netErr.Timeout() { log.Printf("QUIC Stream %s read deadline exceeded\n", stream.StreamID()) break } log.Printf("QUIC Stream %s read error: %v\n", stream.StreamID(), err) break } log.Printf("QUIC Stream %s Received: %s\n", stream.StreamID(), buffer[:n]) // Echo back _, err = stream.Write([]byte("ACK QUIC\n")) if err != nil { log.Printf("QUIC Stream %s write error: %v\n", stream.StreamID(), err) break } // Reset deadline stream.SetReadDeadline(time.Now().Add(5 * time.Minute)) } } func main() { // Generate a self-signed certificate for TLS // In production, use a proper certificate. cer, err := tls.LoadX509KeyPair("server.pem", "server.key") if err != nil { log.Fatalf("Failed to load TLS key pair: %v\n", err) } config := &tls.Config{ Certificates: []tls.Certificate{cer}, NextProtos: []string{"quic"}, // Specify ALPN for QUIC } listener, err := quic實.Listen(":8080", config, nil) // nil for default QUIC config if err != nil { log.Fatalf("QUIC Listen error: %v\n", err) } defer listener.Close() log.Println("QUIC server listening on :8080") for { conn, err := listener.Accept(context.Background()) if err != nil { log.Printf("QUIC Accept error: %v\n", err) continue } log.Printf("QUIC connection accepted: %s\n", conn.RemoteAddr()) // Handle streams within the connection go func() { for { stream, err := conn.AcceptStream(context.Background()) if err != nil { log.Printf("QUIC AcceptStream error: %v\n", err) break } go handleQUICStream(stream) } }() } } ``` -------------------------------- ### Use sync.Pool for Reusable Short-Lived Objects Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/gc.md Illustrates using `sync.Pool` to manage temporary, reusable allocations that are expensive to garbage collect. The example shows getting a `bytes.Buffer` from the pool, resetting it, using it, and then putting it back into the pool. This reduces GC pressure by reusing objects. ```go var bufPool = sync.Pool{ New: func() any { return new(bytes.Buffer) }, } func handler(w http.ResponseWriter, r *http.Request) { buf := bufPool.Get().(*bytes.Buffer) buf.Reset() defer bufPool.Put(buf) // Use buf... } ``` -------------------------------- ### Benchmarking and Load Testing Go Network Apps Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Establish performance baselines before optimizing anything. Learn how to simulate realistic traffic using tools like `vegeta`, `wrk`, and `k6`. Covers throughput, latency percentiles, connection concurrency, and profiling under load. Sets the foundation for diagnosing bottlenecks and measuring the impact of every optimization in the series. ```Go // Example usage of vegeta for load testing // vegeta attack -duration=30s -targets=targets.txt ``` ```Go // Example usage of wrk for load testing // wrk -t4 -c100 -d30s http://localhost:8080 ``` ```Go // Example usage of k6 for load testing // k6 run script.js ``` -------------------------------- ### Running the Benchmarking App Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Command to run the Go benchmarking application from the source file. ```bash go run main.go ``` -------------------------------- ### Go Benchmark Setup for Interface Boxing Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/interface-boxing.md Provides the Go code used for benchmarking the performance impact of interface boxing with large structs versus pointers. This setup includes the interface definition and the struct implementation. ```go // interface-start type InterfaceBoxing interface { Method() float64 } type LargeStruct struct { Data [4096]byte // 4KB payload } func (ls LargeStruct) Method() float64 { return float64(ls.Data[0]) } // interface-end ``` -------------------------------- ### Go Struct Field Alignment Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/fields-alignment.md Demonstrates the difference in memory layout and size between a poorly aligned struct and a well-aligned struct in Go. The example highlights how ordering fields by alignment requirement can reduce padding and memory footprint. ```Go type PoorlyAligned struct { A uint8 B uint64 C uint16 } type WellAligned struct { B uint64 C uint16 A uint8 } ``` -------------------------------- ### GOMAXPROCS, epoll/kqueue, and Scheduler Tuning in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Dive into low-level performance knobs like `GOMAXPROCS`, `GODEBUG`, thread pinning, and how Go’s scheduler interacts with epoll/kqueue. Learn when increasing parallelism helps—and when it doesn’t. Includes tools for CPU affinity and benchmarking the effect of these changes. ```Go package main import ( "fmt" "runtime" "time" ) func worker(id int) { fmt.Printf("Worker %d starting\n", id) time.Sleep(2 * time.Second) fmt.Printf("Worker %d done\n", id) } func main() { // Set GOMAXPROCS to the number of available logical CPUs numCPU := runtime.NumCPU() runtime.GOMAXPROCS(numCPU) fmt.Printf("GOMAXPROCS set to: %d\n", runtime.GOMAXPROCS(0)) // Example of starting goroutines for i := 0; i < 5; i++ { go worker(i) } // Keep the main goroutine alive to see worker output time.Sleep(5 * time.Second) // To observe scheduler behavior with epoll/kqueue, you would typically // run network-intensive applications and monitor system calls or use profiling tools. // The Go runtime automatically uses epoll on Linux and kqueue on macOS/BSD. // Example of using GODEBUG (e.g., to trace scheduler) // You would typically set this as an environment variable before running: // export GODEBUG=schedtrace=1000 // This prints scheduler information every 1000 GC cycles. } ``` -------------------------------- ### Vegeta: Generate Performance Chart Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Creates an HTML file visualizing the load testing results, providing a graphical representation of performance metrics. ```bash vegeta plot < results.bin > plot.html ``` -------------------------------- ### Prefer Stack Allocation Over Heap Allocation Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/gc.md Demonstrates how to avoid escaping variables to the heap by preferring value types when a pointer is unnecessary. The 'BAD' example shows a function returning a pointer to a heap-allocated struct, while the 'BETTER' example uses value types for efficiency. Use `go build -gcflags="-m"` to view escape analysis diagnostics. ```go // BAD: returns pointer to heap-allocated struct func newUser(name string) *User { return &User{Name: name} // escapes to heap } // BETTER: use value types if pointer is unnecessary func printUser(u User) { fmt.Println(u.Name) } ``` -------------------------------- ### Go Interface Boxing: Logging Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/interface-boxing.md Illustrates that implicit boxing for short-lived values, such as in logging statements, is generally acceptable due to minimal overhead. ```go fmt.Println("value:", someStruct) // implicit boxing is fine ``` -------------------------------- ### Run k6 Load Test Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/bench-and-load.md Command to execute a k6 load testing script. ```bash k6 run script.js ``` -------------------------------- ### Go Networking Internals: Concurrency and net Package Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Understand Go’s approach to networking from the ground up. Covers how goroutines, the `net` package, and the runtime scheduler interact, including blocking I/O behavior, connection handling, and the use of pollers like `epoll` or `kqueue` under the hood. ```Go package main import ( "fmt" "net" "sync" ) func handleConnection(conn net.Conn) { defer conn.Close() // Read from connection buffer := make([]byte, 1024) _, err := conn.Read(buffer) if err != nil { fmt.Println("Error reading:", err) return } fmt.Printf("Received: %s\n", buffer) // Write to connection _, err = conn.Write([]byte("Hello from Go!")) if err != nil { fmt.Println("Error writing:", err) return } } func main() { listener, err := net.Listen("tcp", ":8080") if err != nil { fmt.Println("Error listening:", err) return } defer listener.Close() fmt.Println("Server listening on :8080") var wg sync.WaitGroup for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } wg.Add(1) go func() { defer wg.Done() handleConnection(conn) }() } wg.Wait() } ``` -------------------------------- ### Stack vs Heap Allocation Examples Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/stack-alloc.md Demonstrates how returning a pointer to a local variable causes it to escape to the heap, while returning a value keeps it on the stack. ```go func allocate() *int { x := 42 return &x // x escapes to the heap } func noEscape() int { x := 42 return x // x stays on the stack } ``` -------------------------------- ### Go Interface Boxing: Acceptable Abstraction Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/interface-boxing.md Example of using an interface for abstraction where performance implications of boxing are secondary to design benefits like decoupling and testability. ```go type Storage interface { Save([]byte) error } func Process(s Storage) { /* ... */ } ``` -------------------------------- ### Efficient Use of net/http, net.Conn, and UDP in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Compare idiomatic and advanced usage of `net/http` vs raw `net.Conn`. Dive into connection pooling, custom dialers, stream reuse, and buffer tuning. Demonstrates how to avoid common pitfalls like leaking connections, blocking handlers, or over-allocating buffers. ```Go package main import ( "fmt" "io" "net" "net/http" "time" ) func handleHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from HTTP!") } func main() { // HTTP Server Example http.HandleFunc("/", handleHTTP) go http.ListenAndServe(":8080", nil) // Raw TCP Client Example conn, err := net.DialTimeout("tcp", "localhost:8080", 5*time.Second) if err != nil { fmt.Println("Error dialing TCP:", err) return } defer conn.Close() _, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")) if err != nil { fmt.Println("Error writing TCP:", err) return } response, err := io.ReadAll(conn) if err != nil { fmt.Println("Error reading TCP:", err) return } fmt.Printf("TCP Response: %s\n", response) // UDP Example (Client) udpAddr, err := net.ResolveUDPAddr("udp", "localhost:8081") if err != nil { fmt.Println("Error resolving UDP address:", err) return } connUDP, err := net.DialUDP("udp", nil, udpAddr) if err != nil { fmt.Println("Error dialing UDP:", err) return } defer connUDP.Close() _, err = connUDP.Write([]byte("Hello UDP!")) if err != nil { fmt.Println("Error writing UDP:", err) return } fmt.Println("Sent UDP message") } ``` -------------------------------- ### Middleware for Rate Limiting with Context Values Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/context.md Provides an example of middleware that embeds rate-limiting decisions into the request context. Downstream handlers can then inspect this context value. ```go func rateLimitMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Suppose this is the result of some rate-limiting logic rateLimited := true // or false depending on logic // Embed the result into the context ctx := context.WithValue(r.Context(), "rateLimited", rateLimited) // Pass the updated context to the next handler next.ServeHTTP(w, r.WithContext(ctx)) }) } ``` -------------------------------- ### Inefficient Map Population Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/mem-prealloc.md Illustrates an inefficient way to populate a Go map without specifying its initial capacity. This can lead to rehashing and resizing overhead as elements are added. ```go // Inefficient m := make(map[int]string) for i := 0; i < 10000; i++ { m[i] = fmt.Sprintf("val-%d", i) } ``` -------------------------------- ### Build Fully Static Binaries with CGO and netgo Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/comp-flags.md Creates a fully statically linked Go binary, useful for minimal container environments. It uses CGO and the `netgo` build tag to ensure all C libraries and the DNS resolver are statically included. ```bash CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ CC=gcc \ go build -tags netgo -ldflags="-linkmode=external -extldflags '-static'" -o app main.go ``` -------------------------------- ### Go Interface Boxing: Small Value Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/interface-boxing.md Demonstrates that boxing small, copyable values like integers typically incurs no allocations and is considered safe and cheap. ```go var i interface{} i = 123 // safe and cheap ``` -------------------------------- ### Managing 10K++ Concurrent Connections in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Handling massive concurrency requires intentional architecture. Explore how to efficiently serve 10,000+ concurrent sockets using Go’s goroutines, proper resource capping, socket tuning, and runtime configuration. Focuses on connection lifecycles, scaling pitfalls, and real-world tuning. ```Go // This is a conceptual example. Actual implementation requires careful resource management. package main import ( "fmt" "net" "os" "os/signal" "runtime" "syscall" "time" ) func handleClient(conn net.Conn) { defer conn.Close() // Simulate work time.Sleep(1 * time.Minute) } func main() { // Set GOMAXPROCS to utilize available CPU cores runtime.GOMAXPROCS(runtime.NumCPU()) listener, err := net.Listen("tcp", ":8080") if err != nil { fmt.Println("Error listening:", err) return } defer listener.Close() fmt.Println("Server listening on :8080") // Channel to listen for OS signals c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c fmt.Println("\nShutting down server...") listener.Close() // Close listener to stop accepting new connections os.Exit(0) }() for { conn, err := listener.Accept() if err != nil { // Check if the error is due to listener closure if netErr, ok := err.(net.Error); ok && netErr.Temporary() { fmt.Println("Temporary accept error:", err) time.Sleep(100 * time.Millisecond) continue } else if err.Error() == "use of closed network connection" { fmt.Println("Listener closed, stopping accept loop.") break } fmt.Println("Error accepting connection:", err) continue } // Handle each connection in a new goroutine go handleClient(conn) } } ``` -------------------------------- ### Go Network Read Operation Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/a-bit-more-tuning.md A simplified Go function demonstrating how a goroutine handles reading from a network connection. It shows the loop for reading data and how the goroutine might be parked if data is not immediately available, relying on the poller for wakeups. ```go func pollAndRead(conn net.Conn) ([]byte, error) { buf := make([]byte, 4096) for { n, err := conn.Read(buf) if n > 0 { return buf[:n], nil } if err != nil && !isTemporary(err) { return nil, err } // Data not ready yet — goroutine will be parked until poller wakes it } } ``` -------------------------------- ### Go Interface Boxing Example Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/01-common-patterns/interface-boxing.md Demonstrates the basic concept of interface boxing in Go by assigning an integer to an empty interface. This shows how Go wraps the value and its type information. ```go var i interface{} i = 42 ``` -------------------------------- ### Circuit Breaker Initialization Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/resilient-connection-handling.md Go function to create and initialize a new CircuitBreaker. It sets up the sliding window and starts a background ticker for window advancement. ```go func NewCircuitBreaker(errThresh int, succThresh int, interval, reset time.Duration, halfOpenMax int32) *CircuitBreaker { cb := &CircuitBreaker{ failures: newWindow(60), errorThresh: errThresh, successThresh: int32(succThresh), interval: interval, resetTimeout: reset, halfOpenMaxConcurrent: halfOpenMax, } go func() { ticker := time.NewTicker(interval) for range ticker.C { cb.failures.Tick() } }() return cb } ``` -------------------------------- ### Optimizing TLS for Speed in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Tune Go services for fast and secure TLS by enabling session resumption, choosing fast cipher suites, using ALPN negotiation wisely, and minimizing certificate verification cost. Includes examples with tls.Config best practices. ```go // Example of configuring TLS for session resumption import ( "crypto/tls" "net/http" ) func main() { // Create a session ticket key (should be securely generated and managed) key := make([]byte, 32) // Populate key with random bytes... config := &tls.Config{ // Enable session tickets SessionTicketsDisabled: false, SessionTicketKey: key, // Prefer faster cipher suites CipherSuites: []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, }, } server := &http.Server{ Addr: ":8443", TLSConfig: config, } // ... configure routes and start server ... } ``` -------------------------------- ### Trace TLS Handshake in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/connection_observability.md Measures the duration and logs errors during the TLS handshake process by instrumenting crypto/tls. This separates network latency from cryptographic and policy enforcement costs. ```go import ( "crypto/tls" ) func handshakeWithTracing(conn net.Conn, config *tls.Config) (*tls.Conn, error) { tlsConn := tls.Client(conn, config) start := time.Now() err := tlsConn.Handshake() elapsed := time.Since(start) log.Printf("handshake: duration=%s err=%v", elapsed, err) return tlsConn, err } ``` -------------------------------- ### Trace DNS Resolution in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/connection_observability.md Measures the duration and logs IP addresses and errors during DNS resolution by wrapping the default net.Resolver. This helps identify DNS-related latency and failures. ```go import ( "context" "log" "net" "time" ) func resolveWithTracing(ctx context.Context, hostname string) ([]string, error) { start := time.Now() ips, err := net.DefaultResolver.LookupHost(ctx, hostname) elapsed := time.Since(start) log.Printf("dns: host=%s duration=%s ips=%v err=%v", hostname, elapsed, ips, err) return ips, err } ``` -------------------------------- ### Trace Go Connection Teardown Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/connection_observability.md Wraps the Close method of a net.Conn to log the duration and any errors during connection closure. This helps in identifying resource leaks or issues during the teardown phase. ```go func closeWithTracing(c net.Conn) error { start := time.Now() err := c.Close() elapsed := time.Since(start) log.Printf("close: duration=%s err=%v", elapsed, err) return err } ``` -------------------------------- ### Tuning DNS Performance in Go Source: https://github.com/astavonin/go-optimization-guide/blob/main/docs/02-networking/index.md Understand how Go performs name resolution (cgo vs Go resolver), when to cache results, and how to use custom dialers or pre-resolved IPs to avoid flaky network paths. Includes metrics and debugging tips for real-world DNS slowdowns. ```go // Example of a custom dialer to control DNS resolution import ( "context" "net" "time" ) func customDialer() *net.Dialer { return &net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, // Control DNS lookup behavior here, e.g., using a custom resolver } } func main() { // Use the custom dialer dialer := customDialer() conn, err := dialer.Dial("tcp", "example.com:80") if err != nil { // Handle error } defer conn.Close() // ... use connection ... } ```