plr-speedtest 0.2.3 → 0.3.0

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 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