Skip to content

Commit 3f67119

Browse files
committed
perf: upgrade to Go 1.26 and optimize static-web server config
- Bump go.mod and Dockerfile builder image to Go 1.26 (golang:1.26-alpine) - Bump runtime image to alpine:3.23 - Add DisableGeneralOptionsHandler to http.Server (both HTTP and HTTPS) to avoid unnecessary OPTIONS processing overhead - Tighten default timeouts: ReadTimeout/WriteTimeout 30s→10s, IdleTimeout 120s→75s (matches nginx keepalive_timeout) - Set GOGC=400 in benchmark container to reduce GC pressure after warmup when the in-memory cache is fully populated - Update config_test.go to reflect new default timeouts
1 parent a03ec70 commit 3f67119

File tree

6 files changed

+32
-25
lines changed

6 files changed

+32
-25
lines changed

benchmark/Dockerfile.static-web

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Multi-stage build: compile static-web then run in a minimal image
22
# ----------------------------------------------------------------
33
# Stage 1 — build
4-
FROM golang:1.23-alpine AS builder
4+
FROM golang:1.26-alpine AS builder
55

66
WORKDIR /src
77
COPY go.mod go.sum ./
@@ -12,7 +12,7 @@ RUN go build -ldflags="-s -w" -o /bin/static-web ./cmd/static-web
1212

1313
# ----------------------------------------------------------------
1414
# Stage 2 — run
15-
FROM alpine:3.20
15+
FROM alpine:3.23
1616

1717
RUN adduser -D -u 1000 static-web
1818
COPY --from=builder /bin/static-web /usr/local/bin/static-web

benchmark/docker-compose.benchmark.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ services:
2626
environment:
2727
- SW_ROOT=/public
2828
- SW_ADDR=0.0.0.0:8080
29+
# Raise the GC target ratio — after warmup the cache is fully populated
30+
# and allocation rate is very low, so running GC less often is a win.
31+
- GOGC=400
32+
# Ensure Go uses all available CPUs (explicit, matches container quota).
33+
- GOMAXPROCS=0
2934
restart: unless-stopped
3035

3136
# -------------------------------------------------------------------------

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/static-web/server
22

3-
go 1.23
3+
go 1.26
44

55
require (
66
github.com/BurntSushi/toml v1.6.0

internal/config/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ func applyDefaults(cfg *Config) {
134134
cfg.Server.Addr = ":8080"
135135
cfg.Server.TLSAddr = ":8443"
136136
cfg.Server.ReadHeaderTimeout = 5 * time.Second
137-
cfg.Server.ReadTimeout = 30 * time.Second
138-
cfg.Server.WriteTimeout = 30 * time.Second
139-
cfg.Server.IdleTimeout = 120 * time.Second
137+
cfg.Server.ReadTimeout = 10 * time.Second
138+
cfg.Server.WriteTimeout = 10 * time.Second
139+
cfg.Server.IdleTimeout = 75 * time.Second
140140
cfg.Server.ShutdownTimeout = 15 * time.Second
141141

142142
cfg.Files.Root = "./public"

internal/config/config_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ func TestLoadDefaults(t *testing.T) {
2121
if cfg.Server.ReadHeaderTimeout != 5*time.Second {
2222
t.Errorf("Server.ReadHeaderTimeout = %v, want 5s", cfg.Server.ReadHeaderTimeout)
2323
}
24-
if cfg.Server.ReadTimeout != 30*time.Second {
25-
t.Errorf("Server.ReadTimeout = %v, want 30s", cfg.Server.ReadTimeout)
24+
if cfg.Server.ReadTimeout != 10*time.Second {
25+
t.Errorf("Server.ReadTimeout = %v, want 10s", cfg.Server.ReadTimeout)
2626
}
2727
if cfg.Files.Root != "./public" {
2828
t.Errorf("Files.Root = %q, want %q", cfg.Files.Root, "./public")
@@ -89,8 +89,8 @@ csp = "default-src 'none'"
8989
t.Errorf("Security.CSP = %q, want 'default-src none'", cfg.Security.CSP)
9090
}
9191
// Unset fields should still have defaults
92-
if cfg.Server.WriteTimeout != 30*time.Second {
93-
t.Errorf("Server.WriteTimeout = %v, want 30s (default)", cfg.Server.WriteTimeout)
92+
if cfg.Server.WriteTimeout != 10*time.Second {
93+
t.Errorf("Server.WriteTimeout = %v, want 10s (default)", cfg.Server.WriteTimeout)
9494
}
9595
}
9696

internal/server/server.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ func New(cfg *config.ServerConfig, secCfg *config.SecurityConfig, handler http.H
4848
}
4949

5050
s.http = &http.Server{
51-
Addr: cfg.Addr,
52-
Handler: httpHandler,
53-
ReadHeaderTimeout: cfg.ReadHeaderTimeout,
54-
ReadTimeout: cfg.ReadTimeout,
55-
WriteTimeout: cfg.WriteTimeout,
56-
IdleTimeout: cfg.IdleTimeout,
57-
MaxHeaderBytes: 8 * 1024,
51+
Addr: cfg.Addr,
52+
Handler: httpHandler,
53+
ReadHeaderTimeout: cfg.ReadHeaderTimeout,
54+
ReadTimeout: cfg.ReadTimeout,
55+
WriteTimeout: cfg.WriteTimeout,
56+
IdleTimeout: cfg.IdleTimeout,
57+
MaxHeaderBytes: 8 * 1024,
58+
DisableGeneralOptionsHandler: true,
5859
}
5960

6061
if cfg.TLSCert != "" && cfg.TLSKey != "" {
@@ -90,14 +91,15 @@ func New(cfg *config.ServerConfig, secCfg *config.SecurityConfig, handler http.H
9091
}
9192

9293
s.https = &http.Server{
93-
Addr: cfg.TLSAddr,
94-
Handler: httpsHandler,
95-
TLSConfig: tlsCfg,
96-
ReadHeaderTimeout: cfg.ReadHeaderTimeout,
97-
ReadTimeout: cfg.ReadTimeout,
98-
WriteTimeout: cfg.WriteTimeout,
99-
IdleTimeout: cfg.IdleTimeout,
100-
MaxHeaderBytes: 8 * 1024,
94+
Addr: cfg.TLSAddr,
95+
Handler: httpsHandler,
96+
TLSConfig: tlsCfg,
97+
ReadHeaderTimeout: cfg.ReadHeaderTimeout,
98+
ReadTimeout: cfg.ReadTimeout,
99+
WriteTimeout: cfg.WriteTimeout,
100+
IdleTimeout: cfg.IdleTimeout,
101+
MaxHeaderBytes: 8 * 1024,
102+
DisableGeneralOptionsHandler: true,
101103
}
102104
}
103105

0 commit comments

Comments
 (0)