anycable 0.5.2 → 0.6.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +25 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +31 -0
  4. data/.rubocop.yml +22 -22
  5. data/.travis.yml +1 -2
  6. data/CHANGELOG.md +92 -0
  7. data/README.md +10 -58
  8. data/anycable.gemspec +10 -7
  9. data/benchmarks/.gitignore +1 -0
  10. data/benchmarks/2018-10-27.md +181 -0
  11. data/benchmarks/assets/2018-10-27-action-cable-rss.png +0 -0
  12. data/benchmarks/assets/2018-10-27-action-cable-rtt.png +0 -0
  13. data/benchmarks/assets/2018-10-27-anycable-rss.png +0 -0
  14. data/benchmarks/assets/2018-10-27-anycable-rtt.png +0 -0
  15. data/benchmarks/assets/2018-10-27-async-rss.png +0 -0
  16. data/benchmarks/assets/2018-10-27-async-rtt.png +0 -0
  17. data/benchmarks/assets/2018-10-27-falcon-cable-rss.png +0 -0
  18. data/benchmarks/assets/2018-10-27-falcon-cable-rtt.png +0 -0
  19. data/benchmarks/assets/2018-10-27-iodine-cable-rss.png +0 -0
  20. data/benchmarks/assets/2018-10-27-iodine-cable-rtt.png +0 -0
  21. data/benchmarks/assets/2018-10-27-plezi-rss.png +0 -0
  22. data/benchmarks/assets/2018-10-27-plezi-rtt.png +0 -0
  23. data/benchmarks/bench.png +0 -0
  24. data/benchmarks/benchmark.yml +12 -10
  25. data/benchmarks/hosts +2 -2
  26. data/benchmarks/rtt_plot.py +74 -0
  27. data/benchmarks/rtt_plot_test.py +16 -0
  28. data/benchmarks/servers.yml +25 -3
  29. data/bin/anycable +13 -0
  30. data/etc/bug_report_template.rb +1 -1
  31. data/lib/anycable.rb +53 -16
  32. data/lib/anycable/broadcast_adapters.rb +33 -0
  33. data/lib/anycable/broadcast_adapters/redis.rb +42 -0
  34. data/lib/anycable/cli.rb +323 -0
  35. data/lib/anycable/config.rb +91 -17
  36. data/lib/anycable/exceptions_handling.rb +31 -0
  37. data/lib/anycable/handler/capture_exceptions.rb +39 -0
  38. data/lib/anycable/health_server.rb +53 -31
  39. data/lib/anycable/middleware.rb +19 -0
  40. data/lib/anycable/middleware_chain.rb +58 -0
  41. data/lib/anycable/rpc/rpc_pb.rb +1 -1
  42. data/lib/anycable/rpc/rpc_services_pb.rb +1 -1
  43. data/lib/anycable/rpc_handler.rb +28 -26
  44. data/lib/anycable/server.rb +114 -39
  45. data/lib/anycable/socket.rb +1 -1
  46. data/lib/anycable/version.rb +2 -2
  47. metadata +45 -26
  48. data/lib/anycable/handler/exceptions_handling.rb +0 -43
  49. data/lib/anycable/pubsub.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '079d557557d69550f4a490d8fcbcd35b922df102af44c076ea14bc92bff5dda3'
4
- data.tar.gz: 29339983ff86ec5f52959397b566926c00d7116fa8dd56dc4933bac4bd526689
3
+ metadata.gz: f38ac8ce1378f75f5e1b4379c51254a346a2576fdb8326e6e2efb5d1820e857f
4
+ data.tar.gz: 0fa60623686123be319a92c8548b82ae4c3bf9ddadade0234cb3d69118599cd3
5
5
  SHA512:
