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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 917e92197eb60a1304f9caf430bb6c29c71d02d79a2b2c5b3cec0b59d98d53fe
4
- data.tar.gz: 64494899740408ee2d7fc2d8809cdacbdc845567f0e60a5d0534996e673cfd59
3
+ metadata.gz: 73d4d621364f2ead38d1d11300cbe8e31f99eb61e99cb2b240eb3dd5a9e1f805
4
+ data.tar.gz: 373baa9881da4b0169caa9877f4ad438ec0bebb2a0570a890c9d579d9e4e65ba
5
5
  SHA512:
6
- metadata.gz: b320f647b1facbdaccf131c42b1f5e6afaa9fe8dd9aa3edd543a171a1fa94771d7bf3f273fd733305026c27e538f86ce75ce579255b46492be1278c6998423f5
7
- data.tar.gz: 3e340043d664bace37a2f415b0248bdd1aa31a345dcf1ccf290276b96e1c058f11fd9cb7c1158d41783ccf4c2a9fd663030e1bc6b32eea2b1ae1080260ec9830
6
+ metadata.gz: 46fb6d63bf16d3e98b836446dae58306c652bc9abeba0f91090abec890f6d7e0de6c3e2cca7ef6977c59e8a3a8a1fee13ca4a4f76a3a999c371e1537b4cb3b43
7
+ data.tar.gz: 18f813f4b4333bf9da00f37add3f270c297b3a6a16ab7d980bfd1345c75a9069b44a69686c9ff849850f5cc92a8035585d8044ef2893a51e114cc34f137d7323
data/.travis.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.3.0
4
+ - 2.4.2
5
+ - 2.5.1
4
6
  before_install: gem install bundler -v 1.11.2
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Speedtest
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.0"
3
3
  end
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
- @download_runs = options[:download_runs] || 4
13
- @upload_runs = options[:upload_runs] || 4
14
- @ping_runs = options[:ping_runs] || 4
15
- @download_sizes = options[:download_sizes] || [750, 1500]
16
- @upload_sizes = options[:upload_sizes] || [197190, 483960]
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
- threads = []
71
-
72
- start_time = Time.new
73
- @download_sizes.each { |size|
74
- 1.upto(@download_runs) { |i|
75
- threads << Thread.new { |thread|
76
- downloadthread("#{@server_root}/speedtest/random#{size}x#{size}.jpg")
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
- threads.each { |t|
83
- t.join
84
- total_downloaded += t["downloaded"]
85
- raise FailedTransfer.new("Download failed.") if t["error"] == true
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 #{threads.length} threads\n"
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
- threads = []
118
- start_time = Time.new
119
- threads = data.map { |data|
120
- Thread.new(data) { |content|
121
- log " uploading size #{content.size}: #{@server_root}/speedtest/upload.php"
122
- uploadthread("#{@server_root}/speedtest/upload.php", content)
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
- threads.each { |t|
128
- t.join
129
- total_uploaded += t["uploaded"]
130
- raise FailedTransfer.new("Upload failed.") if t["error"] == true
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 #{threads.length} threads\n"
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.2.3
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-11 00:00:00.000000000 Z
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