amdgpu_fan 0.7.0 → 0.8.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: a499ce52639612b25843b04c3497c7c36f23f3a960d0946b7dc2e249e9a18874
4
- data.tar.gz: fa87ca342988d97a91773b1272829a3b825b88dbd65420d6abd26fed8d97ac92
3
+ metadata.gz: 1fb09354467c6ffeb603c4cbc72b131c626e83d4403148ebeb5fac342222ac29
4
+ data.tar.gz: b62420cbf660f704682f34565128c749216bb5605b3d57b843f4bc85671aa09c
5
5
  SHA512:
6
- metadata.gz: 06b3bd73191b39da57ac9c14e7ada8fa2cf1a069e8401f45af10eab6ede0bf79a5ebd2f80ba5c464e60f960e24d11783cf20d698c640a38e36c80846b305772e
7
- data.tar.gz: 794e28fd6ae71a898b1e897a0fd612add4585e901ece8bc3928e62de9d8245107767848352fe7203d4aa5b6ec60c4e78b28523cc0c893d4d0bcb2f67fdd52044
6
+ metadata.gz: f9a94891e8024c9e2c58c46feb4b7654e69978a9215278d9588065db177e8df447670cad9be726f608f16bd77f4a26e2a05fe16c536ce42bce0c9242489d2b43
7
+ data.tar.gz: 8046858789272ed17ce75304f53ee3915973193bc81bd301335448456c99bd8d4d774962668b2b98388a24301e158d4cffb18a65a28d27c7fd45c130c639740d
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'async'
3
4
  require 'thor'
4
5
 
5
6
  require_relative '../lib/amdgpu_fan'
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/AbcSize, Metrics/ClassLength, Metrics/MethodLength
4
+
3
5
  require 'yaml'
4
6
 
5
7
  module AmdgpuFan
@@ -56,18 +58,19 @@ module AmdgpuFan
56
58
  desc 'status [--logo]', 'View device info, current fan speed, and temperature.'
57
59
  def status(option = nil)
58
60
  puts radeon_logo if option == '--logo'
59
- puts ICONS[:gpu] + ' GPU:'.ljust(9) + amdgpu_service.name,
60
- ICONS[:vbios] + ' vBIOS:'.ljust(9) + amdgpu_service.vbios_version,
61
- ICONS[:display] + ' Displays:' + amdgpu_service.display_names.join(', '),
62
- ICONS[:clock] + ' Clocks:'.ljust(9) + clock_status,
63
- ICONS[:memory] + ' Memory:'.ljust(9) + mem_total_mibibyes,
64
- ICONS[:fan] + ' Fan:'.ljust(9) + fan_status,
65
- ICONS[:temp] + ' Temp:'.ljust(9) + "#{amdgpu_service.temperature}°C",
66
- ICONS[:power] + ' Power:'.ljust(9) + "#{amdgpu_service.profile_mode} profile in " \
67
- "#{amdgpu_service.power_dpm_state} mode using " \
68
- "#{amdgpu_service.power_draw} / #{amdgpu_service.power_max} Watts "\
69
- "(#{amdgpu_service.power_draw_percent}%)",
70
- ICONS[:load] + ' Load:'.ljust(9) + percent_meter(amdgpu_service.busy_percent, 20)
61
+ puts ICONS[:gpu] + ' GPU:'.ljust(9) + amdgpu_service.name
62
+ puts ICONS[:vbios] + ' vBIOS:'.ljust(9) + amdgpu_service.vbios_version
63
+ puts "#{ICONS[:display]} Displays:#{amdgpu_service.display_names.join(', ')}"
64
+ puts ICONS[:clock] + ' Clocks:'.ljust(9) + clock_status
65
+ puts ICONS[:memory] + ' Memory:'.ljust(9) + mem_total_mibibyes
66
+ puts ICONS[:fan] + ' Fan:'.ljust(9) + fan_status
67
+ puts ICONS[:temp] + ' Temp:'.ljust(9) + "#{amdgpu_service.temperature}°C"
68
+ puts ICONS[:power] + ' Power:'.ljust(9) +
69
+ "#{amdgpu_service.profile_mode} profile in " \
70
+ "#{amdgpu_service.power_dpm_state} mode using " \
71
+ "#{amdgpu_service.power_draw} / #{amdgpu_service.power_max} Watts "\
72
+ "(#{amdgpu_service.power_draw_percent}%)"
73
+ puts ICONS[:load] + ' Load:'.ljust(9) + percent_meter(amdgpu_service.busy_percent)
71
74
  end
72
75
 
73
76
  desc 'version', 'Print the application version.'
@@ -76,7 +79,7 @@ module AmdgpuFan
76
79
  end
77
80
 
78
81
  desc 'watch [SECONDS]', 'Watch fan speed, load, power, and temperature ' \
