polyphony 0.43.8 → 0.45.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/CHANGELOG.md +38 -0
  4. data/Gemfile.lock +13 -11
  5. data/README.md +20 -5
  6. data/Rakefile +1 -1
  7. data/TODO.md +16 -14
  8. data/bin/stress.rb +28 -0
  9. data/docs/_posts/2020-07-26-polyphony-0.44.md +77 -0
  10. data/docs/api-reference/thread.md +1 -1
  11. data/docs/getting-started/overview.md +14 -14
  12. data/docs/getting-started/tutorial.md +1 -1
  13. data/examples/adapters/sequel_mysql.rb +23 -0
  14. data/examples/adapters/sequel_mysql_pool.rb +33 -0
  15. data/examples/core/{xx-agent.rb → xx-backend.rb} +5 -5
  16. data/examples/core/xx-channels.rb +4 -2
  17. data/examples/core/xx-using-a-mutex.rb +2 -1
  18. data/examples/io/xx-pry.rb +18 -0
  19. data/examples/io/xx-rack_server.rb +71 -0
  20. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +1 -1
  21. data/ext/polyphony/backend.h +41 -0
  22. data/ext/polyphony/event.c +86 -0
  23. data/ext/polyphony/extconf.rb +1 -1
  24. data/ext/polyphony/fiber.c +0 -5
  25. data/ext/polyphony/{libev_agent.c → libev_backend.c} +234 -228
  26. data/ext/polyphony/polyphony.c +4 -0
  27. data/ext/polyphony/polyphony.h +16 -16
  28. data/ext/polyphony/polyphony_ext.c +4 -2
  29. data/ext/polyphony/queue.c +52 -12
  30. data/ext/polyphony/thread.c +55 -42
  31. data/lib/polyphony.rb +25 -39
  32. data/lib/polyphony/adapters/irb.rb +2 -17
  33. data/lib/polyphony/adapters/mysql2.rb +19 -0
  34. data/lib/polyphony/adapters/postgres.rb +5 -5
  35. data/lib/polyphony/adapters/process.rb +2 -2
  36. data/lib/polyphony/adapters/readline.rb +17 -0
  37. data/lib/polyphony/adapters/sequel.rb +45 -0
  38. data/lib/polyphony/core/channel.rb +3 -34
  39. data/lib/polyphony/core/exceptions.rb +11 -0
  40. data/lib/polyphony/core/global_api.rb +11 -6
  41. data/lib/polyphony/core/resource_pool.rb +22 -71
  42. data/lib/polyphony/core/sync.rb +48 -9
  43. data/lib/polyphony/core/throttler.rb +1 -1
  44. data/lib/polyphony/extensions/core.rb +37 -19
  45. data/lib/polyphony/extensions/fiber.rb +5 -1
  46. data/lib/polyphony/extensions/io.rb +7 -8
  47. data/lib/polyphony/extensions/openssl.rb +6 -6
  48. data/lib/polyphony/extensions/socket.rb +12 -22
  49. data/lib/polyphony/extensions/thread.rb +6 -5
  50. data/lib/polyphony/net.rb +2 -1
  51. data/lib/polyphony/version.rb +1 -1
  52. data/polyphony.gemspec +6 -3
  53. data/test/helper.rb +1 -1
  54. data/test/{test_agent.rb → test_backend.rb} +22 -22
  55. data/test/test_event.rb +1 -0
  56. data/test/test_fiber.rb +21 -5
  57. data/test/test_io.rb +1 -1
  58. data/test/test_kernel.rb +5 -0
  59. data/test/test_queue.rb +20 -0
  60. data/test/test_resource_pool.rb +34 -43
  61. data/test/test_signal.rb +5 -29
  62. data/test/test_sync.rb +52 -0
  63. metadata +74 -30
  64. data/.gitbook.yaml +0 -4
  65. data/lib/polyphony/event.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bea457e28d23f96570d448855d00cf76250a55fcb02e12c4305cb551cb55faf4
4
- data.tar.gz: dc97409e61ce82c20eef25101a2c53046635461ef81302e54b121e5bb9c25aa1
3
+ metadata.gz: f9c8ab74213c6cc5e3852f73ee027ee496f2b04c6844e09856c9771ea5e7839a
4
+ data.tar.gz: 83d7c533024b6d6d633b9e18abc392911adfc07f728af826bd84cce35cafb20c
5
5
  SHA512:
