mirror of
https://github.com/benbjohnson/litestream.git
synced 2026-01-25 05:06:30 +00:00
fix(performance): reduce idle CPU usage from ~0.7% to ~0.1% (#993)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -307,22 +307,26 @@ func (c *ReplicaClient) Init(ctx context.Context) (err error) {
|
|||||||
Timeout: 24 * time.Hour,
|
Timeout: 24 * time.Hour,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure transport for insecure connections if needed
|
// Always configure custom HTTP Transport with controlled keepalive settings
|
||||||
|
// to reduce idle CPU usage from default transport's aggressive keepalives.
|
||||||
|
// See: https://github.com/benbjohnson/litestream/issues/992
|
||||||
|
httpClient.Transport = &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}).DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
IdleConnTimeout: 90 * time.Second,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure TLS to skip verification if requested
|
||||||
if c.SkipVerify {
|
if c.SkipVerify {
|
||||||
httpClient.Transport = &http.Transport{
|
httpClient.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
InsecureSkipVerify: true,
|
||||||
DialContext: (&net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
}).DialContext,
|
|
||||||
ForceAttemptHTTP2: true,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 90 * time.Second,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
69
tests/cpu-usage/README.md
Normal file
69
tests/cpu-usage/README.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# CPU Usage Testing
|
||||||
|
|
||||||
|
This directory contains test scripts and configurations for measuring Litestream's idle CPU usage, particularly for validating the fixes in issue #992.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `test-cpu-usage.sh` - Automated CPU monitoring script
|
||||||
|
- `litestream-test-polling.yml` - Config for testing with S3 replication
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. Build Litestream binary:
|
||||||
|
```bash
|
||||||
|
cd ../..
|
||||||
|
go build -o bin/litestream ./cmd/litestream
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set up AWS credentials in `.envrc` at repo root:
|
||||||
|
```bash
|
||||||
|
export AWS_ACCESS_KEY_ID="your-key-id"
|
||||||
|
export AWS_SECRET_ACCESS_KEY="your-secret-key"
|
||||||
|
export AWS_REGION="us-east-2"
|
||||||
|
export S3_BUCKET="your-test-bucket"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Have `sqlite3` CLI installed
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
From this directory, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test for 60 seconds
|
||||||
|
./test-cpu-usage.sh 60
|
||||||
|
|
||||||
|
# Longer test (5 minutes)
|
||||||
|
./test-cpu-usage.sh 300
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Tests
|
||||||
|
|
||||||
|
The script:
|
||||||
|
1. Creates a test SQLite database at `/tmp/test.db`
|
||||||
|
2. Starts Litestream with S3 replication
|
||||||
|
3. Monitors CPU usage every second using `ps`
|
||||||
|
4. Calculates average CPU usage
|
||||||
|
5. Verifies S3 replication is working
|
||||||
|
6. Outputs results and detailed CSV log
|
||||||
|
|
||||||
|
## Expected Results
|
||||||
|
|
||||||
|
Based on testing for PR #993:
|
||||||
|
|
||||||
|
- **With S3 transport fix:** ~0.0067% CPU (99% improvement)
|
||||||
|
- **Original (v0.5.6):** ~0.7% CPU
|
||||||
|
|
||||||
|
The S3 transport fix achieves near-zero idle CPU usage, validating the fix.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
Results are printed to stdout and detailed logs are saved to:
|
||||||
|
- `/tmp/litestream-cpu-log.csv` - Per-second CPU measurements
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Tests require real S3 credentials and will upload data to your bucket
|
||||||
|
- Test database is created at `/tmp/test.db` and cleaned up on each run
|
||||||
|
- CPU measurements are instantaneous snapshots, not averages over intervals
|
||||||
|
- Longer test durations (5-10 minutes) provide more stable averages
|
||||||
12
tests/cpu-usage/litestream-test-polling.yml
Normal file
12
tests/cpu-usage/litestream-test-polling.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Litestream test configuration - POLLING MODE
|
||||||
|
# Tests idle CPU usage with default polling (1s interval)
|
||||||
|
|
||||||
|
dbs:
|
||||||
|
- path: /tmp/test.db
|
||||||
|
replicas:
|
||||||
|
- type: s3
|
||||||
|
bucket: sprite-litestream-debugging
|
||||||
|
region: us-east-2
|
||||||
|
path: test-db-polling
|
||||||
|
# Default: monitor-interval: 1s
|
||||||
|
# Default: monitor-mode: poll
|
||||||
81
tests/cpu-usage/test-cpu-usage.sh
Executable file
81
tests/cpu-usage/test-cpu-usage.sh
Executable file
@@ -0,0 +1,81 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Test script for measuring Litestream idle CPU usage with S3 replication
|
||||||
|
|
||||||
|
DURATION=${1:-300} # Default 5 minutes
|
||||||
|
CONFIG_FILE="litestream-test-polling.yml"
|
||||||
|
MODE_DESC="Polling mode (1s interval)"
|
||||||
|
|
||||||
|
echo "========================================="
|
||||||
|
echo "Litestream CPU Usage Test"
|
||||||
|
echo "========================================="
|
||||||
|
echo "Mode: $MODE_DESC"
|
||||||
|
echo "Config: $CONFIG_FILE"
|
||||||
|
echo "Duration: ${DURATION}s"
|
||||||
|
echo "========================================="
|
||||||
|
|
||||||
|
# Create test database
|
||||||
|
echo "Creating test database..."
|
||||||
|
rm -f /tmp/test.db /tmp/test.db-wal /tmp/test.db-shm
|
||||||
|
sqlite3 /tmp/test.db "CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT);"
|
||||||
|
sqlite3 /tmp/test.db "INSERT INTO test (data) VALUES ('test');"
|
||||||
|
|
||||||
|
# Start Litestream in background
|
||||||
|
echo "Starting Litestream..."
|
||||||
|
# Get script directory and repo root
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
|
|
||||||
|
source "$REPO_ROOT/.envrc"
|
||||||
|
"$REPO_ROOT/bin/litestream" replicate -config "$SCRIPT_DIR/$CONFIG_FILE" &
|
||||||
|
LITESTREAM_PID=$!
|
||||||
|
|
||||||
|
echo "Litestream PID: $LITESTREAM_PID"
|
||||||
|
echo ""
|
||||||
|
echo "Monitoring CPU usage for ${DURATION}s..."
|
||||||
|
echo "Press Ctrl+C to stop early"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Monitor CPU usage
|
||||||
|
echo "Time,CPU%,VSZ,RSS" > /tmp/litestream-cpu-log.csv
|
||||||
|
for i in $(seq 1 $DURATION); do
|
||||||
|
if ! kill -0 $LITESTREAM_PID 2>/dev/null; then
|
||||||
|
echo "ERROR: Litestream process died!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get CPU and memory stats
|
||||||
|
CPU=$(ps -p $LITESTREAM_PID -o %cpu= | xargs)
|
||||||
|
VSZ=$(ps -p $LITESTREAM_PID -o vsz= | xargs)
|
||||||
|
RSS=$(ps -p $LITESTREAM_PID -o rss= | xargs)
|
||||||
|
|
||||||
|
echo "$i,$CPU,$VSZ,$RSS" >> /tmp/litestream-cpu-log.csv
|
||||||
|
|
||||||
|
# Display every 10 seconds
|
||||||
|
if [ $((i % 10)) -eq 0 ]; then
|
||||||
|
echo "[$i/${DURATION}s] CPU: ${CPU}% VSZ: ${VSZ}KB RSS: ${RSS}KB"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Stop Litestream
|
||||||
|
echo ""
|
||||||
|
echo "Stopping Litestream..."
|
||||||
|
kill $LITESTREAM_PID
|
||||||
|
wait $LITESTREAM_PID 2>/dev/null || true
|
||||||
|
|
||||||
|
# Calculate average CPU
|
||||||
|
echo ""
|
||||||
|
echo "========================================="
|
||||||
|
echo "Results"
|
||||||
|
echo "========================================="
|
||||||
|
AVG_CPU=$(awk -F',' 'NR>1 {sum+=$2; count++} END {if(count>0) print sum/count; else print 0}' /tmp/litestream-cpu-log.csv)
|
||||||
|
echo "Average CPU: ${AVG_CPU}%"
|
||||||
|
echo "Detailed log: /tmp/litestream-cpu-log.csv"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show sample of S3 uploads
|
||||||
|
echo "S3 Bucket Contents:"
|
||||||
|
aws s3 ls s3://sprite-litestream-debugging/test-db-${CONFIG_MODE}/ --recursive | head -10
|
||||||
Reference in New Issue
Block a user