anycable 0.5.2 → 0.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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)