Skip to content

Commit e67ed71

Browse files
committed
feat: click controller performance improvements
- return tuple directly from the block - avoid to parse remote_address in the main thread - avoid to replace headers, add only - avoid separate variables for one-single use
1 parent 4ae6ef3 commit e67ed71

File tree

3 files changed

+61
-40
lines changed

3 files changed

+61
-40
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
[![Docker Stars](https://img.shields.io/docker/stars/sjdonado/bit.svg)](https://hub.docker.com/r/sjdonado/bit)
33
[![Docker Image Size](https://img.shields.io/docker/image-size/sjdonado/bit/latest)](https://hub.docker.com/r/sjdonado/bit)
44

5-
Lightweight URL shortener API service with minimal resource requirements. Average memory consumption is under **30MiB** and single CPU core consumption around 20%.
5+
Lightweight URL shortener API service with minimal resource requirements. Average memory consumption is under **30MiB** and single CPU core consumption around 30%.
66

7-
Performance: Avg **1K reqs/sec**, latency 33ms, [benchmark](docs/SETUP.md#benchmark).
7+
Performance: Avg **1K reqs/sec**, latency 30ms, [benchmark](docs/SETUP.md#benchmark).
88

99
Self-hosted with [Dokku](docs/SETUP.md#dokku) and [Docker Compose](docs/SETUP.md#docker-compose).
1010

app/controllers/click.cr

+9-19
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,19 @@ module App::Controllers
1111

1212
def self.redirect_handler
1313
->(env : HTTP::Server::Context) {
14-
slug = env.params.url["slug"]
14+
link_id, url = Database.raw_query("SELECT id, url FROM links WHERE slug = (?) LIMIT 1", env.params.url["slug"]) do |result|
15+
result.move_next ? {result.read(Int64), result.read(String)} : nil
16+
end || raise App::NotFoundException.new(env)
1517

16-
link_data = nil
17-
Database.raw_query("SELECT id, url FROM links WHERE slug = (?) LIMIT 1", slug) do |result|
18-
if result.move_next
19-
link_data = {result.read(Int64), result.read(String)}
20-
end
21-
end
22-
raise App::NotFoundException.new(env) unless link_data
18+
remote_address = env.request.headers["Cf-Connecting-Ip"]? || env.request.remote_address.to_s
2319

24-
link_id, url = link_data
25-
client_ip = IpLookup.ip_from_address(env.request.headers["Cf-Connecting-Ip"]? || env.request.remote_address.to_s)
20+
env.response.status_code = 301
21+
env.response.headers.add("Location", url)
22+
env.response.headers.add("X-Forwarded-For", remote_address)
2623

2724
spawn do
2825
begin
26+
client_ip = IpLookup.ip_from_address(remote_address)
2927
user_agent_str = env.request.headers["User-Agent"]?
3028
referer = env.request.headers["Referer"]?.try { |r| URI.parse(r).host rescue r } || env.params.query["utm_source"]? || "Direct"
3129

@@ -34,7 +32,7 @@ module App::Controllers
3432
click = App::Models::Click.new
3533
click.link_id = link_id
3634
click.country = client_ip ? IpLookup.new(client_ip).try(&.country.try(&.code)) : nil
37-
click.user_agent = ua_parser.to_s
35+
click.user_agent = user_agent_str
3836
click.browser = ua_parser.try(&.family)
3937
click.os = ua_parser.try(&.os.try(&.family))
4038
click.referer = referer
@@ -44,14 +42,6 @@ module App::Controllers
4442
Log.error { "Click tracking error: #{ex.message}" }
4543
end
4644
end
47-
48-
env.response.status_code = 301
49-
env.response.headers.add("Location", url)
50-
env.response.headers.add("X-Forwarded-For", client_ip.to_s)
51-
env.response.print ""
52-
env.response.close
53-
54-
return
5545
}
5646
end
5747
end

docs/SETUP.md

+50-19
Original file line numberDiff line numberDiff line change
@@ -126,33 +126,64 @@ Waiting for the application to be ready...
126126
Seeding the database...
127127
Checking seed results...
128128
Fetching all created links from /api/links...
129-
Selected link for benchmarking: http://localhost:4000/slug2202
129+
Selected link for benchmarking: http://localhost:4000/slug6268
130130
Starting benchmark with Bombardier...
131-
Bombarding http://localhost:4000/slug2202 for 59s using 30 connection(s)
131+
Bombarding http://localhost:4000/slug6268 for 59s using 30 connection(s)
132132
[==============================================================================================] 59s
133133
Done!
134134
Statistics Avg Stdev Max
135-
Reqs/sec 1321.38 427.84 2067.24
136-
Latency 33.19ms 51.13ms 2.00s
135+
Reqs/sec 1113.53 384.47 1642.40
136+
Latency 27.13ms 6.87ms 246.27ms
137137
Latency Distribution
138-
50% 30.01ms
139-
75% 34.38ms
140-
90% 40.59ms
141-
95% 48.35ms
142-
99% 65.21ms
138+
50% 25.13ms
139+
75% 27.60ms
140+
90% 32.34ms
141+
95% 36.06ms
142+
99% 50.99ms
143143
HTTP codes:
144-
1xx - 0, 2xx - 0, 3xx - 39618, 4xx - 0, 5xx - 0
145-
others - 13712
146-
Errors:
147-
dial tcp [::1]:4000: connect: connection refused - 13712
148-
Throughput: 180.24KB/s
144+
1xx - 0, 2xx - 0, 3xx - 65268, 4xx - 0, 5xx - 0
145+
others - 0
146+
Throughput: 308.80KB/s
149147
Benchmark completed successfully.
150148
Analyzing resource usage...
151149
**** Resource Usage Statistics ****
152-
Measurements: 21
153-
Average CPU Usage: 22.53%
154-
Average Memory Usage: 28.62 MiB
155-
Peak CPU Usage: 35.21%
156-
Peak Memory Usage: 62.14 MiB
150+
Measurements: 31
151+
Average CPU Usage: 30.49%
152+
Average Memory Usage: 64.82 MiB
153+
Peak CPU Usage: 34.12%
154+
Peak Memory Usage: 65.45 MiB
157155
Cleanup completed. Resource usage data saved in resource_usage.txt
156+
~/p/bit> cat resource_usage.txt
157+
Timestamp CPU(%) Memory(MiB)
158+
1742499555 0.0 61.76
159+
1742499557 0.01 61.76
160+
1742499559 26.73 65.13
161+
1742499561 32.59 65.16
162+
1742499563 32.66 65.42
163+
1742499565 33.32 65.45
164+
1742499567 31.84 65.2
165+
1742499569 33.01 65.4
166+
1742499571 32.56 65.23
167+
1742499573 32.86 65.23
168+
1742499575 33.31 65.24
169+
1742499577 33.0 65.06
170+
1742499579 32.98 65.07
171+
1742499581 33.42 64.93
172+
1742499583 32.98 64.91
173+
1742499585 32.85 64.93
174+
1742499587 33.39 64.94
175+
1742499589 32.88 64.95
176+
1742499591 31.9 64.95
177+
1742499593 34.12 65.21
178+
1742499595 32.85 64.94
179+
1742499597 32.95 64.89
180+
1742499599 33.88 64.9
181+
1742499601 31.93 64.89
182+
1742499603 33.67 64.89
183+
1742499605 32.62 64.89
184+
1742499607 31.12 65.01
185+
1742499609 31.04 64.77
186+
1742499611 33.95 64.77
187+
1742499613 32.3 64.68
188+
1742499615 32.52 64.94
158189
```

0 commit comments

Comments
 (0)