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)
|
||||||
[](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).
|
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["X-Forwarded-For"] = client_ip.to_s
|
||||||
@env.response.headers["Connection"] = "close"
|
@env.response.headers["Connection"] = "close"
|
||||||
|
|
||||||
@env.response.flush
|
|
||||||
|
|
||||||
spawn do
|
spawn do
|
||||||
begin
|
begin
|
||||||
user_agent_str = @env.request.headers["User-Agent"]?
|
user_agent_str = @env.request.headers["User-Agent"]?
|
||||||
|
|||||||
+1
-3
@@ -15,9 +15,7 @@ module App::Lib
|
|||||||
db_url = base_url + separator +
|
db_url = base_url + separator +
|
||||||
"&journal_mode=WAL" +
|
"&journal_mode=WAL" +
|
||||||
"&synchronous=NORMAL" + # Better performance with reasonable safety
|
"&synchronous=NORMAL" + # Better performance with reasonable safety
|
||||||
"&foreign_keys=true" +
|
"&foreign_keys=true"
|
||||||
"&cache_size=10000" + # Larger cache (10MB) for frequently accessed data
|
|
||||||
"&wal_autocheckpoint=10000" # Less frequent checkpoints
|
|
||||||
|
|
||||||
conf.uri = db_url
|
conf.uri = db_url
|
||||||
end
|
end
|
||||||
|
|||||||
+2
-2
@@ -8,7 +8,7 @@ require "file_utils"
|
|||||||
SERVER_URL = "http://localhost:4000"
|
SERVER_URL = "http://localhost:4000"
|
||||||
API_URL = "#{SERVER_URL}/api/links"
|
API_URL = "#{SERVER_URL}/api/links"
|
||||||
API_KEY = "secure_api_key_1"
|
API_KEY = "secure_api_key_1"
|
||||||
TIME = "60s"
|
TIME = "59s"
|
||||||
|
|
||||||
RESOURCE_USAGE_INTERVAL = 1
|
RESOURCE_USAGE_INTERVAL = 1
|
||||||
CONTAINER_NAME = "bit"
|
CONTAINER_NAME = "bit"
|
||||||
@@ -159,7 +159,7 @@ def run_benchmark
|
|||||||
sleep 2.seconds
|
sleep 2.seconds
|
||||||
process = Process.new(
|
process = Process.new(
|
||||||
"bombardier",
|
"bombardier",
|
||||||
["-d", TIME.to_s, "-l", "--fasthttp", random_link],
|
["-d", TIME.to_s, "-c", "30", "-l", "--fasthttp", random_link],
|
||||||
output: Process::Redirect::Inherit,
|
output: Process::Redirect::Inherit,
|
||||||
error: Process::Redirect::Inherit
|
error: Process::Redirect::Inherit
|
||||||
)
|
)
|
||||||
|
|||||||
+17
-29
@@ -3,12 +3,12 @@ VALUES
|
|||||||
('User 1', 'secure_api_key_1'),
|
('User 1', 'secure_api_key_1'),
|
||||||
('User 2', 'secure_api_key_2');
|
('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 (
|
WITH RECURSIVE link_numbers(n) AS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT n+1 FROM link_numbers
|
SELECT n+1 FROM link_numbers
|
||||||
LIMIT 20000
|
LIMIT 10000
|
||||||
)
|
)
|
||||||
INSERT INTO links (user_id, slug, url)
|
INSERT INTO links (user_id, slug, url)
|
||||||
SELECT
|
SELECT
|
||||||
@@ -17,44 +17,35 @@ SELECT
|
|||||||
'https://sjdonado.com/page/' || n
|
'https://sjdonado.com/page/' || n
|
||||||
FROM link_numbers;
|
FROM link_numbers;
|
||||||
|
|
||||||
-- Create 1,000 clicks per link (20,000,000 total)
|
-- Create 1,000 clicks per link (10 million 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
|
|
||||||
WITH RECURSIVE counts(n) AS (
|
WITH RECURSIVE counts(n) AS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT n+1 FROM counts
|
SELECT n+1 FROM counts
|
||||||
LIMIT 1000
|
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)
|
INSERT INTO clicks (link_id, user_agent, browser, os, referer, country)
|
||||||
SELECT
|
SELECT
|
||||||
link_id,
|
l.id,
|
||||||
CASE (count % 5)
|
CASE (c.n % 5)
|
||||||
WHEN 0 THEN 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
|
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 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 2 THEN 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0)'
|
||||||
WHEN 3 THEN 'Mozilla/5.0 (X11; Linux x86_64)'
|
WHEN 3 THEN 'Mozilla/5.0 (X11; Linux x86_64)'
|
||||||
ELSE 'Mozilla/5.0 (Android 11; Mobile)'
|
ELSE 'Mozilla/5.0 (Android 11; Mobile)'
|
||||||
END,
|
END,
|
||||||
CASE (count % 3)
|
CASE (c.n % 3)
|
||||||
WHEN 0 THEN 'Chrome'
|
WHEN 0 THEN 'Firefox'
|
||||||
WHEN 1 THEN 'Firefox'
|
WHEN 1 THEN 'Chrome'
|
||||||
ELSE 'Safari'
|
ELSE 'Safari'
|
||||||
END,
|
END,
|
||||||
CASE (count % 4)
|
CASE (c.n % 4)
|
||||||
WHEN 0 THEN 'Windows'
|
WHEN 0 THEN 'macOS'
|
||||||
WHEN 1 THEN 'macOS'
|
WHEN 1 THEN 'Windows'
|
||||||
WHEN 2 THEN 'iOS'
|
WHEN 2 THEN 'iOS'
|
||||||
ELSE 'Android'
|
ELSE 'Android'
|
||||||
END,
|
END,
|
||||||
CASE (count % 6)
|
CASE (c.n % 6)
|
||||||
WHEN 0 THEN 'https://sjdonado.com'
|
WHEN 0 THEN 'https://sjdonado.com'
|
||||||
WHEN 1 THEN 'https://donado.co'
|
WHEN 1 THEN 'https://donado.co'
|
||||||
WHEN 2 THEN 'https://idonthavespotify.donado.co'
|
WHEN 2 THEN 'https://idonthavespotify.donado.co'
|
||||||
@@ -62,9 +53,9 @@ SELECT
|
|||||||
WHEN 4 THEN 'https://github.com/sjdonado'
|
WHEN 4 THEN 'https://github.com/sjdonado'
|
||||||
ELSE NULL
|
ELSE NULL
|
||||||
END,
|
END,
|
||||||
CASE (count % 10)
|
CASE (c.n % 10)
|
||||||
WHEN 0 THEN 'US'
|
WHEN 0 THEN 'Colombia'
|
||||||
WHEN 1 THEN 'UK'
|
WHEN 1 THEN 'Brazil'
|
||||||
WHEN 2 THEN 'Canada'
|
WHEN 2 THEN 'Canada'
|
||||||
WHEN 3 THEN 'Germany'
|
WHEN 3 THEN 'Germany'
|
||||||
WHEN 4 THEN 'France'
|
WHEN 4 THEN 'France'
|
||||||
@@ -74,8 +65,5 @@ SELECT
|
|||||||
WHEN 8 THEN 'India'
|
WHEN 8 THEN 'India'
|
||||||
ELSE 'China'
|
ELSE 'China'
|
||||||
END
|
END
|
||||||
FROM click_counts;
|
FROM links l
|
||||||
|
CROSS JOIN counts c;
|
||||||
-- Clean up
|
|
||||||
DROP TABLE link_ids;
|
|
||||||
DROP TABLE click_counts;
|
|
||||||
|
|||||||
+23
-21
@@ -109,14 +109,8 @@ ENV=test crystal spec
|
|||||||
|
|
||||||
## Benchmark
|
## Benchmark
|
||||||
|
|
||||||
RAM: 1GiB
|
- Colima: cpu 1, mem 1
|
||||||
CPU: Apple M3 Pro
|
- SoC: 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
|
|
||||||
|
|
||||||
```
|
```
|
||||||
~/p/bit> colima start --cpu 1 --memory 1
|
~/p/bit> colima start --cpu 1 --memory 1
|
||||||
@@ -132,25 +126,33 @@ Waiting for the application to be ready...
|
|||||||
Seeding the database...
|
Seeding the database...
|
||||||
Checking seed results...
|
Checking seed results...
|
||||||
Fetching all created links from /api/links...
|
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...
|
Starting benchmark with Bombardier...
|
||||||
Bombarding http://localhost:4000/slug187082 with 100000 request(s) using 100 connection(s)
|
Bombarding http://localhost:4000/slug2202 for 59s using 30 connection(s)
|
||||||
100000 / 100000 [==============================================================] 100.00% 12180/s 8s
|
[==============================================================================================] 59s
|
||||||
Done!
|
Done!
|
||||||
Statistics Avg Stdev Max
|
Statistics Avg Stdev Max
|
||||||
Reqs/sec 12335.45 3288.95 20393.16
|
Reqs/sec 1321.38 427.84 2067.24
|
||||||
Latency 8.11ms 1.89ms 35.42ms
|
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:
|
HTTP codes:
|
||||||
1xx - 0, 2xx - 0, 3xx - 0, 4xx - 0, 5xx - 100000
|
1xx - 0, 2xx - 0, 3xx - 39618, 4xx - 0, 5xx - 0
|
||||||
others - 0
|
others - 13712
|
||||||
Throughput: 2.93MB/s
|
Errors:
|
||||||
|
dial tcp [::1]:4000: connect: connection refused - 13712
|
||||||
|
Throughput: 180.24KB/s
|
||||||
Benchmark completed successfully.
|
Benchmark completed successfully.
|
||||||
Analyzing resource usage...
|
Analyzing resource usage...
|
||||||
**** Resource Usage Statistics ****
|
**** Resource Usage Statistics ****
|
||||||
Measurements: 5
|
Measurements: 21
|
||||||
Average CPU Usage: 39.5%
|
Average CPU Usage: 22.53%
|
||||||
Average Memory Usage: 35.25 MiB
|
Average Memory Usage: 28.62 MiB
|
||||||
Peak CPU Usage: 82.25%
|
Peak CPU Usage: 35.21%
|
||||||
Peak Memory Usage: 37.45 MiB
|
Peak Memory Usage: 62.14 MiB
|
||||||
Cleanup completed. Resource usage data saved in resource_usage.txt
|
Cleanup completed. Resource usage data saved in resource_usage.txt
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user