79
- 'refreshed every n seconds.'
82
+ 'refreshed every n seconds.'
80
83
  def watch(seconds = 1)
81
84
  return puts 'Seconds must be from 1 to 600' unless (1..600).cover?(seconds.to_i)
82
85
 
@@ -120,21 +123,21 @@ module AmdgpuFan
120
123
  watcher.measure
121
124
  5.times { print "\033[K\033[A" } # move up a line and clear to end of line
122
125
 
123
- puts ICONS[:clock] + ' Core clock ' + watcher.core_clock.to_s,
124
- ICONS[:memory] + ' Memory clk ' + watcher.mem_clock.to_s,
125
- ICONS[:fan] + ' Fan speed ' + watcher.fan_speed.to_s,
126
- ICONS[:power] + ' Power usage ' + watcher.power.to_s,
127
- ICONS[:temp] + ' Temperature ' + watcher.temp.to_s
126
+ puts "#{ICONS[:clock]} Core clock #{watcher.core_clock}",
127
+ "#{ICONS[:memory]} Memory clk #{watcher.memory_clock}",
128
+ "#{ICONS[:fan]} Fan speed #{watcher.fan_speed_rpm}",
129
+ "#{ICONS[:power]} Power usage #{watcher.power_draw}",
130
+ "#{ICONS[:temp]} Temperature #{watcher.temperature}"
128
131
  sleep 1
129
132
  end
130
133
  end
131
134
 
132
135
  desc 'watch_csv [SECONDS]', 'Watch stats in CSV format ' \
133
- 'refreshed every n seconds defaulting to 1 second.'
136
+ 'refreshed every n seconds defaulting to 1 second.'
134
137
  def watch_csv(seconds = 1)
135
138
  return puts 'Seconds must be from 1 to 600' unless (1..600).cover?(seconds.to_i)
136
139
 
137
- puts 'Timestamp, Core Clock (Mhz),Memory Clock (Mhz),Fan speed (rpm), '\
140
+ puts 'Timestamp,Core Clock (Mhz),Memory Clock (Mhz),Fan speed (rpm),'\
138
141
  'Load (%),Power (Watts),Temp (°C)'
139
142
 
140
143
  trap 'SIGINT' do
@@ -142,13 +145,19 @@ module AmdgpuFan
142
145
  end
143
146
 
144
147
  loop do
145
- puts [Time.now.strftime('%F %T'),
146
- amdgpu_service.core_clock,
147
- amdgpu_service.memory_clock,
148
- amdgpu_service.fan_speed_rpm,
149
- amdgpu_service.busy_percent,
150
- amdgpu_service.power_draw,
151
- amdgpu_service.temperature].join(',')
148
+ list = []
149
+ threads = [
150
+ Thread.new { list[0] = amdgpu_service.core_clock },
151
+ Thread.new { list[1] = amdgpu_service.memory_clock },
152
+ Thread.new { list[2] = amdgpu_service.fan_speed_rpm },
153
+ Thread.new { list[3] = amdgpu_service.busy_percent },
154
+ Thread.new { list[4] = amdgpu_service.power_draw },
155
+ Thread.new { list[5] = amdgpu_service.temperature }
156
+ ]
157
+ threads.each(&:join)
158
+
159
+ puts [Time.now.strftime('%F %T'), *list].join(',')
160
+
152
161
  sleep seconds.to_i
153
162
  end
154
163
  end
@@ -165,7 +174,7 @@ module AmdgpuFan
165
174
 
166
175
  def fan_status
167
176
  "#{amdgpu_service.fan_mode} mode running at " \
168
- "#{amdgpu_service.fan_speed_rpm} rpm (#{amdgpu_service.fan_speed_percent}%)"
177
+ "#{amdgpu_service.fan_speed_rpm} rpm (#{amdgpu_service.fan_speed_percent}%)"
169
178
  end
170
179
 
171
180
  def mem_total_mibibyes
@@ -177,8 +186,8 @@ module AmdgpuFan
177
186
  end
178
187
 
179
188
  def summary_clock
180
- "Core: #{amdgpu_service.core_clock.rjust(7)}#{WATCH_FIELD_SEPARATOR}"\
181
- "Memory: #{amdgpu_service.memory_clock.rjust(7)}"
189
+ "Core: #{amdgpu_service.core_clock.to_s.rjust(7)}#{WATCH_FIELD_SEPARATOR}"\
190
+ "Memory: #{amdgpu_service.memory_clock.to_s.rjust(7)}"
182
191
  end
183
192
 
184
193
  def summary_fan
@@ -201,3 +210,5 @@ module AmdgpuFan
201
210
  end
202
211
  end
203
212
  end