6
- metadata.gz: 53d345ee472bc77fc993880a1a725064bb934ec2789fa72bd97ec07b558942369860fb7077e0fcff6c95cfcff0c0d712090f70b1d9ff7f652160d15ddfc77de4
7
- data.tar.gz: 513a79eeb8a7766078d159cf85d367a6f3f50a0870825275408081d9cfe4e446e7f0b0120bd712f6281ccd0787779ec464b20c9e17c3c60178ceb39c061033c7
6
+ metadata.gz: c42e49ebcd6fb10b384438cb7688801a387963bc2a6fb2c1d3de6d022a7731a7d88db138a34b364b35c9d71830b975a69cb1f14fb277166a9db1802e24e82dec
7
+ data.tar.gz: 6c578eacded00dd7a77a35124c69ebc966e4f9aa42264913df82af147f43955a2ecd86087630c085fcd4d6e964aa705202c5aa24bb4032648d3ba278d60d4f63
@@ -81,6 +81,7 @@ Lint/SuppressedException:
81
81
  - examples/**/*.rb
82
82
 
83
83
  Metrics/MethodLength:
84
+ Max: 12
84
85
  Exclude:
85
86
  - lib/polyphony/http/server/rack.rb
86
87
  - lib/polyphony/extensions/io.rb
@@ -111,6 +112,7 @@ Style/Documentation:
111
112
  Exclude:
112
113
  - test/**/*.rb
113
114
  - examples/**/*.rb
115
+ - lib/polyphony/adapters/**/*.rb
114
116
 
115
117
  Style/FormatString:
116
118
  Exclude:
@@ -172,4 +174,8 @@ Style/RedundantRegexpEscape:
172
174
  Enabled: true
173
175
 
174
176
  Style/SlicingWithRange:
