martin/justfile
Yuri Astrakhan 6d02416720
Improve PG performance by 28% (!!!) (#703)
A very long overdue PostgreSQL querying performance optimization that
should have used cached queries, but ... somehow didn't.

Also, this PR adds two new `just` tasks: `run-release` and `bench-http`

I used [oha](https://github.com/hatoo/oha) for its visual appeal. All
tests were using keep-alive, which I think is relatively accurate
because clients make many tile requests on the same connection. As a
target, I used the same non-empty small tile to reduce the PostgreSQL
indexing load.

❯ just run-release
❯ just bench-http

`bench-http` runs this command:
```
oha -z 120s http://localhost:3000/function_zxy_query/18/235085/122323
```

<pre>
|       before the change          |         after the change         |
|----------------------------------|----------------------------------|
|   Summary:                       | Summary:                         |
|     Success rate:    1.0000      |   Success rate:    1.0000        |
|     Total:    120.0004 secs      |   Total:    120.0002 secs        |
|     Slowest:    0.1339 secs      |   Slowest:    0.3505 secs        |
|     Fastest:    0.0015 secs      |   Fastest:    0.0012 secs        |
|     Average:    0.0076 secs      |   Average:    0.0055 secs        |
|     Requests/sec:    6583.6946   |   Requests/sec:    9073.5398     |
|                                  |                                  |
|     Total data:    113.02 MiB    |   Total data:    155.76 MiB      |
|     Size/request:    150 B       |   Size/request:    150 B         |
|     Size/sec:    964.41 KiB      |   Size/sec:    1.30 MiB          |
|                                  |                                  |
|   Response time histogram:       | Response time histogram:         |
|     0.002 [1]                    |   0.001 [1]                      |
|     0.015 [785706] ■■■■■■■■■■■■■ |   0.036 [1088825] ■■■■■■■■■■■■■  |
|     0.028 [4225]                 |   0.071 [0]                      |
|     0.041 [111]                  |   0.106 [0]                      |
|     0.054 [2]                    |   0.141 [0]                      |
|     0.068 [0]                    |   0.176 [0]                      |
|     0.081 [0]                    |   0.211 [0]                      |
|     0.094 [0]                    |   0.246 [0]                      |
|     0.107 [0]                    |   0.281 [0]                      |
|     0.121 [0]                    |   0.316 [0]                      |
|     0.134 [1]                    |   0.350 [1]                      |
|                                  |                                  |
|   Latency distribution:          | Latency distribution:            |
|     10% in 0.0057 secs           |   10% in 0.0039 secs             |
|     25% in 0.0064 secs           |   25% in 0.0045 secs             |
|     50% in 0.0073 secs           |   50% in 0.0053 secs             |
|     75% in 0.0084 secs           |   75% in 0.0063 secs             |
|     90% in 0.0098 secs           |   90% in 0.0074 secs             |
|     95% in 0.0107 secs           |   95% in 0.0082 secs             |
|     99% in 0.0135 secs           |   99% in 0.0102 secs             |
</pre>

Fixes #678
2023-06-04 15:02:00 -04:00

219 lines
6.2 KiB
Makefile

#!/usr/bin/env just --justfile
set shell := ["bash", "-c"]
export PGPORT := "5411"
export DATABASE_URL := "postgres://postgres:postgres@localhost:" + PGPORT + "/db"
export CARGO_TERM_COLOR := "always"
# export RUST_LOG := "debug"
# export RUST_BACKTRACE := "1"
@_default:
just --list --unsorted
# Start Martin server and a test database
run *ARGS: start
cargo run -- {{ ARGS }}
# Start release-compiled Martin server and a test database
run-release *ARGS: start
cargo run -- {{ ARGS }}
# Start Martin server and open a test page
debug-page *ARGS: start
open tests/debug.html # run will not exit, so open debug page first
just run {{ ARGS }}
# Run PSQL utility against the test database
psql *ARGS:
psql {{ ARGS }} {{ DATABASE_URL }}
# Perform cargo clean to delete all build files
clean: clean-test stop
cargo clean
# Delete test output files
[private]
clean-test:
rm -rf tests/output
# Start a test database
start: (docker-up "db")
# Start an ssl-enabled test database
start-ssl: (docker-up "db-ssl")
# Start a legacy test database
start-legacy: (docker-up "db-legacy")
# Start a specific test database, e.g. db or db-legacy
[private]
docker-up name:
docker-compose up -d {{ name }}
docker-compose run -T --rm db-is-ready
alias _down := stop
alias _stop-db := stop
# Stop the test database
stop:
docker-compose down
# Run benchmark tests
bench: start
cargo bench
# Run HTTP requests benchmark using OHA tool. Use with `just run-release`
bench-http:
@echo "Make sure Martin was started with 'just run-release'"
@if ! command -v oha &> /dev/null; then \
echo "oha could not be found. Installing..." ;\
cargo install oha ;\
fi
@echo "Warming up..."
oha -z 5s --no-tui http://localhost:3000/function_zxy_query/18/235085/122323 > /dev/null
oha -z 120s http://localhost:3000/function_zxy_query/18/235085/122323
# Run all tests using a test database
test: (docker-up "db") test-unit test-int
# Run all tests using an SSL connection to a test database. Expected output won't match.
test-ssl: (docker-up "ssl") test-unit clean-test
tests/test.sh
# Run all tests using the oldest supported version of the database
test-legacy: (docker-up "db-legacy") test-unit test-int
# Run Rust unit and doc tests (cargo test)
test-unit *ARGS:
cargo test --all-targets {{ ARGS }}
cargo test --all-targets --all-features {{ ARGS }}
cargo test --doc
# Run integration tests
test-int: clean-test
#!/usr/bin/env bash
set -euo pipefail
tests/test.sh
@if ( ! diff --brief --recursive --new-file tests/output tests/expected ); then
echo "** Expected output does not match actual output"
echo "** If this is expected, run 'just bless' to update expected output"
exit 1
else
echo "Expected output matches actual output"
fi
# Run integration tests and save its output as the new expected output
bless: start clean-test
tests/test.sh
rm -rf tests/expected
mv tests/output tests/expected
# Build and open mdbook documentation
mdbook:
@if ! command -v mdbook &> /dev/null; then \
echo "mdbook could not be found. Installing..." ;\
cargo install mdbook ;\
fi
mdbook serve docs --open --port 8321
# Build and open code documentation
docs:
cargo doc --no-deps --open
# Run code coverage on tests and save its output in the coverage directory. Parameter could be html or lcov.
coverage FORMAT='html':
#!/usr/bin/env bash
set -euo pipefail
@if ! command -v grcov &> /dev/null; then \
echo "grcov could not be found. Installing..." ;\
cargo install grcov ;\
fi
@if ! rustup component list | grep llvm-tools-preview &> /dev/null; then \
echo "llvm-tools-preview could not be found. Installing..." ;\
rustup component add llvm-tools-preview ;\
fi
just clean
just start
PROF_DIR=target/prof
mkdir -p "$PROF_DIR"
PROF_DIR=$(realpath "$PROF_DIR")
OUTPUT_RESULTS_DIR=target/coverage/{{ FORMAT }}
mkdir -p "$OUTPUT_RESULTS_DIR"
export CARGO_INCREMENTAL=0
export RUSTFLAGS=-Cinstrument-coverage
# Avoid problems with relative paths
export LLVM_PROFILE_FILE=$PROF_DIR/cargo-test-%p-%m.profraw
export MARTIN_PORT=3111
cargo test --all-targets
cargo test --all-targets --all-features
tests/test.sh
set -x
grcov --binary-path ./target/debug \
-s . \
-t {{ FORMAT }} \
--branch \
--ignore 'benches/*' \
--ignore 'tests/*' \
--ignore-not-existing \
-o target/coverage/{{ FORMAT }} \
--llvm \
"$PROF_DIR"
{ set +x; } 2>/dev/null
# if this is html, open it in the browser
if [ "{{ FORMAT }}" = "html" ]; then
open "$OUTPUT_RESULTS_DIR/index.html"
fi
# Build martin docker image
docker-build:
docker build -t ghcr.io/maplibre/martin .
# Build and run martin docker image
docker-run *ARGS:
docker run -it --rm --net host -e DATABASE_URL -v $PWD/tests:/tests ghcr.io/maplibre/martin {{ ARGS }}
# Do any git command, ensuring that the testing environment is set up. Accepts the same arguments as git.
[no-exit-message]
git *ARGS: start
git {{ ARGS }}
# Print the connection string for the test database
print-conn-str:
@echo {{ DATABASE_URL }}
# Run cargo fmt and cargo clippy
lint: fmt clippy
# Run cargo fmt
fmt:
cargo fmt --all -- --check
# Run cargo clippy
clippy:
cargo clippy --workspace --all-targets --all-features --bins --tests --lib --benches -- -D warnings
# These steps automatically run before git push via a git hook
[private]
git-pre-push: stop start
rustc --version
cargo --version
just lint
just test
# Update sqlite database schema. Install SQLX cli if not already installed.
prepare-sqlite:
@if ! command -v cargo-sqlx &> /dev/null; then \
echo "SQLX could not be found. Installing..." ;\
cargo install sqlx-cli --no-default-features --features sqlite,native-tls ;\
fi
cd martin-mbtiles && cargo sqlx prepare --database-url sqlite://$PWD/../tests/fixtures/files/world_cities.mbtiles