amdgpu_fan 0.7.0 → 0.8.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: 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