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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 990697289cbe2c021f74571daada6e866a7ad796df6c855be4852d106ad84b7d
4
- data.tar.gz: a8dd04579e7f955075ee96c95ff003f82de2897ba9f96839ddb05c7e701f45ce
3
+ metadata.gz: 7e837b05925916feb0b10fb28b2ddfbc8bb476aa77091217cbb012fd0c98f6c0
4
+ data.tar.gz: 5b89fafb322999c204408a642e39547a652b61968bd2eae4b1c87b77ae51baec
5
5
  SHA512:
6
- metadata.gz: 746fa1aaff6dd152e5d1b210088f1cdf2e3388d841fd302347919a470afd09e8a0188099a89280e6368d0dff8afe62c884140d332fa45dfdd3bed23b57d386df
7
- data.tar.gz: 6586706a8d2c5eb31fae62a822f5f7c405356ddab44c8f2add1ff3e994715ac724be0c666cc26d38acec5922ce10c3967c03c2d9a9580447ba3a8198e5d0667f
6
+ metadata.gz: df56d4c6bb70b5735e4859c1186b3e754210b84dfd457f804d6f93f2ac804205f351bd2ef557a09f05fa39896bb29180c6974ef9c74a062c8ddbb32506bc5c36
7
+ data.tar.gz: 93791c5474ec82f7470270f371df480ff7178ab903ee59799ddd975d0154841234895bce720c911b0fafba78016f36cc7fbac7210b7025417bff5fde898da0b8
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Unreleased
2
+
3
+ # 0.1.2
4
+
5
+ - Improve Ruby 3.2 and Rack 3 compatibility.
6
+
7
+ # 0.1.1
8
+
9
+ - Fix `extconf.rb` to move the extension in the right place on gem install. (#18)
10
+
11
+ # 0.1.0
12
+
13
+ Initial release
data/Gemfile CHANGED
@@ -6,4 +6,8 @@ gem 'minitest'
6
6
  gem 'rake'
7
7
  gem 'rake-compiler'
8
8
 
9
+ group :benchmark do
10
+ gem "puma"
11
+ end
12
+
9
13
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pitchfork (0.1.0)
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
- rack (3.0.0)
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
- Unicorn is copyrighted free software by all contributors, see logs in
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. We currently prefer the GPLv3 or later for
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 of), is it designed to
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 (your choice) of the GPLv2 or later
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
@@ -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
@@ -1,4 +1,4 @@
1
- require "pitchfork/mem_info"
1
+ require_relative "../lib/pitchfork/mem_info"
2
2
 
3
3
  module App
4
4
  CONST_NUM = Integer(ENV.fetch("NUM", 100_000))
@@ -1,5 +1,5 @@
1
1
  # Minimal sample configuration file for Pitchfork
2
2
 
3
- listen 2007 # by default Pitchfork listens on port 8080
3
+ # listen 2007 # by default Pitchfork listens on port 8080
4
4
  worker_processes 4 # this should be >= nr_cpus
5
5
  refork_after [50, 100, 1000]
@@ -11,4 +11,4 @@ else
11
11
  end
12
12
 
13
13
  have_func('epoll_create1', %w(sys/epoll.h))
14
- create_makefile("pitchfork_http")
14
+ create_makefile("pitchfork/pitchfork_http")
@@ -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
- if value =~ /\n/
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
- response = if @request.response_start_sent
576
- "103 Early Hints\r\n"
577
- else
578
- "HTTP/1.1 103 Early Hints\r\n"
579
- end
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)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pitchfork
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  module Const
6
6
  UNICORN_VERSION = '6.1.0'
7
7
  end
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.0
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: 2022-10-05 00:00:00.000000000 Z
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