hyperctl 0.1.0 → 0.1.1
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 +4 -4
- data/lib/hyperctl.rb +1 -0
- data/lib/hyperctl/sysfs.rb +175 -171
- data/lib/hyperctl/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0b2b0f0133da7e528821e2c7424a4fd5bfc4163
|
4
|
+
data.tar.gz: c77ebe50391c5405b75bfe8121f8edf040492576
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bab6dea8336e756ffa21d23d5ff41410adcc56a13dea20bb5ff0eb1b25aaaebe1fc6d3eb58b24b1ecb80c949212a9ac7e17ca6a2639a3b09fca4a5a75269ca42
|
7
|
+
data.tar.gz: d8864acf582d1a736fc4112a005475b6097e5f2e80969350827f3e1d5423eabdf9e18aadee0b497b7b9d1e8a2e586a6e646e400a6cc799faeea250621941a646
|
data/lib/hyperctl.rb
CHANGED
data/lib/hyperctl/sysfs.rb
CHANGED
@@ -1,189 +1,193 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
1
|
+
require 'hyperctl'
|
2
|
+
|
3
|
+
module Hyperctl
|
4
|
+
class Sysfs
|
5
|
+
attr_accessor :cpu_info
|
6
|
+
|
7
|
+
# @api private
|
8
|
+
def initialize
|
9
|
+
@cpu_info = refresh
|
10
|
+
end
|
11
|
+
|
12
|
+
# Refresh the `cpu_info` [Hash] of the current CPU states
|
13
|
+
#
|
14
|
+
# @return [Hash] of cpu status
|
15
|
+
# @api public
|
16
|
+
def refresh
|
17
|
+
info = {}
|
18
|
+
|
19
|
+
# get a listing of all cpu cores
|
20
|
+
cpu_dirs = Dir.glob('/sys/devices/system/cpu/cpu[0-9]*')
|
21
|
+
|
22
|
+
cpu_dirs.each do |d|
|
23
|
+
# find the "name" of the cpu based on the sysfs dir. Eg, cpu15
|
24
|
+
cpu_name = File.basename d
|
25
|
+
cpu_idx = cpu_name.to_sym
|
26
|
+
info[cpu_idx] = { :name => cpu_name }
|
27
|
+
|
28
|
+
# find the numeric core_id. Eg, 15 in sysfs as
|
29
|
+
# /sys/devices/system/cpu/cpu3/topology/core_id but we can parse it from
|
30
|
+
# the path
|
31
|
+
core_id = cpu_name.match(/cpu(\d+)/)[1].to_i
|
32
|
+
info[cpu_idx][:core_id] = core_id
|
33
|
+
|
34
|
+
# is the cpu online?
|
35
|
+
# if a CPU is online, /sys/devices/system/cpu/cpu1/online will be 1,
|
36
|
+
# otherwise 0. cpu0 appears to be special and does not have the online
|
37
|
+
# sysfs entry on any of the systems I inspected. I suspect that it might
|
38
|
+
# get this attribute if CONFIG_BOOTPARAM_HOTPLUG_CPU0 is enabled per
|
39
|
+
# https://www.kernel.org/doc/Documentation/cpu-hotplug.txt
|
40
|
+
path = File.join(d, 'online')
|
41
|
+
online = false
|
42
|
+
if File.exist?(path)
|
43
|
+
online = to_bool(File.read(path).chomp)
|
44
|
+
elsif core_id == 0
|
45
|
+
# cpu0 gets a special pass if the online attr is missing
|
46
|
+
online = true
|
47
|
+
end
|
48
|
+
info[cpu_idx][:online] = online
|
49
|
+
|
50
|
+
next unless online
|
51
|
+
|
52
|
+
# does the cpu have any [SMT] siblings?
|
53
|
+
# The attr /sys/devices/system/cpu/cpu6/topology/thread_siblings_list
|
54
|
+
# will list all siblings including the cpu's own core_id This attr is not
|
55
|
+
# present if the cpu is offline This attr is not present under EL5.x
|
56
|
+
# (2.6.18-164.el5PAE) on the one system I inspected that appears to have
|
57
|
+
# HT disabled in the bios (/proc/cpuinfo shows the ht cpu flag but
|
58
|
+
# there's no siblings list)
|
59
|
+
path = File.join(d, 'topology/thread_siblings_list')
|
60
|
+
if File.exist?(path)
|
61
|
+
sibs = File.read(path).chomp.split(',')
|
62
|
+
# convert core_id(s) to be numeric
|
63
|
+
sibs.map! {|s| s.to_i }
|
64
|
+
# remove the cpu's core_id from the list
|
65
|
+
sibs = sibs - [ core_id ]
|
66
|
+
unless sibs.empty?
|
67
|
+
info[cpu_idx][:thread_siblings_list] = sibs
|
68
|
+
end
|
65
69
|
end
|
66
70
|
end
|
71
|
+
|
72
|
+
@cpu_info = info
|
67
73
|
end
|
68
74
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
cores
|
75
|
+
# List of all CPUs in system by numeric core id
|
76
|
+
#
|
77
|
+
# @return [Array<Integer>] of core ids
|
78
|
+
# @api public
|
79
|
+
def cores
|
80
|
+
cores = []
|
81
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
82
|
+
cores << cpu_info[k][:core_id]
|
83
|
+
end
|
84
|
+
|
85
|
+
return cores
|
80
86
|
end
|
81
87
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
if cpu_info[k][:online] == true
|
94
|
-
cores << core_id
|
88
|
+
# List of online CPUs in system by numeric core id
|
89
|
+
#
|
90
|
+
# @return [Array<Integer>] of core ids
|
91
|
+
# @api public
|
92
|
+
def online_cores
|
93
|
+
cores = []
|
94
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
95
|
+
core_id = cpu_info[k][:core_id]
|
96
|
+
if cpu_info[k][:online] == true
|
97
|
+
cores << core_id
|
98
|
+
end
|
95
99
|
end
|
100
|
+
|
101
|
+
return cores
|
96
102
|
end
|
97
103
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
if cpu_info[k][:online] == false
|
110
|
-
cores << core_id
|
104
|
+
# List of offline CPUs in system by numeric core id
|
105
|
+
#
|
106
|
+
# @return [Array<Integer>] of core ids
|
107
|
+
# @api public
|
108
|
+
def offline_cores
|
109
|
+
cores = []
|
110
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
111
|
+
core_id = cpu_info[k][:core_id]
|
112
|
+
if cpu_info[k][:online] == false
|
113
|
+
cores << core_id
|
114
|
+
end
|
111
115
|
end
|
116
|
+
|
117
|
+
return cores
|
112
118
|
end
|
113
119
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
if cpu_info[k][:online] == true
|
134
|
-
cores << core_id
|
120
|
+
# List of sibling (aka hyperthread/SMT) CPUs in system by numeric core id
|
121
|
+
#
|
122
|
+
# @return [Array<Integer>] of core ids
|
123
|
+
# @api public
|
124
|
+
def sibling_cores
|
125
|
+
cores = []
|
126
|
+
checked_cores = []
|
127
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
128
|
+
cpu = cpu_info[k]
|
129
|
+
checked_cores << cpu[:core_id]
|
130
|
+
|
131
|
+
if cpu.has_key?(:thread_siblings_list)
|
132
|
+
(cpu[:thread_siblings_list] - checked_cores).each do |core_id|
|
133
|
+
# check to see if the core is already disabled
|
134
|
+
# XXX this probably isn't nessicary as a disabled core appears to #
|
135
|
+
# never be listed as a sibiling
|
136
|
+
if cpu_info[k][:online] == true
|
137
|
+
cores << core_id
|
138
|
+
end
|
135
139
|
end
|
136
140
|
end
|
137
141
|
end
|
142
|
+
|
143
|
+
return cores
|
144
|
+
end
|
145
|
+
|
146
|
+
# Are all phyical/hyperthread/SMT/sibling cores enabled?
|
147
|
+
#
|
148
|
+
# @return [Bool] of status
|
149
|
+
# @api public
|
150
|
+
def all_cores_enabled?
|
151
|
+
cores.count == online_cores.count
|
152
|
+
end
|
153
|
+
|
154
|
+
# Are all hyperthread/SMT/sibling cores Disabled?
|
155
|
+
#
|
156
|
+
# @return [Bool] of status
|
157
|
+
# @api public
|
158
|
+
def all_siblings_disabled?
|
159
|
+
sibling_cores.empty?
|
160
|
+
end
|
161
|
+
|
162
|
+
# Enable a CPU by numeric core id
|
163
|
+
#
|
164
|
+
# @param core_id [Integer]
|
165
|
+
# @api public
|
166
|
+
def self.enable_core(core_id)
|
167
|
+
set_core(core_id, '1')
|
138
168
|
end
|
139
169
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
# @param core_id [Integer]
|
162
|
-
# @api public
|
163
|
-
def self.enable_core(core_id)
|
164
|
-
set_core(core_id, '1')
|
165
|
-
end
|
166
|
-
|
167
|
-
# Disable a CPU by numeric core id
|
168
|
-
#
|
169
|
-
# @param core_id [Integer]
|
170
|
-
# @api public
|
171
|
-
def self.disable_core(core_id)
|
172
|
-
set_core(core_id, '0')
|
173
|
-
end
|
174
|
-
|
175
|
-
private
|
176
|
-
|
177
|
-
def to_bool(s)
|
178
|
-
return true if s =~ /^1$/
|
179
|
-
return false
|
180
|
-
end
|
181
|
-
|
182
|
-
def self.set_core(core_id, state)
|
183
|
-
path = File.join('/sys/devices/system/cpu', "cpu#{core_id.to_s}", 'online')
|
184
|
-
# doesn't work in ruby 1.8.7: File.write(path, '0')
|
185
|
-
File.open(path, 'w') do |f|
|
186
|
-
f.write(state)
|
170
|
+
# Disable a CPU by numeric core id
|
171
|
+
#
|
172
|
+
# @param core_id [Integer]
|
173
|
+
# @api public
|
174
|
+
def self.disable_core(core_id)
|
175
|
+
set_core(core_id, '0')
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def to_bool(s)
|
181
|
+
return true if s =~ /^1$/
|
182
|
+
return false
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.set_core(core_id, state)
|
186
|
+
path = File.join('/sys/devices/system/cpu', "cpu#{core_id.to_s}", 'online')
|
187
|
+
# doesn't work in ruby 1.8.7: File.write(path, '0')
|
188
|
+
File.open(path, 'w') do |f|
|
189
|
+
f.write(state)
|
190
|
+
end
|
187
191
|
end
|
188
|
-
end
|
189
|
-
end #
|
192
|
+
end # class Sysfs
|
193
|
+
end # module Hyperctl
|
data/lib/hyperctl/version.rb
CHANGED