plr-speedtest 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/lib/speedtest/download_worker.rb +26 -0
- data/lib/speedtest/ring.rb +55 -0
- data/lib/speedtest/upload_worker.rb +25 -0
- data/lib/speedtest/version.rb +1 -1
- data/lib/speedtest.rb +58 -62
- data/speedtest.gemspec +2 -0
- metadata +33 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73d4d621364f2ead38d1d11300cbe8e31f99eb61e99cb2b240eb3dd5a9e1f805
|
4
|
+
data.tar.gz: 373baa9881da4b0169caa9877f4ad438ec0bebb2a0570a890c9d579d9e4e65ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46fb6d63bf16d3e98b836446dae58306c652bc9abeba0f91090abec890f6d7e0de6c3e2cca7ef6977c59e8a3a8a1fee13ca4a4f76a3a999c371e1537b4cb3b43
|
7
|
+
data.tar.gz: 18f813f4b4333bf9da00f37add3f270c297b3a6a16ab7d980bfd1345c75a9069b44a69686c9ff849850f5cc92a8035585d8044ef2893a51e114cc34f137d7323
|
data/.travis.yml
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'celluloid/current'
|
2
|
+
|
3
|
+
module Speedtest
|
4
|
+
|
5
|
+
class DownloadWorker
|
6
|
+
include Celluloid
|
7
|
+
|
8
|
+
def initialize(url, logger)
|
9
|
+
@logger = logger
|
10
|
+
@url = url
|
11
|
+
end
|
12
|
+
|
13
|
+
def download
|
14
|
+
@logger.debug " downloading: #{@url}"
|
15
|
+
status = ThreadStatus.new(false, 0)
|
16
|
+
|
17
|
+
page = HTTParty.get(@url, timeout: 10)
|
18
|
+
unless page.code / 100 == 2
|
19
|
+
error "GET #{url} failed with code #{page.code}"
|
20
|
+
status.error = true
|
21
|
+
end
|
22
|
+
status.size = page.body.length
|
23
|
+
status
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Speedtest
|
2
|
+
class FullRing < StandardError; end
|
3
|
+
|
4
|
+
class Ring
|
5
|
+
def initialize(size)
|
6
|
+
raise ArgumentError, 'size cannot be 0' if size == 0
|
7
|
+
|
8
|
+
@size = size
|
9
|
+
@arr = Array.new(size)
|
10
|
+
@num_free = @size
|
11
|
+
|
12
|
+
@append_pos = 0
|
13
|
+
@pop_pos = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def append(elt)
|
17
|
+
raise FullRing unless num_free > 0
|
18
|
+
|
19
|
+
@arr[append_pos] = elt
|
20
|
+
|
21
|
+
@num_free -= 1
|
22
|
+
@append_pos += 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def pop
|
26
|
+
return nil unless num_busy > 0
|
27
|
+
|
28
|
+
value = @arr[pop_pos]
|
29
|
+
@arr[pop_pos] = nil
|
30
|
+
|
31
|
+
@num_free += 1
|
32
|
+
@pop_pos += 1
|
33
|
+
|
34
|
+
return value
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def append_pos
|
40
|
+
@append_pos % @size
|
41
|
+
end
|
42
|
+
|
43
|
+
def pop_pos
|
44
|
+
@pop_pos % @size
|
45
|
+
end
|
46
|
+
|
47
|
+
def num_free
|
48
|
+
@num_free
|
49
|
+
end
|
50
|
+
|
51
|
+
def num_busy
|
52
|
+
@size - @num_free
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'celluloid/current'
|
2
|
+
|
3
|
+
module Speedtest
|
4
|
+
class UploadWorker
|
5
|
+
include Celluloid
|
6
|
+
|
7
|
+
def initialize(url, logger)
|
8
|
+
@url = url
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def upload(content)
|
13
|
+
status = ThreadStatus.new(false, 0)
|
14
|
+
|
15
|
+
page = HTTParty.post(@url, :body => { "content" => content }, timeout: 10)
|
16
|
+
@logger.debug "upload response body = [#{page.body}]"
|
17
|
+
unless page.code / 100 == 2
|
18
|
+
error "GET #{url} failed with code #{page.code}"
|
19
|
+
status.error = true
|
20
|
+
end
|
21
|
+
status.size = page.body.split('=')[1].to_i
|
22
|
+
status
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/speedtest/version.rb
CHANGED
data/lib/speedtest.rb
CHANGED
@@ -2,19 +2,32 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
require_relative 'speedtest/result'
|
4
4
|
require_relative 'speedtest/geo_point'
|
5
|
+
require_relative 'speedtest/download_worker'
|
6
|
+
require_relative 'speedtest/upload_worker'
|
7
|
+
require_relative 'speedtest/ring'
|
5
8
|
|
6
9
|
module Speedtest
|
10
|
+
ThreadStatus = Struct.new(:error, :size)
|
11
|
+
|
7
12
|
class Test
|
8
13
|
|
9
14
|
class FailedTransfer < StandardError; end
|
10
15
|
|
16
|
+
HTTP_PING_TIMEOUT = 5
|
17
|
+
|
11
18
|
def initialize(options = {})
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@ping_runs = options[:ping_runs]
|
15
|
-
@
|
16
|
-
@
|
19
|
+
@min_transfer_secs = options[:min_transfer_secs] || 10
|
20
|
+
@num_threads = options[:num_threads] || 4
|
21
|
+
@ping_runs = options[:ping_runs] || 4
|
22
|
+
@download_size = options[:download_size] || 4000
|
23
|
+
@upload_size = options[:upload_size] || 1_000_000
|
17
24
|
@logger = options[:logger]
|
25
|
+
@num_transfers_padding = options[:num_transfers_padding] || 5
|
26
|
+
|
27
|
+
if @num_transfers_padding > @num_threads
|
28
|
+
@num_transfers_padding = @num_threads
|
29
|
+
end
|
30
|
+
@ping_runs = 2 if @ping_runs < 2
|
18
31
|
end
|
19
32
|
|
20
33
|
def run()
|
@@ -55,51 +68,34 @@ module Speedtest
|
|
55
68
|
@logger.error msg if @logger
|
56
69
|
end
|
57
70
|
|
58
|
-
def downloadthread(url)
|
59
|
-
log " downloading: #{url}"
|
60
|
-
page = HTTParty.get(url)
|
61
|
-
unless page.code / 100 == 2
|
62
|
-
error "GET #{url} failed with code #{page.code}"
|
63
|
-
Thread.current["error"] = true
|
64
|
-
end
|
65
|
-
Thread.current["downloaded"] = page.body.length
|
66
|
-
end
|
67
|
-
|
68
71
|
def download
|
69
72
|
log "\nstarting download tests:"
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
@
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
}
|
79
|
-
}
|
73
|
+
|
74
|
+
start_time = Time.now
|
75
|
+
futures_ring = Ring.new(@num_threads + @num_transfers_padding)
|
76
|
+
download_url = "#{@server_root}/speedtest/random#{@download_size}x#{@download_size}.jpg"
|
77
|
+
pool = DownloadWorker.pool(size: @num_threads, args: [download_url, @logger])
|
78
|
+
1.upto(@num_threads + @num_transfers_padding).each do |i|
|
79
|
+
futures_ring.append(pool.future.download)
|
80
|
+
end
|
80
81
|
|
81
82
|
total_downloaded = 0
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
while (future = futures_ring.pop) do
|
84
|
+
status = future.value
|
85
|
+
raise FailedTransfer.new("Download failed.") if status.error == true
|
86
|
+
total_downloaded += status.size
|
87
|
+
|
88
|
+
if Time.now - start_time < @min_transfer_secs
|
89
|
+
futures_ring.append(pool.future.download)
|
90
|
+
end
|
91
|
+
end
|
87
92
|
|
88
93
|
total_time = Time.new - start_time
|
89
|
-
log "Took #{total_time} seconds to download #{total_downloaded} bytes in #{
|
94
|
+
log "Took #{total_time} seconds to download #{total_downloaded} bytes in #{@num_threads} threads\n"
|
90
95
|
|
91
96
|
[ total_downloaded * 8, total_time ]
|
92
97
|
end
|
93
98
|
|
94
|
-
def uploadthread(url, content)
|
95
|
-
page = HTTParty.post(url, :body => { "content" => content })
|
96
|
-
unless page.code / 100 == 2
|
97
|
-
error "GET #{url} failed with code #{page.code}"
|
98
|
-
Thread.current["error"] = true
|
99
|
-
end
|
100
|
-
Thread.current["uploaded"] = page.body.split('=')[1].to_i
|
101
|
-
end
|
102
|
-
|
103
99
|
def randomString(alphabet, size)
|
104
100
|
(1.upto(size)).map { alphabet[rand(alphabet.length)] }.join
|
105
101
|
end
|
@@ -107,30 +103,30 @@ module Speedtest
|
|
107
103
|
def upload
|
108
104
|
log "\nstarting upload tests:"
|
109
105
|
|
110
|
-
data =
|
111
|
-
@upload_sizes.each { |size|
|
112
|
-
1.upto(@upload_runs) {
|
113
|
-
data << randomString(('A'..'Z').to_a, size)
|
114
|
-
}
|
115
|
-
}
|
106
|
+
data = randomString(('A'..'Z').to_a, @upload_size)
|
116
107
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
108
|
+
start_time = Time.now
|
109
|
+
|
110
|
+
futures_ring = Ring.new(@num_threads + @num_transfers_padding)
|
111
|
+
upload_url = "#{@server_root}/speedtest/upload.php"
|
112
|
+
pool = UploadWorker.pool(size: @num_threads, args: [upload_url, @logger])
|
113
|
+
1.upto(@num_threads + @num_transfers_padding).each do |i|
|
114
|
+
futures_ring.append(pool.future.upload(data))
|
115
|
+
end
|
125
116
|
|
126
117
|
total_uploaded = 0
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
118
|
+
while (future = futures_ring.pop) do
|
119
|
+
status = future.value
|
120
|
+
raise FailedTransfer.new("Upload failed.") if status.error == true
|
121
|
+
total_uploaded += status.size
|
122
|
+
|
123
|
+
if Time.now - start_time < @min_transfer_secs
|
124
|
+
futures_ring.append(pool.future.upload(data))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
132
128
|
total_time = Time.new - start_time
|
133
|
-
log "Took #{total_time} seconds to upload #{total_uploaded} bytes in #{
|
129
|
+
log "Took #{total_time} seconds to upload #{total_uploaded} bytes in #{@num_threads} threads\n"
|
134
130
|
|
135
131
|
# bytes to bits / time = bps
|
136
132
|
[ total_uploaded * 8, total_time ]
|
@@ -167,10 +163,10 @@ module Speedtest
|
|
167
163
|
1.upto(@ping_runs) {
|
168
164
|
start = Time.new
|
169
165
|
begin
|
170
|
-
page = HTTParty.get("#{server}/speedtest/latency.txt")
|
166
|
+
page = HTTParty.get("#{server}/speedtest/latency.txt", timeout: HTTP_PING_TIMEOUT)
|
171
167
|
times << Time.new - start
|
172
168
|
rescue Timeout::Error, Net::HTTPNotFound, Errno::ENETUNREACH => e
|
173
|
-
log "#{e.class} #{e}"
|
169
|
+
log "ping error: #{e.class} [#{e}] for #{server}"
|
174
170
|
times << 999999
|
175
171
|
end
|
176
172
|
}
|
data/speedtest.gemspec
CHANGED
@@ -20,8 +20,10 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
22
|
spec.add_runtime_dependency "httparty", "~> 0.13"
|
23
|
+
spec.add_runtime_dependency "celluloid", "~> 0.17.3"
|
23
24
|
|
24
25
|
spec.add_development_dependency "bundler", "~> 1.11"
|
25
26
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
27
|
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
spec.add_development_dependency "byebug"
|
27
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plr-speedtest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pete Myron
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-05-
|
12
|
+
date: 2018-05-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
@@ -25,6 +25,20 @@ dependencies:
|
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0.13'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: celluloid
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.17.3
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.17.3
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: bundler
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,6 +81,20 @@ dependencies:
|
|
67
81
|
- - "~>"
|
68
82
|
- !ruby/object:Gem::Version
|
69
83
|
version: '3.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: byebug
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
70
98
|
description: Gemmed version of lacostej's speedtest.rb script @ https://github.com/lacostej/speedtest.rb
|
71
99
|
- Test your speed with speedtest.net!
|
72
100
|
email:
|
@@ -84,8 +112,11 @@ files:
|
|
84
112
|
- README.md
|
85
113
|
- Rakefile
|
86
114
|
- lib/speedtest.rb
|
115
|
+
- lib/speedtest/download_worker.rb
|
87
116
|
- lib/speedtest/geo_point.rb
|
88
117
|
- lib/speedtest/result.rb
|
118
|
+
- lib/speedtest/ring.rb
|
119
|
+
- lib/speedtest/upload_worker.rb
|
89
120
|
- lib/speedtest/version.rb
|
90
121
|
- speedtest.gemspec
|
91
122
|
homepage: https://github.com/petemyron/speedtest
|