213
+
214
+ # rubocop:enable Metrics/AbcSize, Metrics/ClassLength, Metrics/MethodLength
@@ -18,9 +18,9 @@ module AmdgpuFan
18
18
  # Return an array of connector objects for the provided card number.
19
19
  # The files are sorted to improve how they are displayed to the user.
20
20
  def where(card_num:)
21
- Dir["/sys/class/drm/card#{card_num}/card#{card_num}-*"].sort.map do |dir_path|
22
- Connector.new card_num: card_num,
23
- dir_path: dir_path,
21
+ Dir["/sys/class/drm/card#{card_num}/card#{card_num}-*"].map do |dir_path|
22
+ Connector.new card_num:,
23
+ dir_path:,
24
24
  index: dir_path[-1],
25
25
  type: dir_path.slice(/(?<=card#{card_num}-)[A-z]+/)
26
26
  end
@@ -3,19 +3,35 @@
3
3
  module AmdgpuFan
4
4
  # A mixin to help with CLI output formatting
5
5
  module CliOutputFormat
6
- METER_CHAR = '*'
6
+ METER_CHARS = [' ', *("\u2588".."\u258F").to_a.reverse].freeze
7
7
  TIME_FORMAT = '%F %T'
8
8
 
9
- private
10
-
11
9
  def current_time
12
10
  Time.now.strftime(TIME_FORMAT)
13
11
  end
14
12
 
15
- def percent_meter(percent, length = 10)
16
- progress_bar_count = (length * percent.to_f / 100).round
17
- percent_string = "#{format '%<num>0.2i', num: percent}%".ljust(3)
18
- "[#{METER_CHAR * progress_bar_count}#{' ' * (length - progress_bar_count)}]#{percent_string}"
13
+ ##
14
+ # Return a string with meter and percentage for +percent+
15
+ #
16
+ def percent_meter(percent, width = 3)
17
+ meter_char_indexes = []
18
+ percent_portion_size = 100.0 / width
19
+ width.times do |i|
20
+ current_portion = percent.to_i - (percent_portion_size * i)
21
+
22
+ current_portion_percent = if current_portion >= percent_portion_size
23
+ 1
24
+ elsif current_portion <= 0
25
+ 0
26
+ else
27
+ current_portion / percent_portion_size
28
+ end
29
+
30
+ meter_char_indexes << ((METER_CHARS.length - 1) * current_portion_percent.to_f).round
31
+ end
32
+
33
+ percent_string = "#{format '%<num>0.2i', num: percent}%".ljust(4)
34
+ "#{percent_string}[#{meter_char_indexes.map { |i| METER_CHARS[i] }.join}]"
19
35
  end
20
36
 
21
37
  def radeon_logo
@@ -36,7 +36,7 @@ module AmdgpuFan
36
36
  end
37
37
 
38
38
  def valid_fan_percent_speed?(percent)
39
- (1..100.to_i).cover?(percent.to_i)
39
+ (1..(100.to_i)).cover?(percent.to_i)
40
40
  end
41
41
  end
42
42
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
4
+
3
5
  require 'net/http'
4
6
 
5
7
  module AmdgpuFan
@@ -44,8 +46,8 @@ module AmdgpuFan
44
46
  hash[current_vendor_id][:devices][current_device_id] = { name: device_name }
45
47
  elsif line[0..2] =~ /\t\t\w/
46
48
  # Subvendor line
47
- subvendor_id = line.split(' ').first.to_i(16)
48
- subdevice_id = line.split(' ')[1].to_i(16)
49
+ # subvendor_id = line.split(' ').first.to_i(16)
50
+ subdevice_id = line.split[1].to_i(16)
49
51
  subdevice_name = line.split(' ')[1].strip
50
52
  hash[current_vendor_id][:devices][current_device_id][subdevice_id] =
51
53
  { name: subdevice_name }
@@ -60,3 +62,5 @@ module AmdgpuFan
60
62
  end
61
63
  end
62
64
  end
65
+
66
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -31,7 +31,7 @@ module AmdgpuFan
31
31
  end
32
32
 
33
33
  def connectors
34
- @connectors ||= Connector.where card_num: card_num
34
+ @connectors ||= Connector.where card_num:
35
35
  end
36
36
 
37
37
  def core_clock
@@ -78,7 +78,7 @@ module AmdgpuFan
78
78
  # Return the fan speed in revolutions per minute
79
79
  #
80
80
  def fan_speed_rpm
81
- File.read(fan_file(:input)).strip
81
+ File.read(fan_file(:input)).strip.to_i
82
82
  end
83
83
 
84
84
  ##
@@ -159,7 +159,7 @@ module AmdgpuFan
159
159
  end
160
160
 
161
161
  def clock_from_pp_file(file)
162
- File.read(file).slice(/\w+(?= \*)/)
162
+ File.read(file).slice(/\w+(?= \*)/).to_i
163
163
  end
164
164
 
165
165
  def device_id
@@ -7,6 +7,7 @@ module AmdgpuFan
7
7
  attr_reader :unit
8
8
 
9
9
  def initialize(unit)
10
+ super
10
11
  @unit = unit
11
12
  end
12
13
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module AmdgpuFan
4
4
  # Current version of RSpec Core, in semantic versioning format.
5
- VERSION = '0.7.0'
5
+ VERSION = '0.8.0'
6
6
  end
@@ -1,21 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'async'
4
+
3
5
  require_relative 'stat_set'
4
6
 
5
7
  module AmdgpuFan
6
8
  # Keep track of stats over time.
7
9
  class Watcher
8
- attr_reader :core_clock, :fan_speed, :num_measurements, :mem_clock, :power, :temp
10
+ attr_reader :core_clock, :fan_speed_rpm, :num_measurements, :memory_clock, :power_draw,
11
+ :temperature
9
12
 
10
13
  def initialize(amdgpu_service)
11
14
  @amdgpu_service = amdgpu_service
12
15
  @num_measurements = 0
13
16
 
14
17
  @core_clock = StatSet.new 'MHz'
15
- @mem_clock = StatSet.new 'MHz'
16
- @fan_speed = StatSet.new 'RPM'
17
- @power = StatSet.new 'W'
18
- @temp = StatSet.new '°C'
18
+ @memory_clock = StatSet.new 'MHz'
19
+ @fan_speed_rpm = StatSet.new 'RPM'
20
+ @power_draw = StatSet.new 'W'
21
+ @temperature = StatSet.new '°C'
19
22
  end
20
23
 
21
24
  ##
@@ -24,19 +27,20 @@ module AmdgpuFan
24
27
  def measure
25
28
  @num_measurements += 1
26
29
 
27
- @core_clock.now = @amdgpu_service.core_clock.to_i
28
- @mem_clock.now = @amdgpu_service.memory_clock.to_i
29
- @fan_speed.now = @amdgpu_service.fan_speed_rpm.to_i
30
- @power.now = @amdgpu_service.power_draw.to_f
31
- @temp.now = @amdgpu_service.temperature.to_i
32
-
33
- [@core_clock, @mem_clock, @fan_speed, @power, @temp].each do |stat_set|
34
- calculate_stats(stat_set)
30
+ Async do |task|
31
+ %i[core_clock fan_speed_rpm memory_clock power_draw temperature].each do |stat|
32
+ task.async do
33
+ send(stat).now = amdgpu_service.send(stat)
34
+ calculate_stats(send(stat))
35
+ end
36
+ end
35
37
  end
36
38
  end
37
39
 
38
40
  private
39
41
 
42
+ attr_reader :amdgpu_service
43
+
40
44
  def calculate_stats(stat_set)
41
45
  if num_measurements == 1
42
46
  stat_set.min = stat_set.now
@@ -47,7 +51,7 @@ module AmdgpuFan
47
51
 
48
52
  stat_set.min = stat_set.now if stat_set.now < stat_set.min
49
53
  stat_set.avg =
50
- ((stat_set.now + stat_set.avg * (num_measurements - 1)) / num_measurements.to_f)
54
+ ((stat_set.now + (stat_set.avg * (num_measurements - 1))) / num_measurements.to_f)
51
55
  .round(1)
52
56
  stat_set.max = stat_set.now if stat_set.now > stat_set.max
53
57
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amdgpu_fan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin McCormack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-03 00:00:00.000000000 Z
11
+ date: 2022-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: thor
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,34 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.1'
55
97
  description: A CLI for interacting with the amdgpu Linux driver
56
98
  email: harlemsquirrel@gmail.com
57
99
  executables:
@@ -77,7 +119,8 @@ files:
77
119
  homepage: https://github.com/HarlemSquirrel/amdgpu-fan-rb
78
120
  licenses:
79
121
  - MIT
80
- metadata: {}
122
+ metadata:
123
+ rubygems_mfa_required: 'true'
81
124
  post_install_message:
82
125
  rdoc_options: []
83
126
  require_paths:
@@ -86,14 +129,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
129
  requirements:
87
130
  - - ">="
88
131
  - !ruby/object:Gem::Version
89
- version: '0'
132
+ version: 3.1.0
90
133
  required_rubygems_version: !ruby/object:Gem::Requirement
91
134
  requirements:
92
135
  - - ">="
93
136
  - !ruby/object:Gem::Version
94
137
  version: '0'
95
138
  requirements: []
96
- rubygems_version: 3.1.2
139
+ rubygems_version: 3.3.3
97
140
  signing_key:
98
141
  specification_version: 4
99
142
  summary: A CLI to view and set fan speeds for AMD graphics cards running on the open