chore: run benchmark
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
[](https://hub.docker.com/r/sjdonado/bit)
|
||||
[](https://hub.docker.com/r/sjdonado/bit)
|
||||
|
||||
Lightweight URL shortener API service with minimal resource requirements. Average memory consumption is under **40MiB** and single CPU core consumption under 40%.
|
||||
Lightweight URL shortener API service with minimal resource requirements. Average memory consumption is under **30MiB** and single CPU core consumption around 20%.
|
||||
|
||||
Performance: Avg **1K reqs/sec**, latency 8ms (100K requests using 100 connections, [benchmark](docs/SETUP.md#benchmark)).
|
||||
Performance: Avg **1K reqs/sec**, latency 33ms, [benchmark](docs/SETUP.md#benchmark).
|
||||
|
||||
Self-hosted with [Dokku](docs/SETUP.md#dokku) and [Docker Compose](docs/SETUP.md#docker-compose).
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ module App::Controllers
|
||||
@env.response.headers["X-Forwarded-For"] = client_ip.to_s
|
||||
@env.response.headers["Connection"] = "close"
|
||||
|
||||
@env.response.flush
|
||||
|
||||
spawn do
|
||||
begin
|
||||
user_agent_str = @env.request.headers["User-Agent"]?
|
||||
|
||||
+1
-3
@@ -15,9 +15,7 @@ module App::Lib
|
||||
db_url = base_url + separator +
|
||||
"&journal_mode=WAL" +
|
||||
"&synchronous=NORMAL" + # Better performance with reasonable safety
|
||||
"&foreign_keys=true" +
|
||||
"&cache_size=10000" + # Larger cache (10MB) for frequently accessed data
|
||||
"&wal_autocheckpoint=10000" # Less frequent checkpoints
|
||||
"&foreign_keys=true"
|
||||
|
||||
conf.uri = db_url
|
||||
end
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ require "file_utils"
|
||||
SERVER_URL = "http://localhost:4000"
|
||||
API_URL = "#{SERVER_URL}/api/links"
|
||||
API_KEY = "secure_api_key_1"
|
||||
TIME = "60s"
|
||||
TIME = "59s"
|
||||
|
||||
RESOURCE_USAGE_INTERVAL = 1
|
||||
CONTAINER_NAME = "bit"
|
||||
@@ -159,7 +159,7 @@ def run_benchmark
|
||||
sleep 2.seconds
|
||||
process = Process.new(
|
||||
"bombardier",
|
||||
["-d", TIME.to_s, "-l", "--fasthttp", random_link],
|
||||
["-d", TIME.to_s, "-c", "30", "-l", "--fasthttp", random_link],
|
||||
output: Process::Redirect::Inherit,
|
||||
error: Process::Redirect::Inherit
|
||||
)
|
||||
|
||||
+17
-29
@@ -3,12 +3,12 @@ VALUES
|
||||
('User 1', 'secure_api_key_1'),
|
||||
('User 2', 'secure_api_key_2');
|
||||
|
||||
-- Create 20,000 links (10,000 per user)
|
||||
-- Create 10,000 links (5,000 per user)
|
||||
WITH RECURSIVE link_numbers(n) AS (
|
||||
SELECT 1
|
||||
UNION ALL
|
||||
SELECT n+1 FROM link_numbers
|
||||
LIMIT 20000
|
||||
LIMIT 10000
|
||||
)
|
||||
INSERT INTO links (user_id, slug, url)
|
||||
SELECT
|
||||
@@ -17,44 +17,35 @@ SELECT
|
||||
'https://sjdonado.com/page/' || n
|
||||
FROM link_numbers;
|
||||
|
||||
-- Create 1,000 clicks per link (20,000,000 total)
|
||||
-- Using batched approach for better performance
|
||||
CREATE TEMP TABLE link_ids AS SELECT id FROM links;
|
||||
|
||||
CREATE TEMP TABLE click_counts(link_id, count) AS
|
||||
-- Create 1,000 clicks per link (10 million total)
|
||||
WITH RECURSIVE counts(n) AS (
|
||||
SELECT 1
|
||||
UNION ALL
|
||||
SELECT n+1 FROM counts
|
||||
LIMIT 1000
|
||||
)
|
||||
SELECT l.id, c.n
|
||||
FROM link_ids l
|
||||
CROSS JOIN counts c;
|
||||
|
||||
-- Insert clicks from the count table
|
||||
INSERT INTO clicks (link_id, user_agent, browser, os, referer, country)
|
||||
SELECT
|
||||
link_id,
|
||||
CASE (count % 5)
|
||||
l.id,
|
||||
CASE (c.n % 5)
|
||||
WHEN 0 THEN 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
|
||||
WHEN 1 THEN 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15)'
|
||||
WHEN 2 THEN 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0)'
|
||||
WHEN 3 THEN 'Mozilla/5.0 (X11; Linux x86_64)'
|
||||
ELSE 'Mozilla/5.0 (Android 11; Mobile)'
|
||||
END,
|
||||
CASE (count % 3)
|
||||
WHEN 0 THEN 'Chrome'
|
||||
WHEN 1 THEN 'Firefox'
|
||||
CASE (c.n % 3)
|
||||
WHEN 0 THEN 'Firefox'
|
||||
WHEN 1 THEN 'Chrome'
|
||||
ELSE 'Safari'
|
||||
END,
|
||||
CASE (count % 4)
|
||||
WHEN 0 THEN 'Windows'
|
||||
WHEN 1 THEN 'macOS'
|
||||
CASE (c.n % 4)
|
||||
WHEN 0 THEN 'macOS'
|
||||
WHEN 1 THEN 'Windows'
|
||||
WHEN 2 THEN 'iOS'
|
||||
ELSE 'Android'
|
||||
END,
|
||||
CASE (count % 6)
|
||||
CASE (c.n % 6)
|
||||
WHEN 0 THEN 'https://sjdonado.com'
|
||||
WHEN 1 THEN 'https://donado.co'
|
||||
WHEN 2 THEN 'https://idonthavespotify.donado.co'
|
||||
@@ -62,9 +53,9 @@ SELECT
|
||||
WHEN 4 THEN 'https://github.com/sjdonado'
|
||||
ELSE NULL
|
||||
END,
|
||||
CASE (count % 10)
|
||||
WHEN 0 THEN 'US'
|
||||
WHEN 1 THEN 'UK'
|
||||
CASE (c.n % 10)
|
||||
WHEN 0 THEN 'Colombia'
|
||||
WHEN 1 THEN 'Brazil'
|
||||
WHEN 2 THEN 'Canada'
|
||||
WHEN 3 THEN 'Germany'
|
||||
WHEN 4 THEN 'France'
|
||||
@@ -74,8 +65,5 @@ SELECT
|
||||
WHEN 8 THEN 'India'
|
||||
ELSE 'China'
|
||||
END
|
||||
FROM click_counts;
|
||||
|
||||
-- Clean up
|
||||
DROP TABLE link_ids;
|
||||
DROP TABLE click_counts;
|
||||
FROM links l
|
||||
CROSS JOIN counts c;
|
||||
|
||||
+23
-21
@@ -109,14 +109,8 @@ ENV=test crystal spec
|
||||
|
||||
## Benchmark
|
||||
|
||||
RAM: 1GiB
|
||||
CPU: Apple M3 Pro
|
||||
|
||||
**Summary**
|
||||
- Reqs/sec (average central tendency): (1328.47 + 1357.19 + 1407.03) / 3 + (1785.03 + 1789.06 + 1778.84) / 3 = 3148.54 reqs/sec
|
||||
- Latency (average central tendency): (76.19 + 74.68 + 71.85) / 3 - (29.43 + 14.50 + 9.42) / 3 = 56.4ms
|
||||
- Latency (for conservative capacity planning): (76.19 + 74.68 + 71.85) / 3 + (29.43 + 14.50 + 9.42) / 3 = 89.63ms
|
||||
- Best single run: 18041.44 reqs/sec
|
||||
- Colima: cpu 1, mem 1
|
||||
- SoC: Apple M3 Pro
|
||||
|
||||
```
|
||||
~/p/bit> colima start --cpu 1 --memory 1
|
||||
@@ -132,25 +126,33 @@ Waiting for the application to be ready...
|
||||
Seeding the database...
|
||||
Checking seed results...
|
||||
Fetching all created links from /api/links...
|
||||
Selected link for benchmarking: http://localhost:4000/slug187082
|
||||
Selected link for benchmarking: http://localhost:4000/slug2202
|
||||
Starting benchmark with Bombardier...
|
||||
Bombarding http://localhost:4000/slug187082 with 100000 request(s) using 100 connection(s)
|
||||
100000 / 100000 [==============================================================] 100.00% 12180/s 8s
|
||||
Bombarding http://localhost:4000/slug2202 for 59s using 30 connection(s)
|
||||
[==============================================================================================] 59s
|
||||
Done!
|
||||
Statistics Avg Stdev Max
|
||||
Reqs/sec 12335.45 3288.95 20393.16
|
||||
Latency 8.11ms 1.89ms 35.42ms
|
||||
Reqs/sec 1321.38 427.84 2067.24
|
||||
Latency 33.19ms 51.13ms 2.00s
|
||||
Latency Distribution
|
||||
50% 30.01ms
|
||||
75% 34.38ms
|
||||
90% 40.59ms
|
||||
95% 48.35ms
|
||||
99% 65.21ms
|
||||
HTTP codes:
|
||||
1xx - 0, 2xx - 0, 3xx - 0, 4xx - 0, 5xx - 100000
|
||||
others - 0
|
||||
Throughput: 2.93MB/s
|
||||
1xx - 0, 2xx - 0, 3xx - 39618, 4xx - 0, 5xx - 0
|
||||
others - 13712
|
||||
Errors:
|
||||
dial tcp [::1]:4000: connect: connection refused - 13712
|
||||
Throughput: 180.24KB/s
|
||||
Benchmark completed successfully.
|
||||
Analyzing resource usage...
|
||||
**** Resource Usage Statistics ****
|
||||
Measurements: 5
|
||||
Average CPU Usage: 39.5%
|
||||
Average Memory Usage: 35.25 MiB
|
||||
Peak CPU Usage: 82.25%
|
||||
Peak Memory Usage: 37.45 MiB
|
||||
Measurements: 21
|
||||
Average CPU Usage: 22.53%
|
||||
Average Memory Usage: 28.62 MiB
|
||||
Peak CPU Usage: 35.21%
|
||||
Peak Memory Usage: 62.14 MiB
|
||||
Cleanup completed. Resource usage data saved in resource_usage.txt
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user