Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .github/workflows/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,19 @@ jobs:
echo "pgpool failed to start"
exit 1

- name: Run integration tests
run: ./test/run.sh
- name: Run smoke test
run: ./test/run_smoke.sh
env:
DB_HOST: localhost
DB_PORT: 5432
DB_USER: pgtest
DB_PASSWORD: test123
DB_NAME: postgres
TARGET_HOST: localhost
TARGET_PORT: 5433

- name: Run concurrent test
run: ./test/run_concurrent.sh
env:
DB_HOST: localhost
DB_PORT: 5432
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.vscode
pgpool
vendor
test/vendor
test/vendor
test/*.out
benchmark/results
682 changes: 21 additions & 661 deletions LICENSE

Large diffs are not rendered by default.

80 changes: 27 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ A PostgreSQL connection pooler written in Go that acts as a proxy between client
- Trust (no password)
- **PostgreSQL Wire Protocol**: Full implementation supporting 40+ message types
- **Extended Query Support**: Parse, Bind, Execute, and Sync operations
- **Prepared Statement Caching**: SHA256-based deduplication across connections
- **Prepared Statement Caching**: Triggers prepare implicitly if server connection misses preprared on new pairing
- **Copy Command Support**: COPY FROM/COPY TO operations
- **Concurrent Connection Handling**: Thread-safe with async client-server pairing

## Quick Start

### Prerequisites

- Go 1.22.6 or later
- PostgreSQL server (tested with PostgreSQL 15)
- Go 1.25 or later
- PostgreSQL server (tested with PostgreSQL 16)

### Installation

Expand Down Expand Up @@ -59,16 +58,27 @@ max_clients = 100
### Running

```bash
# Run with default config (pgpool.conf)
# Run with default config (config.ini)
./pgpool

# Run with custom config
./pgpool -conf /path/to/config.conf

# Run with debug logging
./pgpool -debug
./pgpool --config /path/to/config.ini
# or shorthand
./pgpool -c /path/to/config.ini
```

### Command-Line Flags

| Flag | Shorthand | Default | Description |
|------|-----------|---------|-------------|
| `--config` | `-c` | `./config.ini` | Path to configuration file |
| `--log-level` | `-l` | `info` | Set log level: debug, info, warn, error |
| `--verbose` | `-v` | `false` | Enable debug logging (equivalent to --log-level debug) |
| `--quiet` | `-q` | `false` | Show errors only (equivalent to --log-level error) |

**Environment Variables:**
- `PGPOOL_LOG_LEVEL`: Set default log level (overridden by command-line flags)

## Configuration Reference

### Application Section
Expand Down Expand Up @@ -115,11 +125,6 @@ pgpool supports multiple authentication methods for securing client connections.
- Client → pgpool (validates client connections)
- pgpool → PostgreSQL server (authenticates with the database)

**Security benefits:**
- Passwords are never sent in plain text over the network
- Resistant to replay attacks
- More secure than MD5 or clear password authentication
- Default authentication method in PostgreSQL 14+

### Trust

Expand Down Expand Up @@ -169,51 +174,20 @@ go build -race -v -o pgpool .
GOOS=linux GOARCH=amd64 go build -v -o pgpool-linux .
```

## Architecture

### Connection Flow

1. **Client connects** to pgpool on configured address
2. **Authentication** happens between client and pgpool
3. **Pool assigns** a free server connection or creates a new one
4. **Queries are proxied** between client and server
5. **Connection returns** to pool when client disconnects

### Thread Safety
### Benchmark

- `sync.RWMutex` for concurrent access to shared data structures
- `sync.Map` for pool storage
- Thread-safe `Deque` and `DList` implementations for connection queues
Check [benchmark](benchmark/README.md)

## Performance Considerations
## TODO

- **Connection Reuse**: Minimizes overhead of establishing PostgreSQL connections
- **Prepared Statement Caching**: Reduces parse overhead using SHA256-based deduplication
- **Async Connection Pairing**: Non-blocking queue-based matching of clients to servers
- **Buffer Management**: Shared 4KB buffers with rewindable offsets for efficient reading

## CI/CD

GitHub Actions workflow runs on every push:

1. Build check with Go 1.25.3
2. Linting with golangci-lint
3. Unit tests with coverage reporting
4. Integration tests with PostgreSQL 15
5. Coverage upload to Codecov
* SSL support
* Performance improvement:
granular locking on client/server list
active wait list processing

## License

This project is licensed under the **GNU Affero General Public License v3.0** (AGPL-3.0).

### What does this mean?

- **Free and Open Source**: You can freely use, modify, and distribute this software
- **Copyleft**: If you modify and distribute this software, you must release your modifications under the same license
- **Network Use**: If you run a modified version of this software on a server and let others interact with it over a network, you must make your modified source code available to those users
- **Strong Protection**: Ensures that all users, including those who interact with the software over a network, have access to the source code

This license is particularly important for network services like pgpool, as it ensures that improvements and modifications made to the software remain available to the community, even when deployed as a service.
This project is licensed under the **MIT License**.

See the [LICENSE](LICENSE) file for full details.

Expand Down
209 changes: 209 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# PostgreSQL Connection Pool Benchmark Suite

Comprehensive benchmarking suite for comparing **pgpool** vs **pgbouncer** vs **direct PostgreSQL** connections using the industry-standard `pgbench` tool.

## Overview

This benchmark suite tests:
- **Throughput** (transactions per second)
- **Connection overhead** (initial connection time)
- **Protocol performance** (simple, extended, prepared statements)
- **Workload patterns** (read-only, read-write, complex queries)

## Directory Structure

```
benchmark/
├── config/ # Configuration files
│ ├── pgpool.ini # pgpool configuration
│ ├── pgbouncer.ini # pgbouncer configuration
│ └── userlist.txt # pgbouncer auth file
├── scripts/ # Benchmark scripts
│ ├── setup.sh # Environment setup
│ ├── run_benchmark.sh # Main benchmark runner
│ ├── generate_report.sh # Report generator
│ └── cleanup.sh # Cleanup script
├── results/ # Benchmark results (auto-generated)
│ └── YYYYMMDD_HHMMSS/ # Timestamped results
└── README.md # This file
└── report.md # sample report
```

## Prerequisites

1. **PostgreSQL** (tested with PostgreSQL 15+)
2. **pgbench** (included with PostgreSQL client tools)
3. **pgpool** (built from this repository)
4. **pgbouncer** (optional, for comparison)
5. **Go 1.22+** (to build pgpool)

### Installation

#### macOS
```bash
brew install postgresql pgbouncer
```

#### Ubuntu/Debian
```bash
sudo apt-get install postgresql-client pgbouncer
```

## Quick Start

### 1. Setup Environment

```bash
cd benchmark
./scripts/setup.sh
```

This will:
- Check PostgreSQL connectivity
- Verify pgbench installation
- Build pgpool binary if needed
- Check pgbouncer availability

### 2. Configure Poolers

#### pgpool Configuration

Edit `config/pgpool.ini`:
```ini
[app]
addr = localhost:5433

[db]
id = 1
name = postgres
host = localhost:5432

[user]
dbid = 1
name = pgtest
auth_type = scram
password = test123
max_conn = 20
max_clients = 200
```

#### pgbouncer Configuration

Edit `config/pgbouncer.ini` and `config/userlist.txt` with your credentials.

### 3. Start Poolers

#### Start pgpool
```bash
# In terminal 1
cd /path/to/pgpool
./pgpool -conf benchmark/config/pgpool.ini -debug
```

#### Start pgbouncer (optional)
```bash
# In terminal 2
cd benchmark/config
pgbouncer -d pgbouncer.ini
```

### 4. Run Benchmarks

```bash
./scripts/run_benchmark.sh
```

### 5. Generate Report

```bash
./scripts/generate_report.sh results/YYYYMMDD_HHMMSS
```

This creates:
- `report.md` - Markdown report with comparison tables
- `results.csv` - Raw CSV data for further analysis

## Configuration Options

### Environment Variables

The benchmark runner supports these environment variables:

```bash
# Database configuration
export DB_HOST=localhost
export DB_PORT=5432
export DB_USER=pgtest
export DB_PASSWORD=test123
export DB_NAME=postgres

# Pool ports
export PGPOOL_PORT=5433
export PGBOUNCER_PORT=6432

# Benchmark configuration
export DURATION=60 # seconds per test
export SCALE_FACTOR=10 # pgbench scale factor
export CONNECTION_COUNTS="10 50 100 200" # connection counts to test
```


## Workload Description

The benchmark uses **pgbench's default TPC-B-like workload**, which is the industry-standard benchmark for PostgreSQL performance testing. This workload:

- Simulates a banking/teller application with account updates and balance checks
- Includes multiple tables: `pgbench_accounts`, `pgbench_branches`, `pgbench_tellers`, `pgbench_history`
- Performs a mix of SELECT, UPDATE, and INSERT operations in each transaction
- Provides consistent, reproducible results for comparing different connection pooling solutions

The TPC-B workload is automatically initialized by pgbench with the specified scale factor, eliminating the need for custom migration scripts.

## Understanding Results

### Key Metrics

1. **TPS (Transactions Per Second)** - Higher is better
- Measures throughput
- Shows maximum capacity

2. **Average Latency** - Lower is better
- Mean response time
- Overall user experience

3. **P95/P99 Latency** - Lower is better
- Tail latency
- Worst-case performance
- Critical for user experience

4. **Connection Time** - Lower is better
- Overhead of establishing connections
- Important for connection churn scenarios

### Sample Report Output

see [report](report.md)

## Cleanup

```bash
# Stop poolers and clean pgbench tables
./scripts/cleanup.sh
```

## Advanced Usage

### Testing Specific Scenarios

#### Connection Churn
Test how poolers handle frequent connect/disconnect:
```bash
# Use shorter duration with more connection counts
DURATION=30 CONNECTION_COUNTS="5 10 20 50" ./scripts/run_benchmark.sh
```

#### High Concurrency
Test behavior under extreme load:
```bash
CONNECTION_COUNTS="100 200 500 1000" DURATION=120 ./scripts/run_benchmark.sh
```
27 changes: 27 additions & 0 deletions benchmark/config/pgbouncer.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[databases]
postgres = host=127.0.0.1 port=5432 dbname=postgres

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = scram-sha-256
auth_file = userlist.txt

; Connection pooling
pool_mode = transaction
max_client_conn = 200
default_pool_size = 20

; Logging
admin_users = pgtest
stats_users = pgtest

; Limits
server_lifetime = 3600
server_idle_timeout = 600
query_timeout = 0

; Logging
log_connections = 0
log_disconnections = 0
log_pooler_errors = 1
Loading
Loading