funnel_http 0.2.0 → 0.3.1
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.
- checksums.yaml +4 -4
- data/.golangci.yml +0 -3
- data/CHANGELOG.md +15 -1
- data/README.md +13 -1
- data/ext/funnel_http/funnel_http.go +17 -0
- data/ext/funnel_http/go.mod +5 -3
- data/ext/funnel_http/go.sum +4 -6
- data/ext/funnel_http/run_requests.go +2 -2
- data/lib/funnel_http/client.rb +3 -0
- data/lib/funnel_http/version.rb +1 -1
- data/rbs_collection.lock.yaml +11 -7
- data/sig/funnel_http.rbs +2 -1
- metadata +4 -10
- data/benchmark/README.md +0 -32
- data/benchmark/benchmark.rb +0 -61
- data/benchmark/compose.yml +0 -8
- data/benchmark/html/index.html +0 -4
- data/benchmark/nginx.conf +0 -25
- data/ext/funnel_http/run_requests_test.go +0 -120
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8dc5ca92f2cadd38540d16fefc60846938f645205482549ed6075a151b4bf446
|
4
|
+
data.tar.gz: f4d709200e55e657ba73b70c8c7cd0620ba065644f20f6393c24a765a71cbcf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60c7d733ee0cd9cf43ddb1b705ae69b8b9cb97c32eb6ad62e6d170202760307aaa0caa508128674cd4d2a1d68b78d0f985cad6a5cd15ad138e68446b6e09d171
|
7
|
+
data.tar.gz: 317bb2a84a2bb0e89ccfc92def4669a58f60a107e0756959a3298aa3b2ad0135bbb72db27bfd43825895c962f94c4ab4554e92d7877a2f5d9bd2dc9e3581d660
|
data/.golangci.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
## [Unreleased]
|
2
|
-
[full changelog](http://github.com/sue445/funnel_http/compare/v0.
|
2
|
+
[full changelog](http://github.com/sue445/funnel_http/compare/v0.3.1...main)
|
3
|
+
|
4
|
+
## [0.3.1](https://github.com/sue445/funnel_http/releases/tag/v0.3.1) - 2025-03-12
|
5
|
+
[full changelog](http://github.com/sue445/funnel_http/compare/v0.3.0...v0.3.1)
|
6
|
+
|
7
|
+
* Diet gem
|
8
|
+
* https://github.com/sue445/funnel_http/pull/66
|
9
|
+
* Tweak gem description
|
10
|
+
* https://github.com/sue445/funnel_http/pull/68
|
11
|
+
|
12
|
+
## [0.3.0](https://github.com/sue445/funnel_http/releases/tag/v0.3.0) - 2025-01-12
|
13
|
+
[full changelog](http://github.com/sue445/funnel_http/compare/v0.2.0...v0.3.0)
|
14
|
+
|
15
|
+
* Support request body
|
16
|
+
* https://github.com/sue445/funnel_http/pull/51
|
3
17
|
|
4
18
|
## [0.2.0](https://github.com/sue445/funnel_http/releases/tag/v0.2.0) - 2025-01-07
|
5
19
|
[full changelog](http://github.com/sue445/funnel_http/compare/v0.1.0...v0.2.0)
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# FunnelHttp
|
2
|
-
Perform HTTP requests in parallel
|
2
|
+
Perform HTTP requests in parallel with goroutine
|
3
3
|
|
4
4
|
[](https://badge.fury.io/rb/funnel_http)
|
5
5
|
[](https://github.com/sue445/funnel_http/actions/workflows/build.yml)
|
@@ -45,12 +45,24 @@ requests = [
|
|
45
45
|
"X-Multiple-Values" => ["1st value", "2nd value"],
|
46
46
|
},
|
47
47
|
},
|
48
|
+
|
49
|
+
# with request body
|
50
|
+
{
|
51
|
+
method: :post,
|
52
|
+
uri: "https://example.com/api/user",
|
53
|
+
header: {
|
54
|
+
"Authorization" => "Bearer xxxxxxxx",
|
55
|
+
"Content-Type" => "application/json",
|
56
|
+
},
|
57
|
+
body: '{"name": "sue445"}',
|
58
|
+
},
|
48
59
|
]
|
49
60
|
|
50
61
|
responses = client.perform(requests)
|
51
62
|
# => [
|
52
63
|
# { status_code: 200, body: "Response of /api/user/1", header: { "Content-Type" => ["text/plain;charset=utf-8"]} }
|
53
64
|
# { status_code: 200, body: "Response of /api/user/2", header: { "Content-Type" => ["text/plain;charset=utf-8"]} }
|
65
|
+
# { status_code: 200, body: "Response of /api/user", header: { "Content-Type" => ["text/plain;charset=utf-8"]} }
|
54
66
|
# ]
|
55
67
|
```
|
56
68
|
|
@@ -26,6 +26,7 @@ func rb_funnel_http_run_requests(self C.VALUE, rbAry C.VALUE) C.VALUE {
|
|
26
26
|
Method: getRbHashValueAsString(rbHash, "method"),
|
27
27
|
URL: getRbHashValueAsString(rbHash, "url"),
|
28
28
|
Header: getRbHashValueAsMap(rbHash, "header"),
|
29
|
+
Body: getRbHashValueAsBytes(rbHash, "body"),
|
29
30
|
}
|
30
31
|
requests = append(requests, req)
|
31
32
|
}
|
@@ -111,6 +112,22 @@ func getRbHashValueAsString(rbHash ruby.VALUE, key string) string {
|
|
111
112
|
return ruby.Value2String(value)
|
112
113
|
}
|
113
114
|
|
115
|
+
func getRbHashValueAsBytes(rbHash ruby.VALUE, key string) []byte {
|
116
|
+
value := ruby.RbHashAref(rbHash, ruby.RbToSymbol(ruby.String2Value(key)))
|
117
|
+
|
118
|
+
if value == ruby.Qnil() {
|
119
|
+
return []byte{}
|
120
|
+
}
|
121
|
+
|
122
|
+
length := ruby.RSTRING_LENINT(value)
|
123
|
+
if length == 0 {
|
124
|
+
return []byte{}
|
125
|
+
}
|
126
|
+
|
127
|
+
char := ruby.RSTRING_PTR(value)
|
128
|
+
return C.GoBytes(unsafe.Pointer(char), C.int(length))
|
129
|
+
}
|
130
|
+
|
114
131
|
func getRbHashValueAsMap(rbHash ruby.VALUE, key string) map[string][]string {
|
115
132
|
rbHashValue := ruby.RbHashAref(rbHash, ruby.RbToSymbol(ruby.String2Value(key)))
|
116
133
|
rbKeys := ruby.CallFunction(rbHashValue, "keys")
|
data/ext/funnel_http/go.mod
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
module github.com/sue445/funnel_http
|
2
2
|
|
3
|
-
go 1.23
|
3
|
+
go 1.23.0
|
4
|
+
|
5
|
+
toolchain go1.24.0
|
4
6
|
|
5
7
|
require (
|
6
8
|
github.com/cockroachdb/errors v1.11.3
|
7
9
|
github.com/jarcoal/httpmock v1.3.1
|
8
|
-
github.com/ruby-go-gem/go-gem-wrapper v0.
|
10
|
+
github.com/ruby-go-gem/go-gem-wrapper v0.7.2
|
9
11
|
github.com/stretchr/testify v1.10.0
|
10
|
-
golang.org/x/sync v0.
|
12
|
+
golang.org/x/sync v0.12.0
|
11
13
|
)
|
12
14
|
|
13
15
|
require (
|
data/ext/funnel_http/go.sum
CHANGED
@@ -34,10 +34,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|
34
34
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
35
35
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
36
36
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
37
|
-
github.com/ruby-go-gem/go-gem-wrapper v0.
|
38
|
-
github.com/ruby-go-gem/go-gem-wrapper v0.
|
39
|
-
github.com/ruby-go-gem/go-gem-wrapper v0.6.0 h1:WFu2Cj/uzKAOemsrCo4P6vsdOgB5yesrrJtAqvLkAso=
|
40
|
-
github.com/ruby-go-gem/go-gem-wrapper v0.6.0/go.mod h1:k2k+LziSCMxNYP4J9/9v90xdU6zlU1DJpJDTU6oJhHE=
|
37
|
+
github.com/ruby-go-gem/go-gem-wrapper v0.7.2 h1:Hf7bA5TD/UjJTccTwsbBJWnjpBvcQWAzX50tv9++4+o=
|
38
|
+
github.com/ruby-go-gem/go-gem-wrapper v0.7.2/go.mod h1:k2k+LziSCMxNYP4J9/9v90xdU6zlU1DJpJDTU6oJhHE=
|
41
39
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
42
40
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
43
41
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
@@ -54,8 +52,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|
54
52
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
55
53
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
56
54
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
57
|
-
golang.org/x/sync v0.
|
58
|
-
golang.org/x/sync v0.
|
55
|
+
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
56
|
+
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
59
57
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
60
58
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
61
59
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
@@ -13,6 +13,7 @@ type Request struct {
|
|
13
13
|
Method string
|
14
14
|
URL string
|
15
15
|
Header map[string][]string
|
16
|
+
Body []byte
|
16
17
|
}
|
17
18
|
|
18
19
|
// Response is proxy between CRuby and Go
|
@@ -33,8 +34,7 @@ func RunRequests(httpClient *http.Client, requests []Request) ([]Response, error
|
|
33
34
|
request := request
|
34
35
|
|
35
36
|
g.Go(func() error {
|
36
|
-
|
37
|
-
httpReq, err := http.NewRequest(request.Method, request.URL, bytes.NewBuffer(body))
|
37
|
+
httpReq, err := http.NewRequest(request.Method, request.URL, bytes.NewBuffer(request.Body))
|
38
38
|
if err != nil {
|
39
39
|
return errors.WithStack(err)
|
40
40
|
}
|
data/lib/funnel_http/client.rb
CHANGED
@@ -27,12 +27,14 @@ module FunnelHttp
|
|
27
27
|
# @option requests :method [String, Symbol] **[required]** Request method (e.g. `:get`, `"POST"`)
|
28
28
|
# @option requests :url [String] **[required]** Request url
|
29
29
|
# @option requests :header [Hash{String => String, Array<String>}, nil] Request header
|
30
|
+
# @option requests :body [String, nil] Request body
|
30
31
|
#
|
31
32
|
# @overload perform(request)
|
32
33
|
# @param request [Hash{Symbol => Object}]
|
33
34
|
# @option request :method [String, Symbol] **[required]** Request method (e.g. `:get`, `"POST"`)
|
34
35
|
# @option request :url [String] **[required]** Request url
|
35
36
|
# @option request :header [Hash{String => String, Array<String>}, nil] Request header
|
37
|
+
# @option request :body [String, nil] Request body
|
36
38
|
#
|
37
39
|
# @return [Array<Hash<Symbol => Object>>] `Array` of following `Hash`
|
38
40
|
# @return [Integer] `:status_code`
|
@@ -78,6 +80,7 @@ module FunnelHttp
|
|
78
80
|
url: request[:url].to_s,
|
79
81
|
method: request[:method].to_s.upcase,
|
80
82
|
header: normalize_header(request[:header]),
|
83
|
+
body: request[:body].freeze,
|
81
84
|
}
|
82
85
|
end
|
83
86
|
end
|
data/lib/funnel_http/version.rb
CHANGED
data/rbs_collection.lock.yaml
CHANGED
@@ -2,9 +2,13 @@
|
|
2
2
|
path: ".gem_rbs_collection"
|
3
3
|
gems:
|
4
4
|
- name: base64
|
5
|
-
version: '0'
|
5
|
+
version: '0.1'
|
6
6
|
source:
|
7
|
-
type:
|
7
|
+
type: git
|
8
|
+
name: ruby/gem_rbs_collection
|
9
|
+
revision: 7c22ddc3de54df89ebb2546c9dcb1c1498c8154a
|
10
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
11
|
+
repo_dir: gems
|
8
12
|
- name: cgi
|
9
13
|
version: '0'
|
10
14
|
source:
|
@@ -14,7 +18,7 @@ gems:
|
|
14
18
|
source:
|
15
19
|
type: git
|
16
20
|
name: ruby/gem_rbs_collection
|
17
|
-
revision:
|
21
|
+
revision: 7c22ddc3de54df89ebb2546c9dcb1c1498c8154a
|
18
22
|
remote: https://github.com/ruby/gem_rbs_collection.git
|
19
23
|
repo_dir: gems
|
20
24
|
- name: fileutils
|
@@ -34,7 +38,7 @@ gems:
|
|
34
38
|
source:
|
35
39
|
type: git
|
36
40
|
name: ruby/gem_rbs_collection
|
37
|
-
revision:
|
41
|
+
revision: 7c22ddc3de54df89ebb2546c9dcb1c1498c8154a
|
38
42
|
remote: https://github.com/ruby/gem_rbs_collection.git
|
39
43
|
repo_dir: gems
|
40
44
|
- name: rack
|
@@ -42,7 +46,7 @@ gems:
|
|
42
46
|
source:
|
43
47
|
type: git
|
44
48
|
name: ruby/gem_rbs_collection
|
45
|
-
revision:
|
49
|
+
revision: 7c22ddc3de54df89ebb2546c9dcb1c1498c8154a
|
46
50
|
remote: https://github.com/ruby/gem_rbs_collection.git
|
47
51
|
repo_dir: gems
|
48
52
|
- name: rake
|
@@ -50,7 +54,7 @@ gems:
|
|
50
54
|
source:
|
51
55
|
type: git
|
52
56
|
name: ruby/gem_rbs_collection
|
53
|
-
revision:
|
57
|
+
revision: 7c22ddc3de54df89ebb2546c9dcb1c1498c8154a
|
54
58
|
remote: https://github.com/ruby/gem_rbs_collection.git
|
55
59
|
repo_dir: gems
|
56
60
|
- name: sinatra
|
@@ -58,7 +62,7 @@ gems:
|
|
58
62
|
source:
|
59
63
|
type: git
|
60
64
|
name: ruby/gem_rbs_collection
|
61
|
-
revision:
|
65
|
+
revision: 7c22ddc3de54df89ebb2546c9dcb1c1498c8154a
|
62
66
|
remote: https://github.com/ruby/gem_rbs_collection.git
|
63
67
|
repo_dir: gems
|
64
68
|
- name: stringio
|
data/sig/funnel_http.rbs
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: funnel_http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sue445
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-12 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: go_gem
|
@@ -191,7 +191,7 @@ dependencies:
|
|
191
191
|
- - ">="
|
192
192
|
- !ruby/object:Gem::Version
|
193
193
|
version: '0'
|
194
|
-
description: Perform HTTP requests in parallel
|
194
|
+
description: Perform HTTP requests in parallel with goroutine
|
195
195
|
email:
|
196
196
|
- sue445@sue445.net
|
197
197
|
executables: []
|
@@ -207,11 +207,6 @@ files:
|
|
207
207
|
- README.md
|
208
208
|
- Rakefile
|
209
209
|
- Steepfile
|
210
|
-
- benchmark/README.md
|
211
|
-
- benchmark/benchmark.rb
|
212
|
-
- benchmark/compose.yml
|
213
|
-
- benchmark/html/index.html
|
214
|
-
- benchmark/nginx.conf
|
215
210
|
- ext/funnel_http/extconf.rb
|
216
211
|
- ext/funnel_http/funnel_http.c
|
217
212
|
- ext/funnel_http/funnel_http.go
|
@@ -219,7 +214,6 @@ files:
|
|
219
214
|
- ext/funnel_http/go.mod
|
220
215
|
- ext/funnel_http/go.sum
|
221
216
|
- ext/funnel_http/run_requests.go
|
222
|
-
- ext/funnel_http/run_requests_test.go
|
223
217
|
- lib/funnel_http.rb
|
224
218
|
- lib/funnel_http/client.rb
|
225
219
|
- lib/funnel_http/ext.rb
|
@@ -254,5 +248,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
248
|
requirements: []
|
255
249
|
rubygems_version: 3.6.2
|
256
250
|
specification_version: 4
|
257
|
-
summary: Perform HTTP requests in parallel
|
251
|
+
summary: Perform HTTP requests in parallel with goroutine
|
258
252
|
test_files: []
|
data/benchmark/README.md
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# benchmark for funnel_http
|
2
|
-
## Usage
|
3
|
-
```bash
|
4
|
-
docker compose up --build
|
5
|
-
```
|
6
|
-
|
7
|
-
```bash
|
8
|
-
bundle exec ruby benchmark.rb
|
9
|
-
```
|
10
|
-
|
11
|
-
## Report
|
12
|
-
```
|
13
|
-
Warming up --------------------------------------
|
14
|
-
FunnelHttp::Client#perform
|
15
|
-
2.000 i/100ms
|
16
|
-
Parallel with 4 processes
|
17
|
-
1.000 i/100ms
|
18
|
-
Parallel with 4 threads
|
19
|
-
1.000 i/100ms
|
20
|
-
Calculating -------------------------------------
|
21
|
-
FunnelHttp::Client#perform
|
22
|
-
21.816 (± 4.6%) i/s (45.84 ms/i) - 44.000 in 2.026960s
|
23
|
-
Parallel with 4 processes
|
24
|
-
15.785 (± 6.3%) i/s (63.35 ms/i) - 32.000 in 2.035628s
|
25
|
-
Parallel with 4 threads
|
26
|
-
18.570 (±10.8%) i/s (53.85 ms/i) - 37.000 in 2.008485s
|
27
|
-
|
28
|
-
Comparison:
|
29
|
-
FunnelHttp::Client#perform: 21.8 i/s
|
30
|
-
Parallel with 4 threads: 18.6 i/s - 1.17x slower
|
31
|
-
Parallel with 4 processes: 15.8 i/s - 1.38x slower
|
32
|
-
```
|
data/benchmark/benchmark.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require "benchmark/ips"
|
2
|
-
require "open-uri"
|
3
|
-
require "parallel"
|
4
|
-
require "etc"
|
5
|
-
|
6
|
-
ROOT_DIR = File.expand_path("..", __dir__)
|
7
|
-
|
8
|
-
TEST_SERVER_URL = ENV.fetch("TEST_SERVER_URL") { "http://localhost:8080/" }
|
9
|
-
|
10
|
-
REQUEST_COUNT = 100
|
11
|
-
|
12
|
-
BENCHMARK_CONCURRENCY = (ENV.fetch("BENCHMARK_CONCURRENCY") { 4 }).to_i
|
13
|
-
|
14
|
-
# Build native extension before running benchmark
|
15
|
-
Dir.chdir(ROOT_DIR) do
|
16
|
-
system("bundle config set --local path 'vendor/bundle'", exception: true)
|
17
|
-
system("bundle install", exception: true)
|
18
|
-
system("bundle exec rake clobber compile", exception: true)
|
19
|
-
end
|
20
|
-
|
21
|
-
require_relative "../lib/funnel_http"
|
22
|
-
|
23
|
-
# Suppress Ractor warning
|
24
|
-
$VERBOSE = nil
|
25
|
-
|
26
|
-
system("go version", exception: true)
|
27
|
-
|
28
|
-
requests = Array.new(REQUEST_COUNT, { method: :get, url: TEST_SERVER_URL })
|
29
|
-
|
30
|
-
def fetch_server
|
31
|
-
URI.parse(TEST_SERVER_URL).open(open_timeout: 90, read_timeout: 90).read
|
32
|
-
end
|
33
|
-
|
34
|
-
Benchmark.ips do |x|
|
35
|
-
# x.config(warmup: 1, time: 2)
|
36
|
-
|
37
|
-
x.report("FunnelHttp::Client#perform") do
|
38
|
-
FunnelHttp::Client.new.perform(requests)
|
39
|
-
end
|
40
|
-
|
41
|
-
x.report("Parallel with #{BENCHMARK_CONCURRENCY} processes") do
|
42
|
-
Parallel.each(requests, in_processes: BENCHMARK_CONCURRENCY) do
|
43
|
-
fetch_server
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
x.report("Parallel with #{BENCHMARK_CONCURRENCY} threads") do
|
48
|
-
Parallel.each(requests, in_threads: BENCHMARK_CONCURRENCY) do
|
49
|
-
fetch_server
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# FIXME: open-uri doesn't work in Ractor
|
54
|
-
# x.report("Parallel with Ractor") do
|
55
|
-
# REQUEST_COUNT.times.map do
|
56
|
-
# Ractor.new { URI.parse("http://localhost:8080/").read }
|
57
|
-
# end.each(&:take)
|
58
|
-
# end
|
59
|
-
|
60
|
-
x.compare!
|
61
|
-
end
|
data/benchmark/compose.yml
DELETED
data/benchmark/html/index.html
DELETED
data/benchmark/nginx.conf
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
worker_processes auto;
|
2
|
-
worker_rlimit_nofile 12288;
|
3
|
-
|
4
|
-
events {
|
5
|
-
worker_connections 4096;
|
6
|
-
}
|
7
|
-
|
8
|
-
http {
|
9
|
-
include mime.types;
|
10
|
-
default_type application/octet-stream;
|
11
|
-
|
12
|
-
sendfile on;
|
13
|
-
keepalive_timeout 65;
|
14
|
-
access_log off;
|
15
|
-
|
16
|
-
server {
|
17
|
-
listen 80;
|
18
|
-
server_name localhost;
|
19
|
-
|
20
|
-
location / {
|
21
|
-
root /usr/share/nginx/html;
|
22
|
-
index index.html;
|
23
|
-
}
|
24
|
-
}
|
25
|
-
}
|
@@ -1,120 +0,0 @@
|
|
1
|
-
package main_test
|
2
|
-
|
3
|
-
import (
|
4
|
-
"github.com/jarcoal/httpmock"
|
5
|
-
"github.com/stretchr/testify/assert"
|
6
|
-
"github.com/sue445/funnel_http"
|
7
|
-
"net/http"
|
8
|
-
"testing"
|
9
|
-
)
|
10
|
-
|
11
|
-
func TestRunRequests(t *testing.T) {
|
12
|
-
httpmock.Activate()
|
13
|
-
t.Cleanup(httpmock.DeactivateAndReset)
|
14
|
-
|
15
|
-
httpmock.RegisterResponder("GET", "http://example.com/1",
|
16
|
-
func(req *http.Request) (*http.Response, error) {
|
17
|
-
resp := httpmock.NewStringResponse(200, "GET http://example.com/1")
|
18
|
-
|
19
|
-
resp.Header.Set("Content-Type", "text/plain")
|
20
|
-
|
21
|
-
for key, values := range req.Header {
|
22
|
-
for _, value := range values {
|
23
|
-
resp.Header.Add(key, value)
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
|
-
return resp, nil
|
28
|
-
})
|
29
|
-
|
30
|
-
httpmock.RegisterResponder("GET", "http://example.com/2",
|
31
|
-
func(req *http.Request) (*http.Response, error) {
|
32
|
-
resp := httpmock.NewStringResponse(200, "GET http://example.com/2")
|
33
|
-
|
34
|
-
resp.Header.Set("Content-Type", "text/plain")
|
35
|
-
|
36
|
-
for key, values := range req.Header {
|
37
|
-
for _, value := range values {
|
38
|
-
resp.Header.Add(key, value)
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
|
-
return resp, nil
|
43
|
-
})
|
44
|
-
|
45
|
-
tests := []struct {
|
46
|
-
name string
|
47
|
-
requests []main.Request
|
48
|
-
expected []main.Response
|
49
|
-
}{
|
50
|
-
{
|
51
|
-
name: "1 request",
|
52
|
-
requests: []main.Request{
|
53
|
-
{
|
54
|
-
Method: "GET",
|
55
|
-
URL: "http://example.com/1",
|
56
|
-
Header: map[string][]string{
|
57
|
-
"X-My-Request-Header": {"a", "b"},
|
58
|
-
},
|
59
|
-
},
|
60
|
-
},
|
61
|
-
expected: []main.Response{
|
62
|
-
{
|
63
|
-
StatusCode: 200,
|
64
|
-
Body: []byte("GET http://example.com/1"),
|
65
|
-
Header: map[string][]string{
|
66
|
-
"Content-Type": {"text/plain"},
|
67
|
-
"X-My-Request-Header": {"a", "b"},
|
68
|
-
},
|
69
|
-
},
|
70
|
-
},
|
71
|
-
},
|
72
|
-
{
|
73
|
-
name: "multiple requests",
|
74
|
-
requests: []main.Request{
|
75
|
-
{
|
76
|
-
Method: "GET",
|
77
|
-
URL: "http://example.com/1",
|
78
|
-
Header: map[string][]string{
|
79
|
-
"X-My-Request-Header": {"a", "b"},
|
80
|
-
},
|
81
|
-
},
|
82
|
-
{
|
83
|
-
Method: "GET",
|
84
|
-
URL: "http://example.com/2",
|
85
|
-
Header: map[string][]string{
|
86
|
-
"X-My-Request-Header": {"c", "d"},
|
87
|
-
},
|
88
|
-
},
|
89
|
-
},
|
90
|
-
expected: []main.Response{
|
91
|
-
{
|
92
|
-
StatusCode: 200,
|
93
|
-
Body: []byte("GET http://example.com/1"),
|
94
|
-
Header: map[string][]string{
|
95
|
-
"Content-Type": {"text/plain"},
|
96
|
-
"X-My-Request-Header": {"a", "b"},
|
97
|
-
},
|
98
|
-
},
|
99
|
-
{
|
100
|
-
StatusCode: 200,
|
101
|
-
Body: []byte("GET http://example.com/2"),
|
102
|
-
Header: map[string][]string{
|
103
|
-
"Content-Type": {"text/plain"},
|
104
|
-
"X-My-Request-Header": {"c", "d"},
|
105
|
-
},
|
106
|
-
},
|
107
|
-
},
|
108
|
-
},
|
109
|
-
}
|
110
|
-
|
111
|
-
httpClient := http.Client{}
|
112
|
-
for _, tt := range tests {
|
113
|
-
t.Run(tt.name, func(t *testing.T) {
|
114
|
-
actual, err := main.RunRequests(&httpClient, tt.requests)
|
115
|
-
if assert.NoError(t, err) {
|
116
|
-
assert.Equal(t, tt.expected, actual)
|
117
|
-
}
|
118
|
-
})
|
119
|
-
}
|
120
|
-
}
|