pitchfork 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +6 -2
- data/LICENSE +2 -3
- data/README.md +12 -3
- data/benchmark/README.md +32 -0
- data/benchmark/cow_benchmark.rb +17 -0
- data/examples/constant_caches.ru +1 -1
- data/examples/pitchfork.conf.minimal.rb +1 -1
- data/ext/pitchfork_http/extconf.rb +1 -1
- data/lib/pitchfork/http_response.rb +13 -6
- data/lib/pitchfork/http_server.rb +5 -16
- data/lib/pitchfork/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e837b05925916feb0b10fb28b2ddfbc8bb476aa77091217cbb012fd0c98f6c0
|
4
|
+
data.tar.gz: 5b89fafb322999c204408a642e39547a652b61968bd2eae4b1c87b77ae51baec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df56d4c6bb70b5735e4859c1186b3e754210b84dfd457f804d6f93f2ac804205f351bd2ef557a09f05fa39896bb29180c6974ef9c74a062c8ddbb32506bc5c36
|
7
|
+
data.tar.gz: 93791c5474ec82f7470270f371df480ff7178ab903ee59799ddd975d0154841234895bce720c911b0fafba78016f36cc7fbac7210b7025417bff5fde898da0b8
|
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pitchfork (0.1.
|
4
|
+
pitchfork (0.1.2)
|
5
5
|
rack (>= 2.0)
|
6
6
|
raindrops (~> 0.7)
|
7
7
|
|
@@ -9,7 +9,10 @@ GEM
|
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
11
|
minitest (5.16.3)
|
12
|
-
|
12
|
+
nio4r (2.5.8)
|
13
|
+
puma (5.6.5)
|
14
|
+
nio4r (~> 2.0)
|
15
|
+
rack (3.0.4.1)
|
13
16
|
raindrops (0.20.0)
|
14
17
|
rake (13.0.6)
|
15
18
|
rake-compiler (1.2.0)
|
@@ -23,6 +26,7 @@ PLATFORMS
|
|
23
26
|
DEPENDENCIES
|
24
27
|
minitest
|
25
28
|
pitchfork!
|
29
|
+
puma
|
26
30
|
rake
|
27
31
|
rake-compiler
|
28
32
|
|
data/LICENSE
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
|
1
|
+
Pitchfork is copyrighted free software by all contributors, see logs in
|
2
2
|
revision control for names and email addresses of all of them.
|
3
3
|
|
4
4
|
You can redistribute it and/or modify it under either the terms of the
|
5
5
|
GNU General Public License (GPL) as published by the Free Software
|
6
6
|
Foundation (FSF), either version 2 of the License, or (at your option)
|
7
|
-
any later version.
|
8
|
-
derivative works, but the GPLv2 is fine.
|
7
|
+
any later version.
|
9
8
|
|
10
9
|
The complete texts of the GPLv2 and GPLv3 are below:
|
11
10
|
GPLv2 - https://www.gnu.org/licenses/gpl-2.0.txt
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
`pitchfork` is a preforking HTTP server for Rack applications designed
|
4
4
|
to minimize memory usage by maximizing Copy-on-Write performance.
|
5
5
|
|
6
|
-
Like [`unicorn`](https://yhbt.net/unicorn/README.html) (which `pitchfork` is a derivative
|
6
|
+
Like [`unicorn`](https://yhbt.net/unicorn/README.html) (of which `pitchfork` is a derivative), it is designed to
|
7
7
|
only serve fast clients on low-latency, high-bandwidth connections and take
|
8
8
|
advantage of features in Unix/Unix-like kernels. Slow clients should
|
9
9
|
only be served by placing a reverse proxy capable of fully buffering
|
@@ -99,6 +99,16 @@ compatibility with existing applications.
|
|
99
99
|
Most command-line options for other Rack applications (above) are also
|
100
100
|
supported. Run `pitchfork -h` to see command-line options.
|
101
101
|
|
102
|
+
## Relation to Unicorn
|
103
|
+
|
104
|
+
Pitchfork initially started as a Unicorn patch, however some of Unicorn features
|
105
|
+
as well as Unicorn policy of supporting extremely old Ruby version made it challenging.
|
106
|
+
|
107
|
+
Forking was the occasion to significantly reduce the complexity.
|
108
|
+
|
109
|
+
However some large parts of Pitchfork like the HTTP parser are still mostly unchanged from Unicorn, and Unicorn
|
110
|
+
is fairly stable these days. As such we aim to backport any Unicorn patches that may apply to Pitchfork and vice versa.
|
111
|
+
|
102
112
|
## License
|
103
113
|
|
104
114
|
pitchfork is copyright 2022 Shopify Inc and all contributors.
|
@@ -108,8 +118,7 @@ Unicorn is copyright 2009-2018 by all contributors (see logs in git).
|
|
108
118
|
It is based on Mongrel 1.1.5.
|
109
119
|
Mongrel is copyright 2007 Zed A. Shaw and contributors.
|
110
120
|
|
111
|
-
pitchfork is licensed under
|
112
|
-
(GPLv3+ preferred), or Ruby (1.8)-specific terms.
|
121
|
+
pitchfork is licensed under the GPLv2 or later or Ruby (1.8)-specific terms.
|
113
122
|
See the included LICENSE file for details.
|
114
123
|
|
115
124
|
## Thanks
|
data/benchmark/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Benchmarks
|
2
|
+
|
3
|
+
## Copy on Write Efficiency
|
4
|
+
|
5
|
+
This benchmark aimed to compare real memory usage of differnet servers.
|
6
|
+
|
7
|
+
For instance, Puma 2 workers + 2 threads:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
$ PORT=9292 bundle exec benchmark/cow_benchmark.rb puma -w 2 -t 2 --preload
|
11
|
+
Booting server...
|
12
|
+
Warming the app with ab...
|
13
|
+
Memory Usage:
|
14
|
+
Single Worker Memory Usage: 207.5 MiB
|
15
|
+
Total Cluster Memory Usage: 601.6 MiB
|
16
|
+
```
|
17
|
+
|
18
|
+
Pitchfork 4 workers:
|
19
|
+
|
20
|
+
```bash
|
21
|
+
$ PORT=8080 bundle exec benchmark/cow_benchmark.rb pitchfork -c examples/pitchfork.conf.minimal.rb
|
22
|
+
Booting server...
|
23
|
+
Warming the app with ab...
|
24
|
+
Memory Usage:
|
25
|
+
Single Worker Memory Usage: 62.6 MiB
|
26
|
+
Total Cluster Memory Usage: 320.3 MiB
|
27
|
+
```
|
28
|
+
|
29
|
+
The `constant_caches.ru` application is specifically crafted to demonstrate how shared memory regions
|
30
|
+
get invalidated as applications execute more and more code.
|
31
|
+
|
32
|
+
It is an extreme example for benchmark purposes.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "net/http"
|
3
|
+
|
4
|
+
app_path = File.expand_path('../examples/constant_caches.ru', __dir__)
|
5
|
+
|
6
|
+
puts "Booting server..."
|
7
|
+
pid = Process.spawn(*ARGV, app_path, out: File::NULL, err: File::NULL)
|
8
|
+
sleep 5
|
9
|
+
app_url = "http://localhost:#{ENV.fetch('PORT')}/"
|
10
|
+
puts "Warming the app with ab..."
|
11
|
+
system("ab", "-c", "4", "-n", "500", app_url, out: File::NULL, err: File::NULL)
|
12
|
+
sleep 3
|
13
|
+
puts "Memory Usage:"
|
14
|
+
puts Net::HTTP.get(URI(app_url))
|
15
|
+
|
16
|
+
Process.kill("TERM", pid)
|
17
|
+
Process.wait
|
data/examples/constant_caches.ru
CHANGED
@@ -20,6 +20,18 @@ module Pitchfork
|
|
20
20
|
"#{code} #{STATUS_CODES[code]}\r\n\r\n"
|
21
21
|
end
|
22
22
|
|
23
|
+
def append_header(buf, key, value)
|
24
|
+
case value
|
25
|
+
when Array # Rack 3
|
26
|
+
value.each { |v| buf << "#{key}: #{v}\r\n" }
|
27
|
+
when /\n/ # Rack 2
|
28
|
+
# avoiding blank, key-only cookies with /\n+/
|
29
|
+
value.split(/\n+/).each { |v| buf << "#{key}: #{v}\r\n" }
|
30
|
+
else
|
31
|
+
buf << "#{key}: #{value}\r\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
23
35
|
# writes the rack_response to socket as an HTTP response
|
24
36
|
def http_response_write(socket, status, headers, body,
|
25
37
|
req = Pitchfork::HttpParser.new)
|
@@ -41,12 +53,7 @@ module Pitchfork
|
|
41
53
|
# key in Rack < 1.5
|
42
54
|
hijack = value
|
43
55
|
else
|
44
|
-
|
45
|
-
# avoiding blank, key-only cookies with /\n+/
|
46
|
-
value.split(/\n+/).each { |v| buf << "#{key}: #{v}\r\n" }
|
47
|
-
else
|
48
|
-
buf << "#{key}: #{value}\r\n"
|
49
|
-
end
|
56
|
+
append_header(buf, key, value)
|
50
57
|
end
|
51
58
|
end
|
52
59
|
socket.write(buf << "\r\n".freeze)
|
@@ -572,22 +572,11 @@ module Pitchfork
|
|
572
572
|
end
|
573
573
|
|
574
574
|
def e103_response_write(client, headers)
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
headers.each_pair do |k, vs|
|
582
|
-
next if !vs || vs.empty?
|
583
|
-
values = vs.to_s.split("\n".freeze)
|
584
|
-
values.each do |v|
|
585
|
-
response << "#{k}: #{v}\r\n"
|
586
|
-
end
|
587
|
-
end
|
588
|
-
response << "\r\n".freeze
|
589
|
-
response << "HTTP/1.1 ".freeze if @request.response_start_sent
|
590
|
-
client.write(response)
|
575
|
+
rss = @request.response_start_sent
|
576
|
+
buf = rss ? "103 Early Hints\r\n" : "HTTP/1.1 103 Early Hints\r\n"
|
577
|
+
headers.each { |key, value| append_header(buf, key, value) }
|
578
|
+
buf << (rss ? "\r\nHTTP/1.1 ".freeze : "\r\n".freeze)
|
579
|
+
client.write(buf)
|
591
580
|
end
|
592
581
|
|
593
582
|
def e100_response_write(client, env)
|
data/lib/pitchfork/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pitchfork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: raindrops
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- ".gitattributes"
|
54
54
|
- ".github/workflows/ci.yml"
|
55
55
|
- ".gitignore"
|
56
|
+
- CHANGELOG.md
|
56
57
|
- COPYING
|
57
58
|
- Dockerfile
|
58
59
|
- Gemfile
|
@@ -60,6 +61,8 @@ files:
|
|
60
61
|
- LICENSE
|
61
62
|
- README.md
|
62
63
|
- Rakefile
|
64
|
+
- benchmark/README.md
|
65
|
+
- benchmark/cow_benchmark.rb
|
63
66
|
- docs/Application_Timeouts.md
|
64
67
|
- docs/CONFIGURATION.md
|
65
68
|
- docs/DESIGN.md
|