6
- metadata.gz: a4fdb1f8ccbb3c633996c4aae85ce60263ab5c8f68f13909d93ef2ebe390e5124901b2832221b7fdd809fef1e3ae04628e4e5437aa6f262da51248041b5d0030
7
- data.tar.gz: ba3d770e79aa4775e894d2f568787f62d96f1e699828549e0dba1880a85597e01e565fe0781a51b1da42f7cd359cc7580846c7c01f297ee498e4cbfacfba8329
6
+ metadata.gz: 18014f2f1193f3e4f2984e4800b14097e131f9b93e413cada4f29805295c1b8153f75d9e7b00b843feb7e66c34c1ffa3e6c24d5494f3c0e516dc693ed39acb94
7
+ data.tar.gz: c27a42de1a8b6539a4906e75afe3cea4ac4a5e39c1a006ed06ba106f0b0f99d51b7052a93e54cbfe8ab72114f7b43f34f692214009038a82f7839e614e960b15
@@ -0,0 +1,25 @@
1
+ <!--
2
+ First of all, thanks for your report/suggestion/whatever!
3
+
4
+ This template is for bug reports. If you are reporting a bug, please continue on. If you are here for another reason,
5
+ feel free to skip the rest of this template.
6
+ -->
7
+
8
+ ### Tell us about your environment
9
+
10
+ **Ruby version:**
11
+
12
+ **`anycable` gem version:**
13
+
14
+ **`grpc` gem version:**
15
+
16
+ ### What did you do?
17
+
18
+ ### What did you expect to happen?
19
+
20
+ ### What actually happened?
21
+
22
+ <!--
23
+ Please, provide reproduction script (using this template (https://github.com/anycable/anycable/blob/master/etc/bug_report_template.rb)
24
+ when submitting bugs if possible.
25
+ -->
@@ -0,0 +1,31 @@
1
+ <!--
2
+ First of all, thanks for contributing!
3
+
4
+ If it's a typo fix or minor documentation update feel free to skip the rest of this template!
5
+ -->
6
+
7
+ <!--
8
+ If it's a bug fix, then link it to the issue, for example:
9
+
10
+ Fixes #xxx
11
+ -->
12
+
13
+
14
+ <!--
15
+ Otherwise, describe the changes:
16
+
17
+ ### What is the purpose of this pull request?
18
+
19
+ ### What changes did you make? (overview)
20
+
21
+ ### Is there anything you'd like reviewers to focus on?
22
+
23
+ -->
24
+
25
+ <!--
26
+ Please ensure your PR is ready:
27
+
28
+ - Include tests for this change
29
+ - Add Changelog entry
30
+ - Update documentation for this change (if appropriate)
31
+ -->
data/.rubocop.yml CHANGED
@@ -6,11 +6,9 @@ AllCops:
6
6
  - 'spec/**/*.rb'
7
7
  Exclude:
8
8
  - 'bin/**/*'
9
- - 'spec/dummy/**/*'
10
9
  - 'tmp/**/*'
11
- - 'bench/**/*'
12
- - 'vendor/**/*'
13
10
  - 'lib/anycable/rpc/**/*'
11
+ - 'vendor/**/*'
14
12
  - 'gemfiles/**/*'
15
13
  - 'Gemfile'
16
14
  - 'Rakefile'
@@ -19,16 +17,7 @@ AllCops:
19
17
  StyleGuideCopsOnly: false
20
18
  TargetRubyVersion: 2.4
21
19
 
22
- Naming/AccessorMethodName:
23
- Enabled: false
24
-
25
- Naming/UncommunicativeMethodParamName:
26
- Enabled: false
27
-
28
- Style/PercentLiteralDelimiters:
29
- Enabled: false
30
-
31
- Style/TrivialAccessors:
20
+ Rails:
32
21
  Enabled: false
33
22
 
34
23
  Style/Documentation:
@@ -36,7 +25,7 @@ Style/Documentation:
36
25
  - 'spec/**/*.rb'
37
26
 
38
27
  Style/StringLiterals:
39
- Enabled: false
28
+ EnforcedStyle: double_quotes
40
29
 
41
30
  Layout/SpaceInsideStringInterpolation:
42
31
  EnforcedStyle: no_space
@@ -45,11 +34,13 @@ Style/BlockDelimiters:
45
34
  Exclude:
46
35
  - 'spec/**/*.rb'
47
36
 
48
- Lint/AmbiguousRegexpLiteral:
49
- Enabled: false
37
+ Style/ClassAndModuleChildren:
38
+ Exclude:
39
+ - 'spec/**/*.rb'
50
40
 
51
- Lint/MissingCopEnableDirective:
52
- Enabled: false
41
+ Style/ParallelAssignment:
42
+ Exclude:
43
+ - 'spec/**/*.rb'
53
44
 
54
45
  Metrics/MethodLength:
55
46
  Exclude:
@@ -60,12 +51,21 @@ Metrics/LineLength:
60
51
  Exclude:
61
52
  - 'spec/**/*.rb'
62
53
 
54
+ Metrics/AbcSize:
55
+ Exclude:
56
+ - 'spec/**/*.rb'
57
+
63
58
  Metrics/BlockLength:
64
59
  Exclude:
65
60
  - 'spec/**/*.rb'
66
61
 
67
- Rails/Date:
68
- Enabled: false
62
+ Metrics/CyclomaticComplexity:
63
+ Exclude:
64
+ - 'spec/**/*.rb'
65
+
66
+ Metrics/PerceivedComplexity:
67
+ Exclude:
68
+ - 'spec/**/*.rb'
69
69
 
70
- Rails/TimeZone:
71
- Enabled: false
70
+ Lint/HandleExceptions:
71
+ Enabled: false
data/.travis.yml CHANGED
@@ -8,6 +8,5 @@ notifications:
8
8
  email: false
9
9
 
10
10
  rvm:
11
- - 2.3.6
12
11
  - 2.4.3
13
- - 2.5.0
12
+ - 2.5.1
data/CHANGELOG.md CHANGED
@@ -2,6 +2,98 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.6.0-dev
6
+
7
+ ### Features
8
+
9
+ #### Broadcast adapters
10
+
11
+ AnyCable allows you to use custom broadcasting adapters (Redis is used by default):
12
+
13
+ ```ruby
14
+ # Specify by name (tries to load `AnyCable::BroadcastAdapters::MyAdapter` from
15
+ # "anycable/broadcast_adapters/my_adapter")
16
+ AnyCable.broadcast_adapter = :my_adapter, { option: "value" }
17
+ # or provide an instance (should respond_to #broadcast)
18
+ AnyCable.broadcast_adapter = MyAdapter.new
19
+ ```
20
+
21
+ **Breaking:** to use Redis adapter you must ensure that it is present in your Gemfile; AnyCable gem doesn't have `redis` as a dependency anymore.
22
+
23
+ #### CLI
24
+
25
+ AnyCable now ships with a CLI–`anycable`.
26
+
27
+ Use it to run a gRPC server:
28
+
29
+ ```sh
30
+ # run anycable and load app from app.rb
31
+ bundle exec anycable -r app.rb
32
+ # or
33
+ bundle exec anycable --require app.rb
34
+ ```
35
+
36
+ All configuration options are also supported as CLI options (see `anycable -h` for more information).
37
+
38
+ The only required options is the application file to load (`-r/--require`).
39
+
40
+ You can omit it if you want to load an app form `./config/environment.rb` (e.g. with Rails) or `./config/anycable.rb`.
41
+
42
+ AnyCable CLI also allows you to run a separate command (process) from within a RPC server:
43
+
44
+ ```sh
45
+ $ bundle exec anycable --server-command "anycable-go -p 3334"
46
+ ```
47
+
48
+ #### Configuration
49
+
50
+ - Default server host is changed from `localhost:50051` to `0.0.0.0:50051`
51
+ - Expose gRPC server parameters via `rpc_*` config params:
52
+
53
+ ```ruby
54
+ AnyCable.configure do |config|
55
+ config.rpc_pool_size = 120
56
+ config.rpc_max_waiting_requests = 10
57
+ # etc
58
+ end
59
+ ```
60
+ - `REDIS_URL` env is used by default if present (and no `ANYCABLE_REDIS_URL` specified)
61
+ - Make HTTP health check url configurable
62
+ - Add ability to pass Redis Sentinel config as array of string.
63
+
64
+ Now it's possible to pass Sentinel configuration via env vars:
65
+
66
+ ```sh
67
+ ANYCABLE_REDIS_SENTINELS=127.0.0.1:26380,127.0.0.1:26381 bundle exec anycable
68
+ ```
69
+
70
+ #### Other
71
+
72
+ - Added middlewares support
73
+
74
+ See [docs](https://docs.anycable.io/#/./middlewares).
75
+
76
+ - Added gRPC health checker.
77
+
78
+ See [docs](https://docs.anycable.io/#/./health_checking).
79
+
80
+ ### API changes
81
+
82
+ **NOTE**: the old API is still working but deprecated (you'll see a notice).
83
+
84
+ - Use `AnyCable` instead of `Anycable`
85
+
86
+ - New API for registering error handlers:
87
+
88
+ ```ruby
89
+ AnyCable.capture_exception do |ex|
90
+ Honeybadger.notify(ex)
91
+ end
92
+ ```
93
+
94
+ - `AnyCable::Server.start` is deprecated
95
+
96
+
5
97
  ## 0.5.2 (2018-09-06)
6
98
 
7
99
  - [#48](https://github.com/anycable/anycable/pull/48) Add HTTP health server ([@DarthSim][])
data/README.md CHANGED
@@ -1,40 +1,27 @@
1
- [![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/anycable/anycable/master?grs=github) [![Gem Version](https://badge.fury.io/rb/anycable.svg)](https://rubygems.org/gems/anycable) [![Build Status](https://travis-ci.org/anycable/anycable.svg?branch=master)](https://travis-ci.org/anycable/anycable) [![Circle CI](https://circleci.com/gh/anycable/anycable/tree/master.svg?style=svg)](https://circleci.com/gh/anycable/anycable/tree/master)
1
+ [![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/anycable/anycable/master?grs=github) [![Gem Version](https://badge.fury.io/rb/anycable.svg)](https://rubygems.org/gems/anycable) [![Build Status](https://travis-ci.org/anycable/anycable.svg?branch=master)](https://travis-ci.org/anycable/anycable)
2
2
  [![Gitter](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/anycable/Lobby)
3
+ [![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://docs.anycable.io)
3
4
 
4
- # Anycable
5
+ # AnyCable
6
+
7
+ <img align="right" height="150" width="129"
8
+ title="AnyCable logo" src="https://docs.anycable.io/assets/images/logo.svg">
5
9
 
6
10
  AnyCable allows you to use any WebSocket server (written in any language) as a replacement for your Ruby server (such as Faye, ActionCable, etc).
7
11
 
8
12
  AnyCable uses ActionCable protocol, so you can use ActionCable [JavaScript client](https://www.npmjs.com/package/actioncable) without any monkey-patching.
9
13
 
10
- **NOTE**: Since version 0.4.0 this repository contains only core functionality and cannot be used separately as is.
11
- Rails plug-n-play integration has been extracted to [anycable-rails](https://github.com/anycable/anycable-rails) gem.
12
-
13
14
  <a href="https://evilmartians.com/">
14
15
  <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
15
16
 
16
17
  ## Requirements
17
18
 
18
- - Ruby >= 2.3, <= 2.5
19
+ - Ruby >= 2.4
19
20
  - Redis (for brodcasting, [discuss other options](https://github.com/anycable/anycable/issues/2) with us!)
20
21
 
21
- Or you can try to [build it from source](https://github.com/grpc/grpc/blob/master/INSTALL.md#build-from-source).
22
-
23
- For MacOS there is also [the same problem](https://github.com/google/protobuf/issues/4098) with `google-protobuf` that can be solved
24
- the following way:
25
-
26
- ```ruby
27
- # Gemfile
28
- git 'https://github.com/google/protobuf' do
29
- gem 'google-protobuf'
30
- end
31
- ```
32
-
33
- ## How It Works?
34
-
35
- ![](https://s3.amazonaws.com/anycable/Scheme.png)
22
+ ## Usage
36
23
 
37
- Read our [Wiki](https://github.com/anycable/anycable/wiki) for more.
24
+ Check out our 📑 [Documentation](https://docs.anycable.io).
38
25
 
39
26
  ## Links
40
27
 
@@ -54,46 +41,11 @@ Read our [Wiki](https://github.com/anycable/anycable/wiki) for more.
54
41
 
55
42
  - RailsClub Moscow 2016 [slides](https://speakerdeck.com/palkan/railsclub-moscow-2016-anycable) and [video](https://www.youtube.com/watch?v=-k7GQKuBevY&list=PLiWUIs1hSNeOXZhotgDX7Y7qBsr24cu7o&index=4) (RU)
56
43
 
57
-
58
44
  ## Compatible WebSocket servers
59
45
 
60
- - [Anycable Go](https://github.com/anycable/anycable-go)
46
+ - [AnyCable Go](https://github.com/anycable/anycable-go)
61
47
  - [ErlyCable](https://github.com/anycable/erlycable)
62
48
 
63
- ## Configuration
64
-
65
- Anycable uses [anyway_config](https://github.com/palkan/anyway_config), thus it is also possible to set configuration variables through `secrets.yml` or environment vars.
66
-
67
- ### Example with redis sentinel
68
-
69
- ```yaml
70
- rpc_host: "localhost:50123"
71
- redis_url: "redis://redis-1-1:6379/2"
72
- redis_sentinels:
73
- - { host: 'redis-1-1', port: 26379 }
74
- - { host: 'redis-1-2', port: 26379 }
75
- - { host: 'redis-1-3', port: 26379 }
76
- ```
77
-
78
- ## ActionCable Compatibility
79
-
80
- This is the compatibility list for the AnyCable gem, not for AnyCable servers (which may not support some of the features yet).
81
-
82
- Feature | Status
83
- -------------------------|--------
84
- Connection Identifiers | +
85
- Connection Request (cookies, params) | +
86
- Disconnect Handling | +
87
- Subscribe to channels | +
88
- Parameterized subscriptions | +
89
- Unsubscribe from channels | +
90
- [Subscription Instance Variables](http://edgeapi.rubyonrails.org/classes/ActionCable/Channel/Streams.html) | -
91
- Performing Channel Actions | +
92
- Streaming | +
93
- [Custom stream callbacks](http://edgeapi.rubyonrails.org/classes/ActionCable/Channel/Streams.html) | -
94
- Broadcasting | +
95
- Custom pubsub adapter | Only redis
96
-
97
49
  ## Build
98
50
 
99
51
  - Install required GRPC gems:
data/anycable.gemspec CHANGED
@@ -6,27 +6,30 @@ require 'anycable/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = "anycable"
9
- spec.version = Anycable::VERSION
9
+ spec.version = AnyCable::VERSION
10
10
  spec.authors = ["palkan"]
11
11
  spec.email = ["dementiev.vm@gmail.com"]
12
12
 
13
- spec.summary = "Polyglot replacement for ActionCable server"
14
- spec.description = "Polyglot replacement for ActionCable server"
13
+ spec.summary = "AnyCable is a polyglot replacement for ActionCable-compatible servers"
14
+ spec.description = "AnyCable is a polyglot replacement for ActionCable-compatible servers"
15
15
  spec.homepage = "http://github.com/anycable/anycable"
16
16
  spec.license = "MIT"
17
17
 
18
+ spec.executables = ["anycable"]
18
19
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
20
  spec.require_paths = ["lib"]
20
21
 
21
- spec.add_dependency "anyway_config", "~> 1.1", ">= 1.1.1"
22
- spec.add_dependency "grpc", "~> 1.6"
23
- spec.add_dependency "redis", ">= 3.2"
22
+ spec.required_ruby_version = '>= 2.4.0'
24
23
 
24
+ spec.add_dependency "anyway_config", "~> 1.4.1"
25
+ spec.add_dependency "grpc", "~> 1.15"
26
+
27
+ spec.add_development_dependency "redis", ">= 4.0"
25
28
  spec.add_development_dependency "bundler", "~> 1"
26
29
  spec.add_development_dependency "rake", ">= 10.0"
27
30
  spec.add_development_dependency "rack", "~> 2.0"
28
31
  spec.add_development_dependency "rspec", ">= 3.5"
29
- spec.add_development_dependency "rubocop", "~> 0.58.0"
32
+ spec.add_development_dependency "rubocop", "~> 0.60.0"
30
33
  spec.add_development_dependency "simplecov", ">= 0.3.8"
31
34
  spec.add_development_dependency "pry-byebug"
32
35
  end
@@ -1 +1,2 @@
1
1
  *.retry
2
+ *.pyc
@@ -0,0 +1,181 @@
1
+ # WebSocket Shootout Benchmark (2018-10-27)
2
+
3
+ Code: https://github.com/palkan/websocket-shootout
4
+
5
+ Client/Server instances: c3.2xlarge (8 vCPU, 15 GiB RAM).
6
+
7
+ Ruby: 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin16]
8
+ Rails: 5.2.0 / 6.0.0.aplha (this [PR](https://github.com/rails/rails/pull/33295))
9
+
10
+ The benchmark measures broadcasting RTT for 10k clients and the memory usage.
11
+
12
+ Memory usage charts were captured with [psrecord](https://github.com/astrofrog/psrecord):
13
+
14
+ ```sh
15
+ psrecord <pid> --include-children --plot plot.png
16
+ ```
17
+
18
+ ## Action Cable + Puma (8 workers)
19
+
20
+ Server: `WEB_CONCURRENCY=8 bundle exec rails s -p 3334 -e production`
21
+
22
+ ```
23
+ $ bin/websocket-bench broadcast --concurrent 8 --sample-size 100 --step-size 1000 --payload-padding 200 --total-steps 10 --origin http://0.0.0.0 ws://172.31.21.207:3334/cable --server-type=actioncable
24
+
25
+ clients: 1000 95per-rtt: 2470ms min-rtt: 1ms median-rtt: 518ms max-rtt: 2893ms
26
+ clients: 2000 95per-rtt: 3066ms min-rtt: 1ms median-rtt: 1045ms max-rtt: 3878ms
27
+ clients: 3000 95per-rtt: 3785ms min-rtt: 1ms median-rtt: 2071ms max-rtt: 4211ms
28
+ clients: 4000 95per-rtt: 5141ms min-rtt: 1ms median-rtt: 2363ms max-rtt: 6042ms
29
+ clients: 5000 95per-rtt: 9477ms min-rtt: 1ms median-rtt: 3283ms max-rtt: 10000ms
30
+ clients: 6000 95per-rtt: 7038ms min-rtt: 1ms median-rtt: 3898ms max-rtt: 8684ms
31
+ clients: 7000 95per-rtt: 8517ms min-rtt: 2ms median-rtt: 4108ms max-rtt: 8436ms
32
+ clients: 8000 95per-rtt: 9105ms min-rtt: 2ms median-rtt: 5387ms max-rtt: 9166ms
33
+ clients: 9000 95per-rtt: 10064ms min-rtt: 1ms median-rtt: 5335ms max-rtt: 10108ms
34
+ clients: 10000 95per-rtt: 15766ms min-rtt: 2ms median-rtt: 5921ms max-rtt: 17907ms
35
+ ```
36
+
37
+ ![](assets/2018-10-27-action-cable-rtt.png)
38
+
39
+ ![](assets/2018-10-27-action-cable-rss.png)
40
+
41
+ ## Action Cable + Iodine (8 workers & 16 threads)
42
+
43
+ Server: `bundle exec iodine -p 3334 -w 8 -t 16`
44
+
45
+ ```
46
+ $ bin/websocket-bench broadcast --concurrent 8 --sample-size 100 --step-size 1000 --payload-padding 200 --total-steps 10 --origin http://0.0.0.0 ws://172.31.21.207:3334/cable --server-type=actioncable
47
+
48
+ clients: 1000 95per-rtt: 2354ms min-rtt: 1ms median-rtt: 798ms max-rtt: 2944ms
49
+ clients: 2000 95per-rtt: 3199ms min-rtt: 2ms median-rtt: 2068ms max-rtt: 3603ms
50
+ clients: 3000 95per-rtt: 4808ms min-rtt: 2ms median-rtt: 3226ms max-rtt: 6016ms
51
+ clients: 4000 95per-rtt: 6628ms min-rtt: 1ms median-rtt: 4511ms max-rtt: 7520ms
52
+ clients: 5000 95per-rtt: 7761ms min-rtt: 1ms median-rtt: 5592ms max-rtt: 8828ms
53
+ clients: 6000 95per-rtt: 17042ms min-rtt: 1ms median-rtt: 4557ms max-rtt: 18245ms
54
+ clients: 7000 95per-rtt: 12331ms min-rtt: 1ms median-rtt: 8355ms max-rtt: 13525ms
55
+ clients: 8000 95per-rtt: 16785ms min-rtt: 2ms median-rtt: 6217ms max-rtt: 17609ms
56
+ clients: 9000 95per-rtt: 18438ms min-rtt: 1ms median-rtt: 1111ms max-rtt: 18848ms
57
+ clients: 10000 95per-rtt: 19034ms min-rtt: 1ms median-rtt: 11235ms max-rtt: 24343ms
58
+ ```
59
+
60
+ ![](assets/2018-10-27-iodine-cable-rtt.png)
61
+
62
+ ![](assets/2018-10-27-iodine-cable-rss.png)
63
+
64
+
65
+ ## Action Cable + Falcon (8 workers)
66
+
67
+ Server: `RAILS_ENV=production bundle exec falcon serve -b http://0.0.0.0:3334`
68
+
69
+ ```
70
+ $ bin/websocket-bench broadcast --concurrent 8 --sample-size 100 --step-size 1000 --payload-padding 200 --total-steps 10 --origin http://0.0.0.0 ws://172.31.21.207:3334/cable --server-type=actioncable
71
+
72
+
73
+ clients: 1000 95per-rtt: 1957ms min-rtt: 1ms median-rtt: 766ms max-rtt: 2077ms
74
+ clients: 2000 95per-rtt: 5225ms min-rtt: 1ms median-rtt: 624ms max-rtt: 5969ms
75
+ clients: 3000 95per-rtt: 6358ms min-rtt: 2ms median-rtt: 1205ms max-rtt: 7116ms
76
+ clients: 4000 95per-rtt: 8878ms min-rtt: 1ms median-rtt: 1152ms max-rtt: 10167ms
77
+ clients: 5000 95per-rtt: 8829ms min-rtt: 1ms median-rtt: 2368ms max-rtt: 9792ms
78
+ clients: 6000 95per-rtt: 10831ms min-rtt: 1ms median-rtt: 2892ms max-rtt: 12766ms
79
+ clients: 7000 95per-rtt: 12760ms min-rtt: 1ms median-rtt: 5229ms max-rtt: 14713ms
80
+ clients: 8000 95per-rtt: 15512ms min-rtt: 1ms median-rtt: 4843ms max-rtt: 16353ms
81
+ clients: 9000 95per-rtt: 20176ms min-rtt: 1ms median-rtt: 4919ms max-rtt: 22529ms
82
+ clients: 10000 95per-rtt: 19865ms min-rtt: 1ms median-rtt: 4733ms max-rtt: 20686ms
83
+ ```
84
+
85
+ ![](assets/2018-10-27-falcon-cable-rtt.png)
86
+
87
+ ![](assets/2018-10-27-falcon-cable-rss.png)
88
+
89
+ **NOTE**: for some reason `psrecord` reports negative RSS usage when Falcon starts (almost every run).
90
+
91
+ ## Action Cable + AnyCable-Go 0.6.0.alpha
92
+
93
+ **NOTE**: this benchmark has twice more steps (i.e. 20k instead of 10k).
94
+
95
+ Server: `ANYCABLE_GO_BIN="anycable-go-0.6.0-alpha" ANYCABLE_PORT="3334" bundle exec bin/anycable`
96
+
97
+ ```
98
+ $ bin/websocket-bench broadcast --concurrent 8 --sample-size 100 --step-size 1000 --payload-padding 200 --total-steps 10 --origin http://0.0.0.0 ws://172.31.21.207:3334/cable --server-type=actioncable
99
+
100
+ clients: 1000 95per-rtt: 200ms min-rtt: 4ms median-rtt: 30ms max-rtt: 261ms
101
+ clients: 2000 95per-rtt: 284ms min-rtt: 2ms median-rtt: 51ms max-rtt: 380ms
102
+ clients: 3000 95per-rtt: 490ms min-rtt: 5ms median-rtt: 80ms max-rtt: 651ms
103
+ clients: 4000 95per-rtt: 601ms min-rtt: 3ms median-rtt: 63ms max-rtt: 2114ms
104
+ clients: 5000 95per-rtt: 678ms min-rtt: 11ms median-rtt: 123ms max-rtt: 2946ms
105
+ clients: 6000 95per-rtt: 933ms min-rtt: 12ms median-rtt: 146ms max-rtt: 1815ms
106
+ clients: 7000 95per-rtt: 1034ms min-rtt: 17ms median-rtt: 163ms max-rtt: 4282ms
107
+ clients: 8000 95per-rtt: 866ms min-rtt: 5ms median-rtt: 205ms max-rtt: 1631ms
108
+ clients: 9000 95per-rtt: 1297ms min-rtt: 8ms median-rtt: 230ms max-rtt: 2380ms
109
+ clients: 10000 95per-rtt: 1075ms min-rtt: 4ms median-rtt: 363ms max-rtt: 2718ms
110
+ clients: 11000 95per-rtt: 1382ms min-rtt: 2ms median-rtt: 263ms max-rtt: 4310ms
111
+ clients: 12000 95per-rtt: 1448ms min-rtt: 4ms median-rtt: 205ms max-rtt: 1686ms
112
+ clients: 13000 95per-rtt: 1503ms min-rtt: 11ms median-rtt: 322ms max-rtt: 1879ms
113
+ clients: 14000 95per-rtt: 2662ms min-rtt: 4ms median-rtt: 318ms max-rtt: 5604ms
114
+ clients: 15000 95per-rtt: 2113ms min-rtt: 7ms median-rtt: 353ms max-rtt: 2484ms
115
+ clients: 16000 95per-rtt: 2930ms min-rtt: 3ms median-rtt: 383ms max-rtt: 4021ms
116
+ clients: 17000 95per-rtt: 3349ms min-rtt: 2ms median-rtt: 386ms max-rtt: 5844ms
117
+ clients: 18000 95per-rtt: 2797ms min-rtt: 4ms median-rtt: 361ms max-rtt: 6973ms
118
+ clients: 19000 95per-rtt: 3534ms min-rtt: 6ms median-rtt: 448ms max-rtt: 5482ms
119
+ clients: 20000 95per-rtt: 2892ms min-rtt: 3ms median-rtt: 399ms max-rtt: 4639ms
120
+ ```
121
+
122
+ ![](assets/2018-10-27-anycable-rtt.png)
123
+
124
+ ![](assets/2018-10-27-anycable-rss.png)
125
+
126
+ **NOTE:** RSS were captured only for `anycable-go`
127
+
128
+ ## Falcon + `async-websocket` (4 workers)
129
+
130
+ ```
131
+ $ bin/websocket-bench broadcast --concurrent 8 --sample-size 100 --step-size 1000 --payload-padding 200 --total-steps 10 ws://172.31.21.207:3334/cable
132
+
133
+ clients: 1000 95per-rtt: 964ms min-rtt: 5ms median-rtt: 542ms max-rtt: 971ms
134
+ clients: 2000 95per-rtt: 4912ms min-rtt: 1ms median-rtt: 2796ms max-rtt: 5247ms
135
+ clients: 3000 95per-rtt: 3263ms min-rtt: 6ms median-rtt: 891ms max-rtt: 4166ms
136
+ clients: 4000 95per-rtt: 1778ms min-rtt: 1ms median-rtt: 490ms max-rtt: 2115ms
137
+ clients: 5000 95per-rtt: 2294ms min-rtt: 5ms median-rtt: 513ms max-rtt: 2807ms
138
+ clients: 6000 95per-rtt: 2802ms min-rtt: 9ms median-rtt: 426ms max-rtt: 3263ms
139
+ clients: 7000 95per-rtt: 4196ms min-rtt: 7ms median-rtt: 485ms max-rtt: 5377ms
140
+ clients: 8000 95per-rtt: 4741ms min-rtt: 4ms median-rtt: 772ms max-rtt: 5005ms
141
+ clients: 9000 95per-rtt: 6207ms min-rtt: 2ms median-rtt: 972ms max-rtt: 7296ms
142
+ clients: 10000 95per-rtt: 5468ms min-rtt: 35ms median-rtt: 887ms max-rtt: 6420ms
143
+ ```
144
+
145
+ ![](assets/2018-10-27-async-rtt.png)
146
+
147
+ ![](assets/2018-10-27-async-rss.png)
148
+
149
+
150
+ ## Iodine + Plezi (4 workers & 16 threads)
151
+
152
+ **NOTE**: this benchmark has twice more steps (i.e. 20k instead of 10k).
153
+
154
+ ```
155
+ $ bin/websocket-bench broadcast --concurrent 8 --sample-size 100 --step-size 1000 --payload-padding 200 --total-steps 10 ws://172.31.21.207:3334/cable
156
+
157
+ clients: 1000 95per-rtt: 119ms min-rtt: 0ms median-rtt: 19ms max-rtt: 348ms
158
+ clients: 2000 95per-rtt: 321ms min-rtt: 1ms median-rtt: 45ms max-rtt: 634ms
159
+ clients: 3000 95per-rtt: 392ms min-rtt: 0ms median-rtt: 66ms max-rtt: 1543ms
160
+ clients: 4000 95per-rtt: 424ms min-rtt: 1ms median-rtt: 128ms max-rtt: 617ms
161
+ clients: 5000 95per-rtt: 747ms min-rtt: 1ms median-rtt: 126ms max-rtt: 1252ms
162
+ clients: 6000 95per-rtt: 659ms min-rtt: 0ms median-rtt: 153ms max-rtt: 1621ms
163
+ clients: 7000 95per-rtt: 839ms min-rtt: 0ms median-rtt: 205ms max-rtt: 1041ms
164
+ clients: 8000 95per-rtt: 995ms min-rtt: 1ms median-rtt: 221ms max-rtt: 1534ms
165
+ clients: 9000 95per-rtt: 1072ms min-rtt: 0ms median-rtt: 234ms max-rtt: 5679ms
166
+ clients: 10000 95per-rtt: 1030ms min-rtt: 0ms median-rtt: 298ms max-rtt: 3998ms
167
+ clients: 11000 95per-rtt: 1052ms min-rtt: 1ms median-rtt: 302ms max-rtt: 5539ms
168
+ clients: 12000 95per-rtt: 1017ms min-rtt: 0ms median-rtt: 332ms max-rtt: 5342ms
169
+ clients: 13000 95per-rtt: 1528ms min-rtt: 1ms median-rtt: 391ms max-rtt: 2488ms
170
+ clients: 14000 95per-rtt: 1411ms min-rtt: 1ms median-rtt: 418ms max-rtt: 1810ms
171
+ clients: 15000 95per-rtt: 1674ms min-rtt: 1ms median-rtt: 428ms max-rtt: 2154ms
172
+ clients: 16000 95per-rtt: 1436ms min-rtt: 1ms median-rtt: 463ms max-rtt: 7788ms
173
+ clients: 17000 95per-rtt: 1816ms min-rtt: 0ms median-rtt: 449ms max-rtt: 7299ms
174
+ clients: 18000 95per-rtt: 2025ms min-rtt: 1ms median-rtt: 492ms max-rtt: 4009ms
175
+ clients: 19000 95per-rtt: 1740ms min-rtt: 2ms median-rtt: 522ms max-rtt: 3834ms
176
+ clients: 20000 95per-rtt: 2017ms min-rtt: 2ms median-rtt: 591ms max-rtt: 3579ms
177
+ ```
178
+
179
+ ![](assets/2018-10-27-plezi-rtt.png)
180
+
181
+ ![](assets/2018-10-27-plezi-rss.png)