175
- Enabled: true
177
+ Enabled: true
178
+
179
+ Style/RaiseArgs:
180
+ Exclude:
181
+ - lib/polyphony/extensions/fiber.rb
@@ -1,3 +1,41 @@
1
+ ## 0.45.0
2
+
3
+ * Cleanup code
4
+ * Rename `Agent` to `Backend`
5
+ * Implement `Polyphony::ConditionVariable`
6
+ * Fix Kernel.system
7
+
8
+ ## 0.44.0 2020-07-25
9
+
10
+ * Fix reentrant `ResourcePool` (#38)
11
+ * Add `ResourcePool#discard!` (#35)
12
+ * Add `Mysql2::Client` and `Sequel::ConnectionPool` adapters (#35)
13
+ * Reimplement `Kernel.trap` using `Fiber#interject`
14
+ * Add `Fiber#interject` for running arbitrary code on arbitrary fibers (#39)
15
+
16
+ ## 0.43.11 2020-07-24
17
+
18
+ * Dump uncaught exception info for forked process (#36)
19
+ * Add additional socket config options (#37)
20
+ - :reuse_port (`SO_REUSEPORT`)
21
+ - :backlog (listen backlog, default `SOMAXCONN`)
22
+ * Fix possible race condition in Queue#shift (#34)
23
+
24
+ ## 0.43.10 2020-07-23
25
+
26
+ * Fix race condition when terminating fibers (#33)
27
+ * Fix lock release in `Mutex` (#32)
28
+ * Virtualize agent interface
29
+ * Implement `LibevAgent_connect`
30
+
31
+ ## 0.43.9 2020-07-22
32
+
33
+ * Rewrite `Channel` using `Queue`
34
+ * Rewrite `Mutex` using `Queue`
35
+ * Reimplement `Event` in C to prevent cross-thread race condition
36
+ * Reimplement `ResourcePool` using `Queue`
37
+ * Implement `Queue#size`
38
+
1
39
  ## 0.43.8 2020-07-21
2
40
 
3
41
  * Rename `LibevQueue` to `Queue`
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.43.8)
4
+ polyphony (0.45.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -11,6 +11,7 @@ GEM
11
11
  ansi (1.5.0)
12
12
  ast (2.4.0)
13
13
  builder (3.2.4)
14
+ coderay (1.1.3)
14
15
  colorator (1.1.0)
15
16
  concurrent-ruby (1.1.6)
16
17
  docile (1.3.2)
@@ -22,9 +23,6 @@ GEM
22
23
  forwardable-extended (2.6.0)
23
24
  hiredis (0.6.3)
24
25
  http_parser.rb (0.6.0)
25
- httparty (0.17.0)
26
- mime-types (~> 3.0)
27
- multi_xml (>= 0.5.2)
28
26
  i18n (0.9.5)
29
27
  concurrent-ruby (~> 1.0)
30
28
  jekyll (3.8.6)
@@ -60,25 +58,26 @@ GEM
60
58
  listen (3.2.1)
61
59
  rb-fsevent (~> 0.10, >= 0.10.3)
62
60
  rb-inotify (~> 0.9, >= 0.9.10)
63
- localhost (1.1.4)
64
61
  mercenary (0.3.6)
65
- mime-types (3.3.1)
66
- mime-types-data (~> 3.2015)
67
- mime-types-data (3.2019.1009)
62
+ method_source (1.0.0)
68
63
  minitest (5.13.0)
69
64
  minitest-reporters (1.4.2)
70
65
  ansi
71
66
  builder
72
67
  minitest (>= 5.0)
73
68
  ruby-progressbar
74
- multi_xml (0.6.0)
69
+ mysql2 (0.5.3)
75
70
  parallel (1.19.1)
76
71
  parser (2.7.0.2)
77
72
  ast (~> 2.4.0)
78
73
  pathutil (0.16.2)
79
74
  forwardable-extended (~> 2.6)
80
75
  pg (1.1.4)
76
+ pry (0.13.1)
77
+ coderay (~> 1.1)
78
+ method_source (~> 1.0)
81
79
  public_suffix (4.0.3)
80
+ rack (2.2.3)
82
81
  rainbow (3.0.0)
83
82
  rake (12.3.3)
84
83
  rake-compiler (1.0.5)
@@ -109,6 +108,7 @@ GEM
109
108
  sass-listen (4.0.0)
110
109
  rb-fsevent (~> 0.9, >= 0.9.4)
111
110
  rb-inotify (~> 0.9, >= 0.9.7)
111
+ sequel (5.34.0)
112
112
  simplecov (0.17.1)
113
113
  docile (~> 1.1)
114
114
  json (>= 1.8, < 3)
@@ -122,19 +122,21 @@ PLATFORMS
122
122
  DEPENDENCIES
123
123
  hiredis (= 0.6.3)
124
124
  http_parser.rb (~> 0.6.0)
125
- httparty (= 0.17.0)
126
125
  jekyll (~> 3.8.6)
127
126
  jekyll-remote-theme (~> 0.4.1)
128
127
  jekyll-seo-tag (~> 2.6.1)
129
128
  just-the-docs (~> 0.3.0)
130
- localhost (= 1.1.4)
131
129
  minitest (= 5.13.0)
132
130
  minitest-reporters (= 1.4.2)
131
+ mysql2 (= 0.5.3)
133
132
  pg (= 1.1.4)
134
133
  polyphony!
134
+ pry (= 0.13.1)
135
+ rack (>= 2.0.8, < 2.3.0)
135
136
  rake-compiler (= 1.0.5)
136
137
  redis (= 4.1.0)
137
138
  rubocop (= 0.85.1)
139
+ sequel (= 5.34.0)
138
140
  simplecov (= 0.17.1)
139
141
 
140
142
  BUNDLED WITH
data/README.md CHANGED
@@ -1,10 +1,25 @@
1
- <p align="center"><img src="docs/polyphony-logo.png" /></p>
1
+ <h1 align="center">
2
+ <a href="https://digital-fabric.github.io/polyphony/">
3
+ <img src="docs/polyphony-logo.png" alt="Polyphony">
4
+ </a>
5
+ <br>
6
+ Polyphony
7
+ <br>
8
+ </h1>
2
9
 
3
- # Polyphony - Fine-Grained Concurrency for Ruby
10
+ <h4 align="center">Fine-Grained Concurrency for Ruby</h4>
4
11
 
5
- [![Gem Version](https://badge.fury.io/rb/polyphony.svg)](http://rubygems.org/gems/polyphony)
6
- [![Modulation Test](https://github.com/digital-fabric/polyphony/workflows/Tests/badge.svg)](https://github.com/digital-fabric/polyphony/actions?query=workflow%3ATests)
7
- [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/digital-fabric/polyphony/blob/master/LICENSE)
12
+ <p align="center">
13
+ <a href="http://rubygems.org/gems/polyphony">
14
+ <img src="https://badge.fury.io/rb/polyphony.svg" alt="Ruby gem">
15
+ </a>
16
+ <a href="https://github.com/digital-fabric/polyphony/actions?query=workflow%3ATests">
17
+ <img src="https://github.com/digital-fabric/polyphony/workflows/Tests/badge.svg" alt="Tests">
18
+ </a>
19
+ <a href="https://github.com/digital-fabric/polyphony/blob/master/LICENSE">
20
+ <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
21
+ </a>
22
+ </p>
8
23
 
9
24
  [DOCS](https://digital-fabric.github.io/polyphony/) |
10
25
  [EXAMPLES](examples)
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ task :stress_test do
20
20
  end
21
21
 
22
22
  task :docs do
23
- exec 'RUBYOPT=-W0 jekyll serve -s docs -H ec2-35-158-110-38.eu-central-1.compute.amazonaws.com'
23
+ exec 'RUBYOPT=-W0 jekyll serve -s docs -H ec2-18-156-117-172.eu-central-1.compute.amazonaws.com'
24
24
  end
25
25
 
26
26
  CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "**/*.jar", "pkg", "tmp"
data/TODO.md CHANGED
@@ -1,13 +1,19 @@
1
- - Implement `LibevAgent#connect` API
2
- - Reimplement ResourcePool, Channel, Mutex using Queue
3
- -- Add `Fiber#schedule_with_priority` method, aliased by `Fiber#wakeup`
4
- - Implement agent interface is virtual function table
5
- - Implement proxy agent for plugging in a user-provided agent class
1
+ 0.45
2
+
3
+ - Review all code
4
+ - Cleanup C code
5
+ - Cleanup and annotate examples (and remove all the examples used for
6
+ debugging). Focus on examples that serve as "how-to".
7
+
8
+ 0.45.1
9
+
10
+ - Adapter for Pry and IRB (Which fixes #5 and #6)
11
+
12
+ 0.46.0
6
13
 
7
14
  - Debugging
8
15
  - Eat your own dogfood: need a good tool to check what's going on when some
9
16
  test fails
10
- - Needs to work with Pry (can write perhaps an extension for pry)
11
17
  - First impl in Ruby using `TracePoint` API
12
18
  - Mode of operation:
13
19
  - Two parts: tracer and controller
@@ -117,7 +123,7 @@
117
123
  - discuss using `snooze` for ensuring responsiveness when executing CPU-bound work
118
124
 
119
125
 
120
- ## 0.44
126
+ ## 0.47
121
127
 
122
128
  ### Some more API work, more docs
123
129
 
@@ -130,13 +136,13 @@
130
136
  - proceed from there
131
137
 
132
138
 
133
- ## 0.45
139
+ ## 0.48
134
140
 
135
141
  ### Sinatra / Sidekiq
136
142
 
137
143
  - Pull out redis/postgres code, put into new `polyphony-xxx` gems
138
144
 
139
- ## 0.46
145
+ ## 0.49
140
146
 
141
147
  ### Testing && Docs
142
148
 
@@ -148,11 +154,7 @@
148
154
  - `IO.foreach`
149
155
  - `Process.waitpid`
150
156
 
151
- ## 0.47
152
-
153
- ### Real IO#gets and IO#read
154
-
155
- ## 0.48 DNS
157
+ ## 0.50 DNS
156
158
 
157
159
  ### DNS client
158
160
 
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ `rake recompile`
5
+
6
+ count = ARGV[0] ? ARGV[0].to_i : 100
7
+
8
+ TEST_CMD = 'ruby test/run.rb'
9
+
10
+ def run_test(count)
11
+ puts "#{count}: running tests..."
12
+ system(TEST_CMD)
13
+ return if $?.exitstatus == 0
14
+
15
+ puts "Failure after #{count} tests"
16
+ exit!
17
+ end
18
+
19
+ trap('INT') { exit! }
20
+ t0 = Time.now
21
+ count.times { |i| run_test(i + 1) }
22
+ elapsed = Time.now - t0
23
+ puts format(
24
+ "Successfully ran %d tests in %f seconds (%f per test)",
25
+ count,
26
+ elapsed,
27
+ elapsed / count
28
+ )
@@ -0,0 +1,77 @@
1
+ # Polyphony 0.44.1
2
+
3
+ ## More performance, more compatibility, more robustness
4
+
5
+ The last three weeks have been very busy for Polyphony. Since I first presented
6
+ Polyphony here and elsewhere, 17 issues were closed, 10 pull requests were
7
+ merged, and 144 commits were made by 4 different authors. I'm really
8
+ excited about Polyphony and the momentum it seems to be gathering. Your
9
+ reactions have been very positive so far (it even got [tweeted by
10
+ Matz!](https://twitter.com/yukihiro_matz/status/1279289318083715073))
11
+
12
+ I'm even more excited about the contributions Polyphony is starting to get from
13
+ other developers. Thank you [Will](https://github.com/wjordan),
14
+ [Máximo](https://github.com/ElMassimo) and [Trent](https://github.com/misfo) for
15
+ your valuable contributions! Also, the Polyphony project has now got a logo
16
+ designed by my friend [Gérald Morales](https://webocube.com/).
17
+
18
+ I'd like to encourage other developers to get in on the action and start
19
+ contributing by testing Polyphony, creating issues and writing code and
20
+ documentation. Together we can make Polyphony a game-changer for developing
21
+ concurrent apps in Ruby, and finally put to rest the notion that "Ruby is slow"!
22
+
23
+ Since the last public release of Polyphony, we have focused on fixing bugs,
24
+ improving performance and introducing new features that improve the Polyphony
25
+ developer experience. Polyphony 0.44 is up to 20% percent faster than the
26
+ previous release, due notably to a new ring-buffer implementation used by the
27
+ fiber run queue and the `Polyphony::Queue` class, a new `Backend#read_loop` API
28
+ for tighter server loops, and minimizing `fcntl` syscalls when doing I/O. These
29
+ and other minor improvements have resulted in Polyphony first crossing the
30
+ 50,000 requests per second threshold for the first time in a minimal [rack
31
+ server
32
+ example](https://github.com/digital-fabric/polyphony/blob/master/examples/io/xx-rack_server.rb).
33
+
34
+ Notable new features include a MySQL adapter, a Sequel adapter, and a new
35
+ `Fiber#interject` API that allows executing arbitrary code on arbitrary fibers.
36
+
37
+ We have also fixed numerous bugs, among which an issue building Polyphony on
38
+ MacOS, problems issuing `Net::HTTP` requests with secure URLs, an issue with
39
+ `YAML.load` and much more...
40
+
41
+ For the full list of changes please consult the [change log](https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md).
42
+
43
+ ## What's next for Polyphony?
44
+
45
+ The next release of Polyphony will focus on full support IRB and Pry. Being able
46
+ to run operations in the background in IRB and Pry can be very beneficial, most
47
+ of all when developing and when debugging running processes using `binding.pry`
48
+ for example.
49
+
50
+ Subsequent releases will introduce a whole new full-featured debugger for
51
+ fiber-aware concurrent apps, and eventually full support for Sequel, Sinatra,
52
+ Hanami, Sidekiq and other major areas of the Ruby ecosystem.
53
+
54
+ ## Tipi - a polyphonic web server for Ruby
55
+
56
+ [Tipi](https://github.com/digital-fabric/tipi) is a new web server for Ruby
57
+ apps. It is intended to be *the* go-to app server for Ruby apps looking for
58
+ robustness, scalability and performance. Tipi already supports HTTP/1, HTTP/2,
59
+ WebSockets and SSL termination. It can currently drive simple Rack apps. In the
60
+ future Tipi will be fully compliant with the Rack specification, and will also
61
+ offer a static file server, a rich configuration and automatic TLS certificates
62
+ (using Let's Encrypt) out of the box.
63
+
64
+ For those wondering about performance, here are some preliminary numbers (see
65
+ disclaimer below):
66
+
67
+ - HTTP, hello world, single process: ~50000 requests/second
68
+ - HTTP, Rack hello world app, single process: ~33000 requests/second
69
+ - HTTP, Rack hello world, 4 worker processes: ~95000 requests/second
70
+ - HTTPS, hello world, single process: ~20000 requests/second
71
+ - HTTPS, hello world, 4 worker processes: ~72000 requests/second
72
+
73
+ Disclaimer: these numbers should be taken with a grain of salt. They do not
74
+ follow any established benchmarking methodology, and may vary significantly. The
75
+ different configurtations were benchmarked using the command: `wrk -d10 -t1 -c10
76
+ "<http|https>://127.0.0.1:1234/"` on the same machine (an `m2.xlarge` instance)
77
+ as the server. In the future Tipi's performance might substantially change. YMMV.
@@ -12,7 +12,7 @@ Polyphony enhances the core `Thread` class with APIs for switching and
12
12
  scheduling fibers, and reimplements some of its APIs such as `Thread#raise`
13
13
  using fibers which, incidentally, make it safe.
14
14
 
15
- Each thread has its own run queue and its own system agent. While running
15
+ Each thread has its own run queue and its own system backend. While running
16
16
  multiple threads does not result in true parallelism in MRI Ruby, sometimes
17
17
  multithreading is inevitable, for instance when using third-party gems that
18
18
  spawn threads, or when calling blocking APIs that are not fiber-aware.
@@ -341,25 +341,25 @@ move_on_after(10) { perform_query }
341
341
  cancel_after(10) { perform_query }
342
342
  ```
343
343
 
344
- ## The System Agent
344
+ ## The Polyphony Backend
345
345
 
346
346
  In order to implement automatic fiber switching when performing blocking
347
- operations, Polyphony introduces a concept called the *system agent*. The system
348
- agent is an object having a uniform interface, that performs all blocking
347
+ operations, Polyphony introduces a concept called the *system backend*. The system
348
+ backend is an object having a uniform interface, that performs all blocking
349
349
  operations.
350
350
 
351
351
  While a standard event loop-based solution would implement a blocking call
352
- separately from the fiber scheduling, the system agent integrates the two to
352
+ separately from the fiber scheduling, the system backend integrates the two to
353
353
  create a blocking call that is already knows how to switch and schedule fibers.
354
354
  For example, in Polyphony all APIs having to do with reading from files or
355
- sockets end up calling `Thread.current.agent.read`, which does all the work.
355
+ sockets end up calling `Thread.current.backend.read`, which does all the work.
356
356
 
357
357
  This design offers some major advantages over other designs. It minimizes memory
358
358
  allocations, of both Ruby objects and C structures. For example, instead of
359
359
  having to allocate libev watchers on the heap and then pass them around, they
360
360
  are allocated on the stack instead, which saves up on both memory and CPU cycles.
361
361
 
362
- In addition, the agent interface includes two methods that allow maximizing
362
+ In addition, the backend interface includes two methods that allow maximizing
363
363
  server performance by accepting connections and reading from sockets in a tight
364
364
  loop. Here's a naive implementation of an HTTP/1 server:
365
365
 
@@ -372,7 +372,7 @@ def handle_client(socket)
372
372
  reqs = []
373
373
  parser.on_message_complete = proc { |env| reqs << { foo: :bar } }
374
374
 
375
- Thread.current.agent.read_loop(socket) do |data|
375
+ Thread.current.backend.read_loop(socket) do |data|
376
376
  parser << data
377
377
  reqs.each { |r| reply(socket, r) }
378
378
  reqs.clear
@@ -388,20 +388,20 @@ end
388
388
  server = TCPServer.open('0.0.0.0', 1234)
389
389
  puts "listening on port 1234"
390
390
 
391
- Thread.current.agent.accept_loop(server) do |client|
391
+ Thread.current.backend.accept_loop(server) do |client|
392
392
  spin { handle_client(client) }
393
393
  end
394
394
  ```
395
395
 
396
- The `#read_loop` and `#accept_loop` agent methods implement tight loops that
396
+ The `#read_loop` and `#accept_loop` backend methods implement tight loops that
397
397
  provide a significant boost to performance (up to +30% better throughput.)
398
398
 
399
- Currently, Polyphony includes a single system agent based on
399
+ Currently, Polyphony includes a single system backend based on
400
400
  [libev](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod). In the future,
401
- Polyphony will include other platform-specific system agents, such as a Windows
402
- agent using
401
+ Polyphony will include other platform-specific system backends, such as a Windows
402
+ backend using
403
403
  [IOCP](https://docs.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports),
404
- or an [io_uring](https://unixism.net/loti/what_is_io_uring.html) agent,
404
+ or an [io_uring](https://unixism.net/loti/what_is_io_uring.html) backend,
405
405
  which might be a game-changer for writing highly-concurrent Ruby-based web apps.
406
406
 
407
407
  ## Writing Web Apps with Polyphony
@@ -482,5 +482,5 @@ reach version 1.0. Here are some of the exciting directions we're working on.
482
482
 
483
483
  - Support for more core and stdlib APIs
484
484
  - More adapters for gems with C-extensions, such as `mysql`, `sqlite3` etc
485
- - Use `io_uring` agent as alternative to the libev agent
485
+ - Use `io_uring` backend as alternative to the libev backend
486
486
  - More concurrency constructs for building highly concurrent applications