Core reference benchmark for the S3-backed page-group tiered VFS. Measures query latency against social network databases stored on S3-compatible object storage.
Queries: post+user join, profile (5 joins), who-liked, mutual friends, indexed filter, full scan + filter
Cache levels: none, interior, index, data (see below)
| Cache level | What's cached | What's fetched from S3 | When this happens |
|---|---|---|---|
| none | nothing | everything | Fresh start, empty cache |
| interior | interior B-tree pages | index + data pages | First query after connection open |
| index | interior + index pages | data pages only | Normal turbolite operation |
| data | everything | nothing | Equivalent to local SQLite |
Social network with 4 tables. At 1M posts: 100K users, 2.5M friendships, 3M likes (1.46GB, 91 page groups).
CREATE TABLE users (
id INTEGER PRIMARY KEY,
first_name TEXT, last_name TEXT, email TEXT,
school TEXT, city TEXT, bio TEXT, joined_at INTEGER
);
CREATE TABLE posts (
id INTEGER PRIMARY KEY,
user_id INTEGER, content TEXT, created_at INTEGER, like_count INTEGER
);
CREATE TABLE friendships (
user_a INTEGER, user_b INTEGER, created_at INTEGER,
PRIMARY KEY (user_a, user_b)
);
CREATE TABLE likes (
user_id INTEGER, post_id INTEGER, created_at INTEGER,
PRIMARY KEY (user_id, post_id)
);
CREATE INDEX idx_posts_user ON posts(user_id);
CREATE INDEX idx_posts_created ON posts(created_at);
CREATE INDEX idx_friendships_b ON friendships(user_b, user_a);
CREATE INDEX idx_likes_post ON likes(post_id);
CREATE INDEX idx_likes_user ON likes(user_id, created_at);
CREATE INDEX idx_users_school ON users(school);| Name | SQL | What it tests |
|---|---|---|
| post | SELECT p.*, u.first_name, u.last_name, u.school, u.city FROM posts p JOIN users u ON u.id = p.user_id WHERE p.id = ? |
Point lookup + 1 join. Touches 2 index pages + 2 data pages. |
| profile | SELECT u.*, p.id, p.content, p.created_at, p.like_count FROM users u JOIN posts p ON p.user_id = u.id WHERE u.id = ? ORDER BY p.created_at DESC LIMIT 10 |
User profile page. Index scan on posts(user_id), sorted by created_at. Multiple data pages. |
| who-liked | SELECT u.first_name, u.last_name, u.school, l.created_at FROM likes l JOIN users u ON u.id = l.user_id WHERE l.post_id = ? ORDER BY l.created_at DESC LIMIT 50 |
Reverse lookup through likes index, join to users. Up to 50 rows from scattered data pages. |
| mutual | SELECT u.id, u.first_name, u.last_name, u.school FROM friendships f1 JOIN friendships f2 ON f1.user_b = f2.user_b JOIN users u ON u.id = f1.user_b WHERE f1.user_a = ? AND f2.user_a = ? LIMIT 20 |
Self-join on friendships. Two index scans + intersection + user lookup. |
| idx-filter | SELECT COUNT(*) FROM posts WHERE user_id = ? |
Indexed count. Covered by idx_posts_user, only index pages needed. |
| scan-filter | SELECT COUNT(*) FROM posts WHERE like_count > ? |
Full table scan. No index on like_count, must read every data page. |
The VFS uses three prefetch strategies, selected automatically per query via EXPLAIN QUERY PLAN:
| Strategy | When | Default schedule | What happens |
|---|---|---|---|
| SCAN (plan-aware) | EQP says SCAN table |
All groups submitted upfront | Bulk prefetch of entire table before first read. No hop schedule involved. |
| SEARCH | EQP says SEARCH table USING INDEX |
[0.3, 0.3, 0.4] |
Aggressive warmup from first miss. SEARCH queries scan unknown portions of indexes/tables. |
| Lookup | No EQP info, point queries, DDL | [0, 0, 0] |
Three free hops before any prefetch. Lookups hit 1-2 pages per tree. |
Each element in a schedule is the fraction of eligible sibling groups to prefetch on the Nth consecutive cache miss (per-tree). When misses exceed the array length, fraction=1.0 (all remaining siblings).
Prefetch schedules are set on TurboliteConfig at VFS construction:
let config = TurboliteConfig {
prefetch_search: vec![0.4, 0.3, 0.3],
prefetch_lookup: vec![0.0, 0.0, 0.2],
query_plan_prefetch: true, // enable plan-aware SCAN bulk prefetch
..Default::default()
};| Field | Type | Description |
|---|---|---|
prefetch_search |
Vec<f32> |
SEARCH query prefetch schedule (aggressive) |
prefetch_lookup |
Vec<f32> |
Lookup/point query prefetch schedule (conservative) |
query_plan_prefetch |
bool |
Enable/disable plan-aware SCAN bulk prefetch |
SEARCH queries scan unknown portions of indexes/tables and need aggressive warmup. Lookups hit 1-2 pages per tree and barely need prefetch. Per-tree miss counters ensure independent tracking across trees in a query: a profile query hitting users (miss 1) then posts (miss 1) tracks each tree separately. SCAN queries need everything upfront and bypass schedules entirely (plan-aware bulk prefetch).
--sizes Row counts, comma-separated (default: 10000)
--iterations Measured iterations per query per cache level (default: 10)
--warmup Warmup iterations before measuring (default: 2)
--modes Cache levels to run, comma-separated (default: all)
Options: none, interior, index, data
--queries Queries to run, comma-separated (default: all)
Options: post, profile, who-liked, mutual, idx-filter, scan-filter
--prefetch-threads Worker threads for parallel S3 fetches (default: 8)
--prefetch-search SEARCH prefetch schedule (default: 0.3,0.3,0.4)
--prefetch-lookup Lookup prefetch schedule (default: 0,0,0)
--prefetch-hops Radial prefetch schedule for Positional strategy (default: 0.33,0.33)
--ppg Pages per page group (default: 256)
--page-size Page size in bytes (default: 65536)
--import Import mode: "auto" generates locally then uploads, or path to existing .db
--skip-verify Skip COUNT(*) verification
--cleanup Delete S3 data after benchmark
--plan-aware Enable Phase Marne query-plan-aware prefetch
--post-prefetch Per-query SEARCH schedule for post+user (default: off)
--post-lookup Per-query LOOKUP schedule for post+user (default: off)
--profile-prefetch Per-query SEARCH schedule for profile (default: 0.1,0.2,0.3)
--profile-lookup Per-query LOOKUP schedule for profile (default: 0,0,0,0)
--who-liked-prefetch SEARCH schedule for who-liked (default: 0.3,0.3,0.4)
--who-liked-lookup LOOKUP schedule for who-liked (default: 0,0,0)
--mutual-prefetch SEARCH schedule for mutual (default: 0.4,0.3,0.3)
--mutual-lookup LOOKUP schedule for mutual (default: 0,0,0)
--idx-filter-prefetch SEARCH schedule for idx-filter (default: 0.2,0.3,0.5)
--idx-filter-lookup LOOKUP schedule for idx-filter (default: 0,0,0)
--scan-filter-prefetch SEARCH schedule for scan-filter (default: off)
--scan-filter-lookup LOOKUP schedule for scan-filter (default: off)
--matrix Sweep schedule pairs at "none" level (see Matrix Mode below)
--matrix-schedules Schedule pairs to test (semicolon-separated, "search/lookup" format)
Matrix mode (--matrix) tests each query at cache level "none" with every schedule pair in --matrix-schedules. This produces a comparison table per query showing how different search/lookup schedule combinations affect latency, GET count, and bytes transferred.
# Default 10 schedule pairs (off, old uniform, current dual, aggressive, etc.)
cargo run --release --features tiered,zstd --bin tiered-bench -- \
--sizes 1000000 --import auto --plan-aware --matrix --iterations 10
# Custom schedule pairs
cargo run --release --features tiered,zstd --bin tiered-bench -- \
--sizes 1000000 --plan-aware --matrix --iterations 10 \
--matrix-schedules "off;0.3,0.3,0.4/0,0.1,0.2;0.5,0.5/0,0,0.1;1.0/0"Schedule pair format: search_schedule/lookup_schedule, semicolon-separated. off = no prefetch (both zeros). No slash = same schedule for both.
Output is a table per query:
--- post+user ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 96.0ms 111.7ms 13.9 16.2MB
0.30,0.30,0.40 / 0.00,0.10,0.20 77.1ms 94.7ms 14.0 17.1MB
0.50,0.50 / 0.00,0.00,0.10 74.2ms 99.1ms 11.5 6.8MB
tiered-tune connects to an existing turbolite database and sweeps prefetch schedules against your actual queries. Instead of benchmarking a synthetic dataset, tune against your real workload.
# Tune against an existing database
TIERED_TEST_BUCKET=my-bucket AWS_ENDPOINT_URL=https://t3.storage.dev \
cargo run --release --features tiered,zstd --bin tiered-tune -- \
--prefix "databases/tenant-123" \
--query "SELECT * FROM users WHERE id = ?1" --param 42 \
--query "SELECT p.*, u.name FROM posts p JOIN users u ON p.user_id = u.id WHERE p.id = ?1" --param 100 \
--plan-aware --iterations 10
# Custom schedule grid
cargo run --release --features tiered,zstd --bin tiered-tune -- \
--prefix "databases/tenant-123" \
--query "SELECT * FROM orders WHERE user_id = ?1 ORDER BY created_at DESC LIMIT 20" --param 1 \
--search-schedules "0.3,0.3,0.4;0.5,0.5;1.0" \
--lookup-schedules "0;0,0,0.1;0,0,0,0.1,0.2" \
--plan-aware --iterations 10The tool builds a Cartesian product of search x lookup schedules, tests each pair, and recommends the best one with the Rust config to apply it:
Best: 0.50,0.50 / 0.00,0.00,0.10 (p50 = 74.2ms)
TurboliteConfig.prefetch_search = vec![0.5, 0.5];
TurboliteConfig.prefetch_lookup = vec![0.0, 0.0, 0.1];
| Variable | Required | Default | Description |
|---|---|---|---|
TIERED_TEST_BUCKET |
yes | -- | S3 bucket name (also accepts BUCKET_NAME) |
AWS_REGION |
no | from env | AWS region |
AWS_ENDPOINT_URL |
no | default S3 | Custom endpoint (Tigris: https://fly.storage.tigris.dev) |
Set TIERED_TEST_BUCKET, AWS_REGION, AWS_ENDPOINT_URL, and AWS credentials as environment variables, then run:
# Generate 100K rows, upload to S3, run all cache levels
TIERED_TEST_BUCKET=my-bucket AWS_ENDPOINT_URL=https://fly.storage.tigris.dev \
cargo run --release --features tiered,zstd --bin tiered-bench -- \
--sizes 100000 --import auto
# Reuse existing 1M-row data on S3
TIERED_TEST_BUCKET=my-bucket AWS_ENDPOINT_URL=https://fly.storage.tigris.dev \
cargo run --release --features tiered,zstd --bin tiered-bench -- \
--sizes 1000000 --modes interior,index
# Quick: just point lookups at interior level
TIERED_TEST_BUCKET=my-bucket AWS_ENDPOINT_URL=https://fly.storage.tigris.dev \
cargo run --release --features tiered,zstd --bin tiered-bench -- \
--sizes 1000000 --modes interior --queries postData is stored at social_{size}/ in the bucket and reused across runs automatically. No need for --import after the first run.
The Fly app turbolite-tiered-bench is pre-configured in fly.toml:
- Region:
iad - VM:
performance-8x(8 dedicated vCPU, 16GB RAM) - Volume: 40GB at
/data - S3 credentials set via
fly secrets
# From project root (not benchmark/)
fly deploy --app turbolite-tiered-bench \
--config benchmark/fly.toml \
--dockerfile benchmark/Dockerfile \
--remote-only
# Machine starts automatically, runs the benchmark, then stops.
# If it doesn't start, kick it manually:
fly machine start <machine-id> --app turbolite-tiered-benchThe process args in fly.toml control what runs:
[processes]
app = "--sizes 1000000 --iterations 10 --skip-verify --modes none,interior,index,data"Results are uploaded to S3 by the entrypoint:
aws s3 ls s3://$TIERED_TEST_BUCKET/bench/logs/ --endpoint-url $AWS_ENDPOINT_URL
# Download latest
aws s3 cp s3://$TIERED_TEST_BUCKET/bench/logs/<filename>.log /tmp/bench.log \
--endpoint-url $AWS_ENDPOINT_URL
# Parse results
grep -E '\[data\]|\[index\]|\[interior\]|\[none\]' /tmp/bench.logOr check Fly logs directly:
fly logs --app turbolite-tiered-bench --no-tail | grep -E '\[data\]|\[index\]|\[interior\]|\[none\]'S3 Express One Zone provides single-digit ms latency from the same availability zone. Regular S3 Standard works too, with higher latency (~20-50ms GETs).
| Resource | Value |
|---|---|
| S3 Express bucket | turbolite-bench--use2-az1--x-s3 |
| S3 Standard bucket | turbolite-bench-regular |
| Region | us-east-2 |
| AZ | us-east-2a (zone ID: use2-az1) |
| Security group | sg-07069137083c088b7 (SSH open) |
Cross-compiled binaries from cargo-lambda hang on Amazon Linux. Use Docker:
docker build --platform linux/amd64 -f - -o type=local,dest=./target/docker-out . <<'DOCKERFILE'
FROM rust:1-bookworm AS builder
RUN apt-get update && apt-get install -y cmake && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY Cargo.toml Cargo.lock* ./
COPY src/ src/
COPY bin/ bin/
COPY benchmark/ benchmark/
RUN cargo build --release --features tiered,zstd --bin tiered-bench
FROM scratch
COPY --from=builder /app/target/release/tiered-bench /tiered-bench
DOCKERFILEAMI=$(aws ec2 describe-images --region us-east-2 --owners amazon \
--filters "Name=name,Values=al2023-ami-2023*-x86_64" "Name=state,Values=available" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' --output text)
INSTANCE_ID=$(aws ec2 run-instances --region us-east-2 \
--image-id $AMI --instance-type t3.medium --key-name russellromney \
--security-group-ids sg-07069137083c088b7 \
--placement AvailabilityZone=us-east-2a \
--iam-instance-profile Name=turbolite-bench-ec2 \
--associate-public-ip-address \
--query 'Instances[0].InstanceId' --output text)
aws ec2 wait instance-running --region us-east-2 --instance-ids $INSTANCE_ID
IP=$(aws ec2 describe-instances --region us-east-2 --instance-ids $INSTANCE_ID \
--query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
# Push SSH key (expires in 60s), then upload binary
aws ec2-instance-connect send-ssh-public-key --region us-east-2 \
--instance-id $INSTANCE_ID --instance-os-user ec2-user \
--ssh-public-key file://~/.ssh/id_rsa.pub
scp -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa \
./target/docker-out/tiered-bench ec2-user@$IP:/home/ec2-user/tiered-bench
# Push key again, then run
aws ec2-instance-connect send-ssh-public-key --region us-east-2 \
--instance-id $INSTANCE_ID --instance-os-user ec2-user \
--ssh-public-key file://~/.ssh/id_rsa.pub
ssh -o StrictHostKeyChecking=no -o ServerAliveInterval=15 -i ~/.ssh/id_rsa ec2-user@$IP \
'chmod +x /home/ec2-user/tiered-bench && \
BUCKET_NAME=turbolite-bench--use2-az1--x-s3 AWS_REGION=us-east-2 \
/home/ec2-user/tiered-bench --sizes 100000 --import auto 2>&1'
# Or use regular S3 instead of S3 Express:
# BUCKET_NAME=turbolite-bench-regular AWS_REGION=us-east-2 \
# /home/ec2-user/tiered-bench --sizes 100000 --import auto 2>&1'
# Terminate when done
aws ec2 terminate-instances --region us-east-2 --instance-ids $INSTANCE_IDaws iam create-role --role-name turbolite-bench-ec2-role \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam put-role-policy --role-name turbolite-bench-ec2-role --policy-name s3-express-access \
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["s3express:CreateSession","s3:GetObject","s3:PutObject","s3:ListBucket","s3:GetBucketLocation"],"Resource":["arn:aws:s3express:us-east-2:462570052286:bucket/turbolite-bench--use2-az1--x-s3","arn:aws:s3express:us-east-2:462570052286:bucket/turbolite-bench--use2-az1--x-s3/*","arn:aws:s3:::turbolite-bench-regular","arn:aws:s3:::turbolite-bench-regular/*"]}]}'
aws iam create-instance-profile --instance-profile-name turbolite-bench-ec2
aws iam add-role-to-instance-profile --instance-profile-name turbolite-bench-ec2 --role-name turbolite-bench-ec2-role
sleep 10- cargo-lambda binaries hang on AWS Linux. Always use the Docker build for EC2 deployments.
- EC2 Instance Connect keys expire in 60 seconds. Push a new key before each SSH/SCP command.
- Fly deploy from project root. Run
fly deploy --config benchmark/fly.toml --dockerfile benchmark/Dockerfilefrom the project root, not frombenchmark/. - Machine may not auto-start after deploy. Use
fly machine start <id>if the machine stops immediately after deploy. - Data reuse is automatic. Data lives at
social_{size}/in the bucket. The bench checks for an existing manifest before generating.
1M posts (812MB, 51 page groups, BTreeAware grouping, 64KB pages, 256 ppg).
Default prefetch: search [0.3, 0.3, 0.4], lookup [0, 0, 0], plan-aware enabled.
Per-query schedules: search and lookup set independently per query (see CLI flags above).
S3 Express One Zone (EC2 c5.2xlarge, us-east-2a, ~4ms GET latency):
| Query | p50 | p90 | Avg GETs | Avg bytes |
|---|---|---|---|---|
| post+user | 77ms | 93ms | 10.5 | 4MB |
| profile | 190ms | 278ms | 41.7 | 54MB |
| who-liked | 129ms | 182ms | 15.7 | 14MB |
| mutual | 82ms | 114ms | 17.3 | 29MB |
| idx-filter | 74ms | 86ms | 8.0 | 3MB |
| scan-filter | 586ms | 692ms | 98.4 | 139MB |
Tigris (Fly.io iad, performance-8x, ~25ms GET latency):
Per-query schedules tuned for Tigris latency (warmer lookups than S3 Express defaults). Best p50 from matrix sweep of 17 search/lookup schedule pairs per query.
| Query | Best schedule | p50 | p90 | Avg GETs | Avg bytes |
|---|---|---|---|---|---|
| post+user | 1.00 / 0,0,0.10 |
192ms | 324ms | 20.0 | 31MB |
| profile | 0.20,0.30,0.50 / 0,0.10,0.20 |
524ms | 806ms | 41.5 | 54MB |
| who-liked | 0.30,0.30,0.40 / 0,0,0,0 |
340ms | 572ms | 16.6 | 24MB |
| mutual | 0.40,0.30,0.30 / 0.10,0.20,0.30 |
183ms | 264ms | 13.1 | 17MB |
| idx-filter | 0.30,0.30,0.40 / 0.10,0.20,0.30 |
173ms | 242ms | 19.5 | 38MB |
| scan-filter | 0.40,0.30,0.30 / 0,0,0 |
984ms | 1.3s | 102.4 | 139MB |
10 search/lookup schedule pairs tested per query. Key findings:
S3 Express winners (by p50):
| Query | Best schedule | p50 | vs off/off | GETs | Bytes |
|---|---|---|---|---|---|
| post+user | 0.50,0.50 / 0,0,0.10 |
74ms | -23% | 11.5 | 7MB |
| profile | 0.30,0.30,0.40 / 0,0.10,0.20 |
188ms | -11% | 41.4 | 53MB |
| who-liked | 0.30,0.30,0.40 / 0,0.10,0.20 |
118ms | -16% | 15.7 | 15MB |
| mutual | 0.50,0.50 / 0.10,0.20,0.30 |
69ms | -11% | 11.8 | 13MB |
| idx-filter | 0.33,0.33,0.34 / 0.33,0.33,0.34 |
66ms | -5% | 12.4 | 17MB |
| scan-filter | 1.00 / 0 |
553ms | -5% | 97.9 | 139MB |
Tigris winners (by p50):
| Query | Best schedule | p50 | vs off/off | GETs | Bytes |
|---|---|---|---|---|---|
| post+user | 1.00 / 0,0,0.10 |
192ms | -17% | 20.0 | 31MB |
| profile | 0.20,0.30,0.50 / 0,0.10,0.20 |
524ms | -15% | 41.5 | 54MB |
| who-liked | 0.30,0.30,0.40 / 0,0,0,0 |
340ms | -20% | 16.6 | 24MB |
| mutual | 0.40,0.30,0.30 / 0.10,0.20,0.30 |
183ms | -34% | 13.1 | 17MB |
| idx-filter | 0.30,0.30,0.40 / 0.10,0.20,0.30 |
173ms | -8% | 19.5 | 38MB |
| scan-filter | 0.40,0.30,0.30 / 0,0,0 |
984ms | -18% | 102.4 | 139MB |
Storage backend determines optimal tuning. On S3 Express (~4ms GET), zero-heavy lookup schedules (0,0,0) dominate because individual range GETs cost only 4ms. On Tigris (~25ms GET), warmer lookup schedules (0,0.1,0.2 or 0.1,0.2,0.3) pay off because each avoided round trip saves 25ms. The per-query schedule system lets each query use the optimal pair for its backend.
Search and lookup need independent tuning. Setting both to the same schedule (the old behavior) accidentally worked on some queries but hurt others. Independent schedules let SEARCH queries use aggressive warmup while point-query lookups stay conservative. Profile went from 681ms to 480ms on Tigris once search and lookup were split.
Scan-filter is schedule-insensitive. Plan-aware frontrunning bulk-prefetches the entire table before the first read. Schedule variation is noise on both backends. This validates that frontrunning (Phase Marne) is doing its job for SCAN queries.
off/off is a viable baseline. With seekable sub-chunk encoding, each cache miss is a ~18KB range GET instead of a full 1.2MB group download. On S3 Express, off/off delivers 96ms point lookups and 212ms profiles. This validates that the sub-chunk architecture is sound on its own; prefetch is optimization on top, not a crutch.
--- post+user ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 96.0ms 111.7ms 13.9 16.2MB
0.33,0.33,0.34 / 0.33,0.33,0.34 95.3ms 118.1ms 16.5 11.0MB
0.30,0.30,0.40 / 0.00,0.10,0.20 77.1ms 94.7ms 14.0 17.1MB
0.30,0.30,0.40 / 0.30,0.30,0.40 92.0ms 113.1ms 16.2 10.3MB
0.50,0.50 / 0.00,0.00,0.10 74.2ms 99.1ms 11.5 6.8MB
0.50,0.50 / 0.10,0.20,0.30 102.3ms 128.5ms 22.7 28.3MB
0.50,0.30,0.20 / 0.10,0.10,0.20 98.7ms 123.3ms 18.1 19.0MB
1.00 / 0.00 76.3ms 93.9ms 18.0 30.2MB
0.20,0.30,0.50 / 0.00,0.00,0.20 87.6ms 132.4ms 16.0 20.3MB
0.40,0.30,0.30 / 0.10,0.20,0.30 95.6ms 111.0ms 17.4 15.9MB
--- profile ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 211.7ms 279.5ms 43.2 59.7MB
0.33,0.33,0.34 / 0.33,0.33,0.34 254.1ms 327.0ms 56.2 75.9MB
0.30,0.30,0.40 / 0.00,0.10,0.20 188.0ms 262.9ms 41.4 52.8MB
0.30,0.30,0.40 / 0.30,0.30,0.40 269.0ms 336.6ms 58.4 81.0MB
0.50,0.50 / 0.00,0.00,0.10 218.5ms 295.8ms 46.1 67.0MB
0.50,0.50 / 0.10,0.20,0.30 258.6ms 349.4ms 61.5 86.7MB
0.50,0.30,0.20 / 0.10,0.10,0.20 264.3ms 339.4ms 64.0 97.2MB
1.00 / 0.00 199.7ms 267.8ms 44.8 63.9MB
0.20,0.30,0.50 / 0.00,0.00,0.20 192.4ms 309.5ms 41.6 53.5MB
0.40,0.30,0.30 / 0.10,0.20,0.30 236.0ms 373.1ms 55.3 75.0MB
--- who-liked ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 141.0ms 196.7ms 17.3 13.3MB
0.33,0.33,0.34 / 0.33,0.33,0.34 156.3ms 249.2ms 17.8 29.1MB
0.30,0.30,0.40 / 0.00,0.10,0.20 118.1ms 173.1ms 15.7 15.0MB
0.30,0.30,0.40 / 0.30,0.30,0.40 124.3ms 270.8ms 22.3 39.4MB
0.50,0.50 / 0.00,0.00,0.10 130.8ms 254.7ms 22.6 34.9MB
0.50,0.50 / 0.10,0.20,0.30 173.4ms 206.4ms 19.4 33.4MB
0.50,0.30,0.20 / 0.10,0.10,0.20 135.5ms 281.3ms 21.4 36.8MB
1.00 / 0.00 150.7ms 192.5ms 17.8 20.4MB
0.20,0.30,0.50 / 0.00,0.00,0.20 147.6ms 254.2ms 22.3 32.3MB
0.40,0.30,0.30 / 0.10,0.20,0.30 146.3ms 286.0ms 26.1 53.9MB
--- mutual ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 77.8ms 89.4ms 15.0 22.0MB
0.33,0.33,0.34 / 0.33,0.33,0.34 74.0ms 145.4ms 8.8 4.0MB
0.30,0.30,0.40 / 0.00,0.10,0.20 76.8ms 98.6ms 11.5 8.9MB
0.30,0.30,0.40 / 0.30,0.30,0.40 73.0ms 110.1ms 8.4 2.8MB
0.50,0.50 / 0.00,0.00,0.10 73.5ms 108.5ms 8.9 3.0MB
0.50,0.50 / 0.10,0.20,0.30 69.4ms 132.4ms 11.8 13.3MB
0.50,0.30,0.20 / 0.10,0.10,0.20 72.5ms 103.2ms 9.7 5.7MB
1.00 / 0.00 75.0ms 97.3ms 12.3 12.4MB
0.20,0.30,0.50 / 0.00,0.00,0.20 78.4ms 100.4ms 13.5 15.8MB
0.40,0.30,0.30 / 0.10,0.20,0.30 82.3ms 89.3ms 8.8 3.0MB
--- idx-filter ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 69.5ms 90.2ms 8.8 3.0MB
0.33,0.33,0.34 / 0.33,0.33,0.34 65.5ms 81.4ms 12.4 17.2MB
0.30,0.30,0.40 / 0.00,0.10,0.20 74.5ms 137.0ms 17.6 31.1MB
0.30,0.30,0.40 / 0.30,0.30,0.40 76.1ms 92.1ms 11.5 10.9MB
0.50,0.50 / 0.00,0.00,0.10 65.8ms 94.1ms 11.6 12.9MB
0.50,0.50 / 0.10,0.20,0.30 69.7ms 96.2ms 8.2 2.8MB
0.50,0.30,0.20 / 0.10,0.10,0.20 71.2ms 109.5ms 14.4 22.3MB
1.00 / 0.00 81.8ms 103.5ms 16.0 26.0MB
0.20,0.30,0.50 / 0.00,0.00,0.20 77.1ms 100.5ms 21.0 42.2MB
0.40,0.30,0.30 / 0.10,0.20,0.30 69.4ms 81.2ms 12.1 16.1MB
--- scan-filter ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 580.6ms 646.0ms 98.2 138.6MB
0.33,0.33,0.34 / 0.33,0.33,0.34 579.0ms 663.1ms 102.7 152.6MB
0.30,0.30,0.40 / 0.00,0.10,0.20 591.0ms 673.3ms 102.3 152.6MB
0.30,0.30,0.40 / 0.30,0.30,0.40 574.5ms 666.8ms 97.8 138.6MB
0.50,0.50 / 0.00,0.00,0.10 577.3ms 598.8ms 97.8 138.6MB
0.50,0.50 / 0.10,0.20,0.30 566.7ms 701.6ms 98.4 138.6MB
0.50,0.30,0.20 / 0.10,0.10,0.20 574.0ms 635.6ms 97.3 138.5MB
1.00 / 0.00 553.2ms 623.4ms 97.9 138.6MB
0.20,0.30,0.50 / 0.00,0.00,0.20 554.9ms 632.3ms 97.5 138.5MB
0.40,0.30,0.30 / 0.10,0.20,0.30 554.1ms 637.5ms 97.2 138.5MB
--- post+user ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 243.8ms 348.1ms 21.3 42.6MB
0.33,0.33,0.34 / 0.33,0.33,0.34 245.0ms 344.2ms 18.5 21.2MB
0.30,0.30,0.40 / 0.00,0.10,0.20 259.2ms 394.8ms 23.6 46.0MB
0.30,0.30,0.40 / 0.30,0.30,0.40 238.3ms 411.2ms 16.5 13.1MB
0.50,0.50 / 0.00,0.00,0.10 289.8ms 363.1ms 18.9 31.9MB
0.50,0.50 / 0.10,0.20,0.30 281.7ms 440.6ms 20.1 26.0MB
0.50,0.30,0.20 / 0.10,0.10,0.20 218.6ms 271.0ms 23.7 37.4MB
1.00 / 0.00 260.0ms 500.8ms 19.5 37.3MB
0.20,0.30,0.50 / 0.00,0.00,0.20 231.6ms 286.2ms 18.9 30.8MB
0.40,0.30,0.30 / 0.10,0.20,0.30 261.3ms 447.1ms 23.6 37.1MB
--- profile ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 727.0ms 1.1s 54.5 93.5MB
0.33,0.33,0.34 / 0.33,0.33,0.34 730.7ms 982.4ms 82.1 127.2MB
0.30,0.30,0.40 / 0.00,0.10,0.20 680.6ms 824.5ms 47.5 74.9MB
0.30,0.30,0.40 / 0.30,0.30,0.40 667.0ms 997.2ms 90.8 137.5MB
0.50,0.50 / 0.00,0.00,0.10 549.0ms 920.5ms 40.8 50.0MB
0.50,0.50 / 0.10,0.20,0.30 700.6ms 824.9ms 76.7 113.8MB
0.50,0.30,0.20 / 0.10,0.10,0.20 609.4ms 937.8ms 75.6 111.0MB
1.00 / 0.00 688.8ms 1.1s 54.8 95.4MB
0.20,0.30,0.50 / 0.00,0.00,0.20 634.5ms 675.9ms 50.4 80.8MB
0.40,0.30,0.30 / 0.10,0.20,0.30 705.9ms 934.0ms 84.8 130.4MB
--- who-liked ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 424.3ms 523.3ms 24.6 48.6MB
0.33,0.33,0.34 / 0.33,0.33,0.34 413.6ms 750.0ms 21.8 49.1MB
0.30,0.30,0.40 / 0.00,0.10,0.20 384.1ms 482.8ms 31.1 73.4MB
0.30,0.30,0.40 / 0.30,0.30,0.40 417.5ms 579.5ms 26.9 68.4MB
0.50,0.50 / 0.00,0.00,0.10 471.9ms 550.5ms 30.5 77.0MB
0.50,0.50 / 0.10,0.20,0.30 380.1ms 612.4ms 21.3 51.3MB
0.50,0.30,0.20 / 0.10,0.10,0.20 488.0ms 618.1ms 31.0 87.7MB
1.00 / 0.00 533.0ms 720.6ms 30.5 79.3MB
0.20,0.30,0.50 / 0.00,0.00,0.20 374.0ms 595.2ms 26.6 61.3MB
0.40,0.30,0.30 / 0.10,0.20,0.30 369.0ms 451.8ms 31.2 82.0MB
--- mutual ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 209.9ms 315.7ms 16.2 29.4MB
0.33,0.33,0.34 / 0.33,0.33,0.34 208.8ms 256.1ms 15.9 27.4MB
0.30,0.30,0.40 / 0.00,0.10,0.20 200.5ms 425.7ms 9.1 4.3MB
0.30,0.30,0.40 / 0.30,0.30,0.40 188.0ms 369.1ms 20.5 43.6MB
0.50,0.50 / 0.00,0.00,0.10 235.2ms 305.7ms 15.9 25.4MB
0.50,0.50 / 0.10,0.20,0.30 214.1ms 329.9ms 17.5 29.0MB
0.50,0.30,0.20 / 0.10,0.10,0.20 204.3ms 340.7ms 10.3 10.2MB
1.00 / 0.00 231.5ms 329.6ms 8.7 3.8MB
0.20,0.30,0.50 / 0.00,0.00,0.20 162.0ms 225.9ms 16.2 27.9MB
0.40,0.30,0.30 / 0.10,0.20,0.30 156.8ms 227.9ms 17.4 31.2MB
--- idx-filter ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 259.8ms 472.6ms 16.5 30.6MB
0.33,0.33,0.34 / 0.33,0.33,0.34 198.3ms 446.9ms 17.1 30.8MB
0.30,0.30,0.40 / 0.00,0.10,0.20 158.9ms 257.4ms 18.4 32.6MB
0.30,0.30,0.40 / 0.30,0.30,0.40 344.2ms 535.8ms 16.6 32.6MB
0.50,0.50 / 0.00,0.00,0.10 176.2ms 232.1ms 16.7 30.7MB
0.50,0.50 / 0.10,0.20,0.30 215.5ms 343.5ms 18.9 38.7MB
0.50,0.30,0.20 / 0.10,0.10,0.20 245.5ms 392.8ms 16.8 30.0MB
1.00 / 0.00 185.8ms 311.5ms 19.8 40.3MB
0.20,0.30,0.50 / 0.00,0.00,0.20 234.6ms 366.0ms 14.4 22.7MB
0.40,0.30,0.30 / 0.10,0.20,0.30 163.5ms 359.3ms 12.2 16.6MB
--- scan-filter ---
search / lookup p50 p90 GETs bytes
------------------------------------ ---------- ---------- ---------- ------------
off / off 922.3ms 1.2s 108.0 152.7MB
0.33,0.33,0.34 / 0.33,0.33,0.34 900.7ms 1.1s 107.5 152.7MB
0.30,0.30,0.40 / 0.00,0.10,0.20 920.5ms 1.0s 105.4 152.7MB
0.30,0.30,0.40 / 0.30,0.30,0.40 973.5ms 1.1s 101.8 138.6MB
0.50,0.50 / 0.00,0.00,0.10 944.0ms 1.2s 107.2 152.7MB
0.50,0.50 / 0.10,0.20,0.30 937.3ms 1.6s 108.8 152.8MB
0.50,0.30,0.20 / 0.10,0.10,0.20 1.1s 1.2s 108.9 152.8MB
1.00 / 0.00 1.1s 1.3s 109.8 152.8MB
0.20,0.30,0.50 / 0.00,0.00,0.20 1.0s 1.4s 109.3 152.8MB
0.40,0.30,0.30 / 0.10,0.20,0.30 952.8ms 1.2s 107.3 138.7MB