File tree Expand file tree Collapse file tree 5 files changed +216
-0
lines changed
Expand file tree Collapse file tree 5 files changed +216
-0
lines changed Original file line number Diff line number Diff line change 1+ #!/usr/bin/env falcon --verbose serve -c
2+ # frozen_string_literal: true
3+
4+ def limited_semaphore_token ( request )
5+ if request . respond_to? ( :connection )
6+ io = request . connection . stream . io
7+
8+ if io . respond_to? ( :token )
9+ return io . token
10+ end
11+ end
12+
13+ return nil
14+ end
15+
16+ run do |env |
17+ # This is not part of the rack specification, but is available when running under Falcon.
18+ request = env [ "protocol.http.request" ]
19+
20+ # Simulate a leaked IO object:
21+ # leak_io = request.connection.stream.io.dup
22+
23+ # There is no guarantee that there is a connection or that the connection has a token:
24+ token = limited_semaphore_token ( request )
25+
26+ if env [ "PATH_INFO" ] == "/fast"
27+ if token
28+ # Keeping the connection alive here is problematic because if the next request is slow, it will "block the server" since we have relinquished the token already.
29+ token . release
30+ request . connection . persistent = false
31+ end
32+
33+ # Simulated "fast / non-blocking" request:
34+ sleep ( 0.01 )
35+ elsif env [ "PATH_INFO" ] == "/slow"
36+ # Simulated "slow / blocking" request:
37+ sleep ( 0.1 )
38+ end
39+
40+ [ 200 , { } , [ "Hello World" ] ]
41+ end
Original file line number Diff line number Diff line change 1+ #!/usr/bin/env falcon-host
2+ # frozen_string_literal: true
3+
4+ # Released under the MIT License.
5+ # Copyright, 2019-2024, by Samuel Williams.
6+
7+ require "falcon/environment/rack"
8+ require_relative "../limited/limited"
9+
10+ service "limited.localhost" do
11+ include Falcon ::Environment ::Rack
12+
13+ scheme "http"
14+ protocol { Async ::HTTP ::Protocol ::HTTP1 . new (
15+ persistent : false ,
16+ ) }
17+
18+ # Extend the endpoint options to include the (connection) limited wrapper.
19+ endpoint_options do
20+ super ( ) . merge (
21+ protocol : protocol ,
22+ wrapper : Limited ::Wrapper . new
23+ )
24+ end
25+
26+ count 1
27+
28+ url "http://localhost:8080"
29+
30+ endpoint do
31+ ::Async ::HTTP ::Endpoint . parse ( url ) . with ( **endpoint_options )
32+ end
33+ end
Original file line number Diff line number Diff line change 1+ PATH
2+ remote: ../..
3+ specs:
4+ falcon (0.51.1)
5+ async
6+ async-container (~> 0.20)
7+ async-container-supervisor (~> 0.5.0)
8+ async-http (~> 0.75)
9+ async-http-cache (~> 0.4)
10+ async-service (~> 0.10)
11+ bundler
12+ localhost (~> 1.1)
13+ openssl (~> 3.0)
14+ protocol-http (~> 0.31)
15+ protocol-rack (~> 0.7)
16+ samovar (~> 2.3)
17+
18+ GEM
19+ remote: https://rubygems.org/
20+ specs:
21+ async (2.23.1)
22+ console (~> 1.29)
23+ fiber-annotation
24+ io-event (~> 1.9)
25+ metrics (~> 0.12)
26+ traces (~> 0.15)
27+ async-container (0.24.0)
28+ async (~> 2.22)
29+ async-container-supervisor (0.5.1)
30+ async-container (~> 0.22)
31+ async-service
32+ io-endpoint
33+ memory-leak (~> 0.5)
34+ async-http (0.88.0)
35+ async (>= 2.10.2)
36+ async-pool (~> 0.9)
37+ io-endpoint (~> 0.14)
38+ io-stream (~> 0.6)
39+ metrics (~> 0.12)
40+ protocol-http (~> 0.49)
41+ protocol-http1 (~> 0.30)
42+ protocol-http2 (~> 0.22)
43+ traces (~> 0.10)
44+ async-http-cache (0.4.5)
45+ async-http (~> 0.56)
46+ async-pool (0.10.3)
47+ async (>= 1.25)
48+ async-service (0.13.0)
49+ async
50+ async-container (~> 0.16)
51+ console (1.30.2)
52+ fiber-annotation
53+ fiber-local (~> 1.1)
54+ json
55+ fiber-annotation (0.2.0)
56+ fiber-local (1.1.0)
57+ fiber-storage
58+ fiber-storage (1.0.0)
59+ io-endpoint (0.15.2)
60+ io-event (1.10.0)
61+ io-stream (0.6.1)
62+ json (2.10.2)
63+ kgio (2.11.4)
64+ localhost (1.3.1)
65+ mapping (1.1.1)
66+ memory-leak (0.5.2)
67+ metrics (0.12.2)
68+ openssl (3.3.0)
69+ protocol-hpack (1.5.1)
70+ protocol-http (0.49.0)
71+ protocol-http1 (0.31.0)
72+ protocol-http (~> 0.22)
73+ protocol-http2 (0.22.1)
74+ protocol-hpack (~> 1.4)
75+ protocol-http (~> 0.47)
76+ protocol-rack (0.11.2)
77+ protocol-http (~> 0.43)
78+ rack (>= 1.0)
79+ rack (3.1.12)
80+ raindrops (0.20.1)
81+ samovar (2.3.0)
82+ console (~> 1.0)
83+ mapping (~> 1.0)
84+ traces (0.15.2)
85+ unicorn (6.1.0)
86+ kgio (~> 2.6)
87+ raindrops (~> 0.7)
88+
89+ PLATFORMS
90+ arm64-darwin-24
91+ ruby
92+
93+ DEPENDENCIES
94+ falcon!
95+ unicorn (~> 6.1)
96+
97+ BUNDLED WITH
98+ 2.6.2
Original file line number Diff line number Diff line change 1+ source "https://rubygems.org"
2+
3+ gem "unicorn" , "~> 6.1"
4+ gem "falcon" , path : "../../"
Original file line number Diff line number Diff line change 1+ # Unicorn (Mode)
2+
3+ This is a comparison of Unicorn and Falcon running in single-request-per-process / ` connection: close ` .
4+
5+ ## Unicorn
6+
7+ ``` sh
8+ > bundle exec unicorn -E production --port 9090
9+ ```
10+
11+ ## Falcon
12+
13+ ``` sh
14+ > bundle exec falcon host falcon.rb
15+ ```
16+
17+ ## Results
18+
19+ ```
20+ samuel@sakura ~/D/i/wrk (main)> ./wrk --verbose -t1 -c1 -d1 http://localhost:8080
21+ Running 1s test @ http://localhost:8080
22+ 1 threads and 1 connections
23+ 6795 requests in 1.10s, 610.49KB read
24+ Requests/sec: 6170.43
25+ Transfer/sec: 554.37KB
26+
27+ Thread Stats Avg Stdev Min Max +/- Stdev
28+ Latency: 153.80us 227.98us 94.00us 5.12ms 97.91%
29+ Req/sec: 6.22k 2.15k 49.00 7.25k 90.91%
30+ samuel@sakura ~/D/i/wrk (main)> ./wrk --verbose -t1 -c1 -d1 http://localhost:9090
31+ Running 1s test @ http://localhost:9090
32+ 1 threads and 1 connections
33+ 12070 requests in 1.10s, 0.99MB read
34+ Requests/sec: 10963.92
35+ Transfer/sec: 0.90MB
36+
37+ Thread Stats Avg Stdev Min Max +/- Stdev
38+ Latency: 190.98us 1.06ms 45.00us 15.56ms 98.39%
39+ Req/sec: 11.03k 3.48k 712.00 12.68k 90.91%
40+ ```
You can’t perform that action at this time.
0 commit comments