hyperctl 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -0
- data/README.md +200 -0
- data/Rakefile +14 -0
- data/bin/hyperctl +90 -0
- data/hyperctl.gemspec +33 -0
- data/lib/hyperctl/sysfs.rb +189 -0
- data/lib/hyperctl/version.rb +3 -0
- data/lib/hyperctl.rb +43 -0
- data/spec/hyperctl_spec.rb +123 -0
- data/spec/hyperctl_sysfs_spec.rb +154 -0
- data/spec/spec_helper.rb +102 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd42c9d0ce6995577336ac5d079c38b2dbcf5f0b
|
4
|
+
data.tar.gz: d71520d05bb74c3bb584868fbdb9663be22b7b6c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d90ca4e32248d536a58eb2a9f463e69caa9cbf8617d2d9e0b86358f38f95e2727292476c0ac94ba5acceadf373ee4c6db6075f7cacbd19acfbad78f63bc856d8
|
7
|
+
data.tar.gz: f3fdfd9fbc3ee5c449efddcd8af2daf59ed74123efe78769add4bffd3d9e7ae87942133907d3504cc65c51fb7a8f4783f2313056f63eaa2d2e511b2c24d4d523
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
Ruby hyperctl Gem
|
2
|
+
=================
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/jhoblitt/hyperctl.png)](https://travis-ci.org/jhoblitt/hyperctl)
|
5
|
+
|
6
|
+
#### Table of Contents
|
7
|
+
|
8
|
+
1. [Summary](#summary)
|
9
|
+
2. [Description](#description)
|
10
|
+
3. [Install](#install)
|
11
|
+
4. [Usage](#usage)
|
12
|
+
5. [Versioning](#versioning)
|
13
|
+
6. [Support](#support)
|
14
|
+
7. [Contributing](#contributing)
|
15
|
+
8. [See Also](#see-also)
|
16
|
+
|
17
|
+
Summary
|
18
|
+
-------
|
19
|
+
|
20
|
+
A utility for enabling/disabling hyperthreading
|
21
|
+
|
22
|
+
|
23
|
+
Description
|
24
|
+
-----------
|
25
|
+
|
26
|
+
This Gem provides a simple cli utility named `hyperctl` that can check the
|
27
|
+
status of and [with appropriate permissions] enable/disable
|
28
|
+
hyperthreading/SMT/sibling cores on Linux via the
|
29
|
+
[`sysfs`](https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt)
|
30
|
+
pseudo filesystem. It should be compatible with most modern Linux
|
31
|
+
distributions as long as `sysfs` is mounted at `/sysfs`.
|
32
|
+
|
33
|
+
|
34
|
+
Install
|
35
|
+
-------
|
36
|
+
|
37
|
+
### via rubygems
|
38
|
+
|
39
|
+
gem install hyperctl
|
40
|
+
|
41
|
+
### from git repo with bundler
|
42
|
+
|
43
|
+
bundle install
|
44
|
+
bundle exec rake install
|
45
|
+
|
46
|
+
|
47
|
+
Usage
|
48
|
+
-----
|
49
|
+
|
50
|
+
### `hyperctl`
|
51
|
+
|
52
|
+
Usage:
|
53
|
+
hyperctl
|
54
|
+
hyperctl (--enable | --disable) [--quiet]
|
55
|
+
hyperctl --status (--enable | --disable) [--quiet]
|
56
|
+
hyperctl -h | --help
|
57
|
+
hyperctl --version
|
58
|
+
|
59
|
+
Options:
|
60
|
+
--enable Enable hyperthreading.
|
61
|
+
--disable Diable hyperthreading.
|
62
|
+
--status Report hyperthreading state.
|
63
|
+
--quiet Suppress stdout.
|
64
|
+
--version Show version.
|
65
|
+
-h --help Show this screen.
|
66
|
+
|
67
|
+
#### Exit codes
|
68
|
+
|
69
|
+
* `0` - success
|
70
|
+
* `1` - option parsing related error
|
71
|
+
* `2` - system error (Eg., permission denied)
|
72
|
+
* `3` - status does not match desired state
|
73
|
+
|
74
|
+
#### no options
|
75
|
+
|
76
|
+
Prints the current status of hyperthreading on the system to the `stdout`.
|
77
|
+
Exits with `0` if no errors were encountered.
|
78
|
+
|
79
|
+
$ hyperctl
|
80
|
+
cpu0 : enabled - hypertheading: enabled
|
81
|
+
cpu1 : enabled - hypertheading: enabled
|
82
|
+
cpu2 : enabled - hypertheading: enabled
|
83
|
+
cpu3 : enabled - hypertheading: enabled
|
84
|
+
cpu4 : enabled - hypertheading: enabled
|
85
|
+
cpu5 : enabled - hypertheading: enabled
|
86
|
+
cpu6 : enabled - hypertheading: enabled
|
87
|
+
cpu7 : enabled - hypertheading: enabled
|
88
|
+
|
89
|
+
#### `(--enable | --disable) [--quiet]`
|
90
|
+
|
91
|
+
Attempt to enable or disable all hyperthread/SMT/sibling cores on the system.
|
92
|
+
Exits with `0` upon success, `2` for system errors, or `3` for state change
|
93
|
+
failures (unlikely).
|
94
|
+
|
95
|
+
With appropriate permissions to modify the appropriate sysfs entries:
|
96
|
+
|
97
|
+
$ sudo hyperctl --disable
|
98
|
+
cpu0 : enabled - hypertheading: disabled
|
99
|
+
cpu1 : enabled - hypertheading: disabled
|
100
|
+
cpu2 : enabled - hypertheading: disabled
|
101
|
+
cpu3 : enabled - hypertheading: disabled
|
102
|
+
cpu4 : disabled - hypertheading: disabled
|
103
|
+
cpu5 : disabled - hypertheading: disabled
|
104
|
+
cpu6 : disabled - hypertheading: disabled
|
105
|
+
cpu7 : disabled - hypertheading: disabled
|
106
|
+
$ echo $?
|
107
|
+
0
|
108
|
+
|
109
|
+
Without appropriate permissions:
|
110
|
+
|
111
|
+
$ hyperctl --disable
|
112
|
+
Permission denied @ rb_sysopen - /sys/devices/system/cpu/cpu4/online
|
113
|
+
$ echo $?
|
114
|
+
2
|
115
|
+
|
116
|
+
#### `--status (--enable | --disable) [--quiet]`
|
117
|
+
|
118
|
+
Checks the status of hyperthread/SMT/sibling cores on the system. Exits with
|
119
|
+
`0` if the state matches the `(--enable | --disable)` option, otherwise with
|
120
|
+
`3`
|
121
|
+
|
122
|
+
System already in `--disable` state:
|
123
|
+
|
124
|
+
$ sudo hyperctl --status --disable
|
125
|
+
cpu0 : enabled - hypertheading: disabled
|
126
|
+
cpu1 : enabled - hypertheading: disabled
|
127
|
+
cpu2 : enabled - hypertheading: disabled
|
128
|
+
cpu3 : enabled - hypertheading: disabled
|
129
|
+
cpu4 : disabled - hypertheading: disabled
|
130
|
+
cpu5 : disabled - hypertheading: disabled
|
131
|
+
cpu6 : disabled - hypertheading: disabled
|
132
|
+
cpu7 : disabled - hypertheading: disabled
|
133
|
+
$ echo $?
|
134
|
+
0
|
135
|
+
|
136
|
+
System not in `--enable` state:
|
137
|
+
|
138
|
+
$ sudo hyperctl --status --enable
|
139
|
+
cpu0 : enabled - hypertheading: disabled
|
140
|
+
cpu1 : enabled - hypertheading: disabled
|
141
|
+
cpu2 : enabled - hypertheading: disabled
|
142
|
+
cpu3 : enabled - hypertheading: disabled
|
143
|
+
cpu4 : disabled - hypertheading: disabled
|
144
|
+
cpu5 : disabled - hypertheading: disabled
|
145
|
+
cpu6 : disabled - hypertheading: disabled
|
146
|
+
cpu7 : disabled - hypertheading: disabled
|
147
|
+
$ echo $?
|
148
|
+
3
|
149
|
+
|
150
|
+
#### `[--quiet]`
|
151
|
+
|
152
|
+
Suppresses the `stdout` status message. Intended for usage from scripts.
|
153
|
+
|
154
|
+
$ sudo hyperctl --status --enable --quiet
|
155
|
+
$ echo $?
|
156
|
+
3
|
157
|
+
|
158
|
+
$ sudo hyperctl --status --disable --quiet
|
159
|
+
$ echo $?
|
160
|
+
0
|
161
|
+
|
162
|
+
|
163
|
+
Versioning
|
164
|
+
----------
|
165
|
+
|
166
|
+
This Gem is versioned according to the [Semantic Versioning
|
167
|
+
2.0.0](http://semver.org/spec/v2.0.0.html) specification.
|
168
|
+
|
169
|
+
|
170
|
+
Support
|
171
|
+
-------
|
172
|
+
|
173
|
+
Please log tickets and issues at [github](https://github.com/jhoblitt/hyperctl)
|
174
|
+
|
175
|
+
|
176
|
+
Contributing
|
177
|
+
------------
|
178
|
+
|
179
|
+
1. Fork it on github
|
180
|
+
2. Make a local clone of your fork
|
181
|
+
3. Create a topic branch. Eg, `feature/mousetrap`
|
182
|
+
4. Make/commit changes
|
183
|
+
* Commit messages should be in
|
184
|
+
[imperative tense](http://git-scm.com/book/ch5-2.html)
|
185
|
+
* Check that `Rspec` unit tests are not broken and coverage is added for
|
186
|
+
new features - `bundle exec rake spec`
|
187
|
+
* Documentation of API/features is updated as appropriate in the README
|
188
|
+
5. When the feature is complete, rebase / squash the branch history as
|
189
|
+
necessary to remove "fix typo", "oops", "whitespace" and other trivial
|
190
|
+
commits
|
191
|
+
6. Push the topic branch to github
|
192
|
+
7. Open a Pull Request (PR) from the *topic branch* onto parent repo's `master`
|
193
|
+
branch
|
194
|
+
|
195
|
+
|
196
|
+
See Also
|
197
|
+
--------
|
198
|
+
|
199
|
+
* [Linux sysfs docs](https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt)
|
200
|
+
* [Linux cpu-hotplug docs](https://www.kernel.org/doc/Documentation/cpu-hotplug.txt)
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
YARD::Rake::YardocTask.new do |t|
|
8
|
+
t.files = ['lib/**/*.rb']
|
9
|
+
t.stats_options = ['--list-undoc']
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => [
|
13
|
+
:spec,
|
14
|
+
]
|
data/bin/hyperctl
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'hyperctl'
|
4
|
+
require "docopt"
|
5
|
+
|
6
|
+
doc = <<DOCOPT
|
7
|
+
#{__FILE__}
|
8
|
+
|
9
|
+
Usage:
|
10
|
+
#{__FILE__}
|
11
|
+
#{__FILE__} (--enable | --disable) [--quiet]
|
12
|
+
#{__FILE__} --status (--enable | --disable) [--quiet]
|
13
|
+
#{__FILE__} -h | --help
|
14
|
+
#{__FILE__} --version
|
15
|
+
|
16
|
+
Options:
|
17
|
+
--enable Enable hyperthreading.
|
18
|
+
--disable Diable hyperthreading.
|
19
|
+
--status Report hyperthreading state.
|
20
|
+
--quiet Suppress stdout.
|
21
|
+
--version Show version.
|
22
|
+
-h --help Show this screen.
|
23
|
+
|
24
|
+
DOCOPT
|
25
|
+
|
26
|
+
|
27
|
+
@options = {}
|
28
|
+
begin
|
29
|
+
@options = Docopt::docopt(doc)
|
30
|
+
rescue Docopt::Exit => e
|
31
|
+
puts e.message
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
|
35
|
+
if @options['--version']
|
36
|
+
puts Hyperctl::VERSION
|
37
|
+
exit 0
|
38
|
+
end
|
39
|
+
|
40
|
+
hctl = Hyperctl::Sysfs.new
|
41
|
+
|
42
|
+
exit_code = 0
|
43
|
+
|
44
|
+
begin
|
45
|
+
if @options['--status']
|
46
|
+
exit_code = check_status(hctl)
|
47
|
+
elsif @options['--enable'] || @options['--disable']
|
48
|
+
exit_code = change_state(hctl)
|
49
|
+
end
|
50
|
+
|
51
|
+
unless @options['--quiet']
|
52
|
+
text = Hyperctl.status(hctl)
|
53
|
+
puts text
|
54
|
+
end
|
55
|
+
rescue Errno::EACCES => e
|
56
|
+
puts e.message
|
57
|
+
exit 2
|
58
|
+
end
|
59
|
+
|
60
|
+
exit exit_code
|
61
|
+
|
62
|
+
BEGIN {
|
63
|
+
def change_state(hctl)
|
64
|
+
if @options['--enable']
|
65
|
+
Hyperctl.enable(hctl)
|
66
|
+
hctl.refresh
|
67
|
+
return check_status(hctl)
|
68
|
+
end
|
69
|
+
|
70
|
+
if @options['--disable']
|
71
|
+
Hyperctl.disable(hctl)
|
72
|
+
hctl.refresh
|
73
|
+
return check_status(hctl)
|
74
|
+
end
|
75
|
+
|
76
|
+
raise
|
77
|
+
end
|
78
|
+
|
79
|
+
def check_status(hctl)
|
80
|
+
if @options['--enable']
|
81
|
+
return hctl.all_cores_enabled? ? 0 : 3
|
82
|
+
end
|
83
|
+
|
84
|
+
if @options['--disable']
|
85
|
+
return hctl.all_siblings_disabled? ? 0 : 3
|
86
|
+
end
|
87
|
+
|
88
|
+
raise
|
89
|
+
end
|
90
|
+
}
|
data/hyperctl.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'hyperctl/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'hyperctl'
|
6
|
+
s.version = Hyperctl::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ['Joshua Hoblitt']
|
9
|
+
s.email = ['jhoblitt@cpan.org']
|
10
|
+
s.homepage = 'https://github.com/jhoblitt/hyperctl'
|
11
|
+
s.summary = %q{A utility for enabling/disabling hyperthreading}
|
12
|
+
s.description = %q{This Gem provides a simple cli utility named `hyperctl`
|
13
|
+
that can check the status of and [with appropriate permissions] enable/disable
|
14
|
+
hyperthreading/SMT/sibling cores on Linux via the `sysfs` pseudo filesystem.
|
15
|
+
It should be compatible with most modern Linux distributions as long as `sysfs` is mounted at `/sysfs`.}
|
16
|
+
s.license = 'Apache 2.0'
|
17
|
+
|
18
|
+
s.required_ruby_version = '>= 1.8.7'
|
19
|
+
s.add_runtime_dependency('docopt', '~> 0.5.0')
|
20
|
+
s.add_development_dependency('rspec', '~> 3.0')
|
21
|
+
s.add_development_dependency('rspec-expectations', '~> 3.0')
|
22
|
+
s.add_development_dependency('rspec-mocks', '~> 3.0')
|
23
|
+
s.add_development_dependency('rake', '~> 10.0')
|
24
|
+
s.add_development_dependency('fakefs', '~> 0.5.2')
|
25
|
+
s.add_development_dependency('mocha', '~> 1.0')
|
26
|
+
s.add_development_dependency('yard', '~> 0.8')
|
27
|
+
|
28
|
+
s.rubygems_version = '>= 1.6.1'
|
29
|
+
s.files = `git ls-files`.split("\n")
|
30
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
31
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
32
|
+
s.require_path = 'lib'
|
33
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
class Hyperctl::Sysfs
|
2
|
+
attr_accessor :cpu_info
|
3
|
+
|
4
|
+
# @api private
|
5
|
+
def initialize
|
6
|
+
@cpu_info = refresh
|
7
|
+
end
|
8
|
+
|
9
|
+
# Refresh the `cpu_info` [Hash] of the current CPU states
|
10
|
+
#
|
11
|
+
# @return [Hash] of cpu status
|
12
|
+
# @api public
|
13
|
+
def refresh
|
14
|
+
info = {}
|
15
|
+
|
16
|
+
# get a listing of all cpu cores
|
17
|
+
cpu_dirs = Dir.glob('/sys/devices/system/cpu/cpu[0-9]*')
|
18
|
+
|
19
|
+
cpu_dirs.each do |d|
|
20
|
+
# find the "name" of the cpu based on the sysfs dir. Eg, cpu15
|
21
|
+
cpu_name = File.basename d
|
22
|
+
cpu_idx = cpu_name.to_sym
|
23
|
+
info[cpu_idx] = { :name => cpu_name }
|
24
|
+
|
25
|
+
# find the numeric core_id. Eg, 15 in sysfs as
|
26
|
+
# /sys/devices/system/cpu/cpu3/topology/core_id but we can parse it from
|
27
|
+
# the path
|
28
|
+
core_id = cpu_name.match(/cpu(\d+)/)[1].to_i
|
29
|
+
info[cpu_idx][:core_id] = core_id
|
30
|
+
|
31
|
+
# is the cpu online?
|
32
|
+
# if a CPU is online, /sys/devices/system/cpu/cpu1/online will be 1,
|
33
|
+
# otherwise 0. cpu0 appears to be special and does not have the online
|
34
|
+
# sysfs entry on any of the systems I inspected. I suspect that it might
|
35
|
+
# get this attribute if CONFIG_BOOTPARAM_HOTPLUG_CPU0 is enabled per
|
36
|
+
# https://www.kernel.org/doc/Documentation/cpu-hotplug.txt
|
37
|
+
path = File.join(d, 'online')
|
38
|
+
online = false
|
39
|
+
if File.exist?(path)
|
40
|
+
online = to_bool(File.read(path).chomp)
|
41
|
+
elsif core_id == 0
|
42
|
+
# cpu0 gets a special pass if the online attr is missing
|
43
|
+
online = true
|
44
|
+
end
|
45
|
+
info[cpu_idx][:online] = online
|
46
|
+
|
47
|
+
next unless online
|
48
|
+
|
49
|
+
# does the cpu have any [SMT] siblings?
|
50
|
+
# The attr /sys/devices/system/cpu/cpu6/topology/thread_siblings_list
|
51
|
+
# will list all siblings including the cpu's own core_id This attr is not
|
52
|
+
# present if the cpu is offline This attr is not present under EL5.x
|
53
|
+
# (2.6.18-164.el5PAE) on the one system I inspected that appears to have
|
54
|
+
# HT disabled in the bios (/proc/cpuinfo shows the ht cpu flag but
|
55
|
+
# there's no siblings list)
|
56
|
+
path = File.join(d, 'topology/thread_siblings_list')
|
57
|
+
if File.exist?(path)
|
58
|
+
sibs = File.read(path).chomp.split(',')
|
59
|
+
# convert core_id(s) to be numeric
|
60
|
+
sibs.map! {|s| s.to_i }
|
61
|
+
# remove the cpu's core_id from the list
|
62
|
+
sibs = sibs - [ core_id ]
|
63
|
+
unless sibs.empty?
|
64
|
+
info[cpu_idx][:thread_siblings_list] = sibs
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
@cpu_info = info
|
70
|
+
end
|
71
|
+
|
72
|
+
# List of all CPUs in system by numeric core id
|
73
|
+
#
|
74
|
+
# @return [Array<Integer>] of core ids
|
75
|
+
# @api public
|
76
|
+
def cores
|
77
|
+
cores = []
|
78
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
79
|
+
cores << cpu_info[k][:core_id]
|
80
|
+
end
|
81
|
+
|
82
|
+
return cores
|
83
|
+
end
|
84
|
+
|
85
|
+
# List of online CPUs in system by numeric core id
|
86
|
+
#
|
87
|
+
# @return [Array<Integer>] of core ids
|
88
|
+
# @api public
|
89
|
+
def online_cores
|
90
|
+
cores = []
|
91
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
92
|
+
core_id = cpu_info[k][:core_id]
|
93
|
+
if cpu_info[k][:online] == true
|
94
|
+
cores << core_id
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
return cores
|
99
|
+
end
|
100
|
+
|
101
|
+
# List of offline CPUs in system by numeric core id
|
102
|
+
#
|
103
|
+
# @return [Array<Integer>] of core ids
|
104
|
+
# @api public
|
105
|
+
def offline_cores
|
106
|
+
cores = []
|
107
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
108
|
+
core_id = cpu_info[k][:core_id]
|
109
|
+
if cpu_info[k][:online] == false
|
110
|
+
cores << core_id
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
return cores
|
115
|
+
end
|
116
|
+
|
117
|
+
# List of sibling (aka hyperthread/SMT) CPUs in system by numeric core id
|
118
|
+
#
|
119
|
+
# @return [Array<Integer>] of core ids
|
120
|
+
# @api public
|
121
|
+
def sibling_cores
|
122
|
+
cores = []
|
123
|
+
checked_cores = []
|
124
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
125
|
+
cpu = cpu_info[k]
|
126
|
+
checked_cores << cpu[:core_id]
|
127
|
+
|
128
|
+
if cpu.has_key?(:thread_siblings_list)
|
129
|
+
(cpu[:thread_siblings_list] - checked_cores).each do |core_id|
|
130
|
+
# check to see if the core is already disabled
|
131
|
+
# XXX this probably isn't nessicary as a disabled core appears to #
|
132
|
+
# never be listed as a sibiling
|
133
|
+
if cpu_info[k][:online] == true
|
134
|
+
cores << core_id
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
return cores
|
141
|
+
end
|
142
|
+
|
143
|
+
# Are all phyical/hyperthread/SMT/sibling cores enabled?
|
144
|
+
#
|
145
|
+
# @return [Bool] of status
|
146
|
+
# @api public
|
147
|
+
def all_cores_enabled?
|
148
|
+
cores.count == online_cores.count
|
149
|
+
end
|
150
|
+
|
151
|
+
# Are all hyperthread/SMT/sibling cores Disabled?
|
152
|
+
#
|
153
|
+
# @return [Bool] of status
|
154
|
+
# @api public
|
155
|
+
def all_siblings_disabled?
|
156
|
+
sibling_cores.empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
# Enable a CPU by numeric core id
|
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)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end # class Hyperctl::Sysfs
|
data/lib/hyperctl.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'hyperctl/sysfs'
|
2
|
+
|
3
|
+
module Hyperctl
|
4
|
+
# Enable all sibling cores
|
5
|
+
#
|
6
|
+
# @param hctl [Hyperctl::Sysfs] object
|
7
|
+
# @api public
|
8
|
+
def self.enable(hctl)
|
9
|
+
# as far as I can tell, there's no way to discover the topology information
|
10
|
+
# for which cores and siblings if either of them is disabled. So we are
|
11
|
+
# just trying to enable everything that is disabled...
|
12
|
+
cores = hctl.offline_cores
|
13
|
+
cores.each {|core_id| Hyperctl::Sysfs.enable_core(core_id) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Disable all sibling cores
|
17
|
+
#
|
18
|
+
# @param hctl [Hyperctl::Sysfs] object
|
19
|
+
# @api public
|
20
|
+
def self.disable(hctl)
|
21
|
+
cores = hctl.sibling_cores
|
22
|
+
cores.each {|core_id| Hyperctl::Sysfs.disable_core(core_id) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Generate a pretty formatted string of sibling core status
|
26
|
+
#
|
27
|
+
# @param hctl [Hyperctl::Sysfs] object
|
28
|
+
# @return [String] the generated string
|
29
|
+
# @api public
|
30
|
+
def self.status(hctl)
|
31
|
+
cpu_info = hctl.cpu_info
|
32
|
+
text = ""
|
33
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
34
|
+
cpu = cpu_info[k]
|
35
|
+
state = cpu[:online] ? 'enabled' : 'disabled'
|
36
|
+
ht = cpu.has_key?(:thread_siblings_list) ? 'enabled' : 'disabled'
|
37
|
+
text << "#{sprintf('%-5s',k.to_s)}: #{sprintf('%-8s', state)}"
|
38
|
+
text << " - hypertheading: #{ht}\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
return text
|
42
|
+
end
|
43
|
+
end # module Hyperctl
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hyperctl do
|
4
|
+
let(:hctl) { Hyperctl::Sysfs.new }
|
5
|
+
|
6
|
+
describe '#status' do
|
7
|
+
context '8 physical cores with HT enabled' do
|
8
|
+
include_context "cpuinfo_8core_w_ht"
|
9
|
+
|
10
|
+
text =<<EOS
|
11
|
+
cpu0 : enabled - hypertheading: enabled
|
12
|
+
cpu1 : enabled - hypertheading: enabled
|
13
|
+
cpu2 : enabled - hypertheading: enabled
|
14
|
+
cpu3 : enabled - hypertheading: enabled
|
15
|
+
cpu4 : enabled - hypertheading: enabled
|
16
|
+
cpu5 : enabled - hypertheading: enabled
|
17
|
+
cpu6 : enabled - hypertheading: enabled
|
18
|
+
cpu7 : enabled - hypertheading: enabled
|
19
|
+
cpu8 : enabled - hypertheading: enabled
|
20
|
+
cpu9 : enabled - hypertheading: enabled
|
21
|
+
cpu10: enabled - hypertheading: enabled
|
22
|
+
cpu11: enabled - hypertheading: enabled
|
23
|
+
cpu12: enabled - hypertheading: enabled
|
24
|
+
cpu13: enabled - hypertheading: enabled
|
25
|
+
cpu14: enabled - hypertheading: enabled
|
26
|
+
cpu15: enabled - hypertheading: enabled
|
27
|
+
EOS
|
28
|
+
it do
|
29
|
+
hctl.stubs(:cpu_info).returns(info)
|
30
|
+
expect(Hyperctl.status(hctl)).to eq(text)
|
31
|
+
end
|
32
|
+
end # 8 physical cores with HT enabled
|
33
|
+
|
34
|
+
context '12 physical cores with HT disabled' do
|
35
|
+
include_context "cpuinfo_12core_wo_ht"
|
36
|
+
text =<<EOS
|
37
|
+
cpu0 : enabled - hypertheading: disabled
|
38
|
+
cpu1 : enabled - hypertheading: disabled
|
39
|
+
cpu2 : enabled - hypertheading: disabled
|
40
|
+
cpu3 : enabled - hypertheading: disabled
|
41
|
+
cpu4 : enabled - hypertheading: disabled
|
42
|
+
cpu5 : enabled - hypertheading: disabled
|
43
|
+
cpu6 : enabled - hypertheading: disabled
|
44
|
+
cpu7 : enabled - hypertheading: disabled
|
45
|
+
cpu8 : enabled - hypertheading: disabled
|
46
|
+
cpu9 : enabled - hypertheading: disabled
|
47
|
+
cpu10: enabled - hypertheading: disabled
|
48
|
+
cpu11: enabled - hypertheading: disabled
|
49
|
+
cpu12: disabled - hypertheading: disabled
|
50
|
+
cpu13: disabled - hypertheading: disabled
|
51
|
+
cpu14: disabled - hypertheading: disabled
|
52
|
+
cpu15: disabled - hypertheading: disabled
|
53
|
+
cpu16: disabled - hypertheading: disabled
|
54
|
+
cpu17: disabled - hypertheading: disabled
|
55
|
+
cpu18: disabled - hypertheading: disabled
|
56
|
+
cpu19: disabled - hypertheading: disabled
|
57
|
+
cpu20: disabled - hypertheading: disabled
|
58
|
+
cpu21: disabled - hypertheading: disabled
|
59
|
+
cpu22: disabled - hypertheading: disabled
|
60
|
+
cpu23: disabled - hypertheading: disabled
|
61
|
+
EOS
|
62
|
+
it do
|
63
|
+
hctl.stubs(:cpu_info).returns(info)
|
64
|
+
|
65
|
+
expect(Hyperctl.status(hctl)).to eq(text)
|
66
|
+
end
|
67
|
+
end # 12 physical cores with HT disabled
|
68
|
+
end #status
|
69
|
+
|
70
|
+
describe '#disable' do
|
71
|
+
context '8 physical cores with HT enabled' do
|
72
|
+
include_context "cpuinfo_8core_w_ht"
|
73
|
+
|
74
|
+
it 'should turn cores off' do
|
75
|
+
hctl.stubs(:cpu_info).returns(info)
|
76
|
+
8.upto(15).each do |core_id|
|
77
|
+
Hyperctl::Sysfs.expects(:disable_core).with(core_id).once
|
78
|
+
end
|
79
|
+
|
80
|
+
Hyperctl.disable(hctl)
|
81
|
+
end
|
82
|
+
end # 8 physical cores with HT enabled
|
83
|
+
|
84
|
+
context '12 physical cores with HT disabled' do
|
85
|
+
include_context "cpuinfo_12core_wo_ht"
|
86
|
+
|
87
|
+
it 'should do nothing' do
|
88
|
+
# all SMT cores are already disabled
|
89
|
+
hctl.stubs(:cpu_info).returns(info)
|
90
|
+
Hyperctl::Sysfs.expects(:disable_core).never
|
91
|
+
|
92
|
+
Hyperctl.disable(hctl)
|
93
|
+
end
|
94
|
+
end # 12 physical cores with HT disabled
|
95
|
+
end #disable
|
96
|
+
|
97
|
+
describe '#enable' do
|
98
|
+
context '8 physical cores with HT enabled' do
|
99
|
+
include_context "cpuinfo_8core_w_ht"
|
100
|
+
|
101
|
+
it 'should do nothing' do
|
102
|
+
# all SMT cores are already enabled
|
103
|
+
hctl.stubs(:cpu_info).returns(info)
|
104
|
+
Hyperctl::Sysfs.expects(:enable_core).never
|
105
|
+
|
106
|
+
Hyperctl.enable(hctl)
|
107
|
+
end
|
108
|
+
end # 8 physical cores with HT enabled
|
109
|
+
|
110
|
+
context '12 physical cores with HT disabled' do
|
111
|
+
include_context "cpuinfo_12core_wo_ht"
|
112
|
+
|
113
|
+
it 'should turn cores on' do
|
114
|
+
hctl.stubs(:cpu_info).returns(info)
|
115
|
+
12.upto(23).each do |core_id|
|
116
|
+
Hyperctl::Sysfs.expects(:enable_core).with(core_id).once
|
117
|
+
end
|
118
|
+
|
119
|
+
Hyperctl.enable(hctl)
|
120
|
+
end
|
121
|
+
end # 12 physical cores with HT disabled
|
122
|
+
end #enable
|
123
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
# pp must be required before fakefs
|
3
|
+
# see: https://github.com/defunkt/fakefs/issues/99
|
4
|
+
require 'pp'
|
5
|
+
require 'fakefs/spec_helpers'
|
6
|
+
|
7
|
+
describe Hyperctl::Sysfs do
|
8
|
+
let(:hctl) { Hyperctl::Sysfs.new }
|
9
|
+
include FakeFS::SpecHelpers
|
10
|
+
|
11
|
+
context 'on a 8 physical core w/ HT enabled system' do
|
12
|
+
include_context "sysfs_8core_w_ht"
|
13
|
+
include_context "cpuinfo_8core_w_ht"
|
14
|
+
|
15
|
+
context 'fakefs sanity checks' do
|
16
|
+
it { expect(File.exists?(sysfs('cpu1', 'online'))).to be true }
|
17
|
+
it { expect(File.exists?(sysfs('cpu1', 'topology/thread_siblings_list'))).to be true }
|
18
|
+
it { expect(sysfs('cpu1', 'topology/thread_siblings_list')).to contain(/1,9/) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#new' do
|
22
|
+
it 'finds all the cores' do
|
23
|
+
expect(hctl.cpu_info).to eq(info)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#disable_core' do
|
28
|
+
it 'disbles core_id 15' do
|
29
|
+
Hyperctl::Sysfs.disable_core(15)
|
30
|
+
|
31
|
+
expect(sysfs('cpu15', 'online')).to contain(/^0$/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context '#cores' do
|
36
|
+
it 'lists all cores' do
|
37
|
+
expect(hctl.cores).to eq((0 .. 15).to_a)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context '#online_cores' do
|
42
|
+
it 'lists all enabled cores' do
|
43
|
+
expect(hctl.online_cores).to eq((0 .. 15).to_a)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context '#offline_cores' do
|
48
|
+
it 'lists all disabled cores' do
|
49
|
+
expect(hctl.offline_cores).to eq []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context '#sibling_cores' do
|
54
|
+
it 'lists all smt cores' do
|
55
|
+
expect(hctl.sibling_cores).to eq((8 .. 15).to_a)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context '#all_cores_enabled?' do
|
60
|
+
it 'returns true' do
|
61
|
+
expect(hctl.all_cores_enabled?).to be true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context '#all_siblings_disabled?' do
|
66
|
+
it 'returns false' do
|
67
|
+
expect(hctl.all_siblings_disabled?).to be false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context '#enable_core' do
|
72
|
+
it 'enables core_id 15' do
|
73
|
+
Hyperctl::Sysfs.enable_core(15)
|
74
|
+
|
75
|
+
expect(sysfs('cpu15', 'online')).to contain(/^1$/)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end # on a 8 physical core w/ HT enabled system
|
79
|
+
|
80
|
+
context 'on a 12 physical core w/ HT diabled system' do
|
81
|
+
include_context "sysfs_12core_wo_ht"
|
82
|
+
include_context "cpuinfo_12core_wo_ht"
|
83
|
+
|
84
|
+
context 'fakefs sanity checks' do
|
85
|
+
it { expect(File.exists?(sysfs('cpu0', 'online'))).to be false }
|
86
|
+
it { expect(File.exists?(sysfs('cpu0', 'topology/thread_siblings_list'))).to be true }
|
87
|
+
|
88
|
+
it { expect(File.exists?(sysfs('cpu1', 'online'))).to be true }
|
89
|
+
it { expect(File.exists?(sysfs('cpu1', 'topology/thread_siblings_list'))).to be true }
|
90
|
+
|
91
|
+
it { expect(File.exists?(sysfs('cpu23', 'online'))).to be true }
|
92
|
+
it { expect(File.exists?(sysfs('cpu23', 'topology/thread_siblings_list'))).to be false }
|
93
|
+
end
|
94
|
+
|
95
|
+
context '#new' do
|
96
|
+
it 'finds all the cores' do
|
97
|
+
hctl = Hyperctl::Sysfs.new
|
98
|
+
expect(hctl.cpu_info).to eq(info)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context '#disable_core' do
|
103
|
+
it 'disbles core_id 15' do
|
104
|
+
Hyperctl::Sysfs.disable_core(15)
|
105
|
+
|
106
|
+
expect(sysfs('cpu15', 'online')).to contain(/^0$/)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context '#cores' do
|
111
|
+
it 'lists all cores' do
|
112
|
+
expect(hctl.cores).to eq((0 .. 23).to_a)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context '#online_cores' do
|
117
|
+
it 'lists all enabled cores' do
|
118
|
+
expect(hctl.online_cores).to eq((0 .. 11).to_a)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context '#offline_cores' do
|
123
|
+
it 'lists all disabled cores' do
|
124
|
+
expect(hctl.offline_cores).to eq((12 .. 23).to_a)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context '#sibling_cores' do
|
129
|
+
it 'lists all smt cores' do
|
130
|
+
expect(hctl.sibling_cores).to eq []
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context '#all_cores_enabled?' do
|
135
|
+
it 'returns false' do
|
136
|
+
expect(hctl.all_cores_enabled?).to be false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context '#all_siblings_disabled?' do
|
141
|
+
it 'returns true' do
|
142
|
+
expect(hctl.all_siblings_disabled?).to be true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context '#enable_core' do
|
147
|
+
it 'enables core_id 15' do
|
148
|
+
Hyperctl::Sysfs.enable_core(15)
|
149
|
+
|
150
|
+
expect(sysfs('cpu15', 'online')).to contain(/^1$/)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end # on a 12 physical core w/ HT disabled system
|
154
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'hyperctl'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.mock_framework = :mocha
|
5
|
+
end
|
6
|
+
|
7
|
+
def sysfs(cpu_name, attr)
|
8
|
+
File.join('/sys/devices/system/cpu/', cpu_name, attr)
|
9
|
+
end
|
10
|
+
|
11
|
+
def mksysfs(cpu_name, attr, value)
|
12
|
+
path = sysfs(cpu_name, attr)
|
13
|
+
dir = File.dirname path
|
14
|
+
FileUtils.mkdir_p dir
|
15
|
+
File.open(path, 'w+') do |f|
|
16
|
+
f.write(value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec::Matchers.define :contain do |content|
|
21
|
+
match do |path|
|
22
|
+
File.read(path) =~ content
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# 2.6.32-431.5.1.el6.x86_64
|
27
|
+
# 2 x Intel(R) Xeon(R) CPU E5-2643 0 @ 3.30GHz
|
28
|
+
RSpec.shared_context 'sysfs_8core_w_ht' do
|
29
|
+
before do
|
30
|
+
0.upto(15).each do |core_id|
|
31
|
+
next if core_id == 0
|
32
|
+
mksysfs("cpu#{core_id}", 'online', "1\n")
|
33
|
+
end
|
34
|
+
0.upto(7).each do |core_id|
|
35
|
+
mksysfs("cpu#{core_id}", 'topology/thread_siblings_list', "#{core_id},#{core_id + 8}\n")
|
36
|
+
end
|
37
|
+
8.upto(15).each do |core_id|
|
38
|
+
mksysfs("cpu#{core_id}", 'topology/thread_siblings_list', "#{core_id},#{core_id - 8}\n")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec.shared_context 'cpuinfo_8core_w_ht' do
|
44
|
+
info = {}
|
45
|
+
0.upto(7).each do |core_id|
|
46
|
+
name = "cpu#{core_id}"
|
47
|
+
info[name.to_sym] = {
|
48
|
+
:core_id => core_id,
|
49
|
+
:online => true,
|
50
|
+
:thread_siblings_list => [ core_id + 8 ],
|
51
|
+
:name => name,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
8.upto(15).each do |core_id|
|
55
|
+
name = "cpu#{core_id}"
|
56
|
+
info[name.to_sym] = {
|
57
|
+
:core_id => core_id,
|
58
|
+
:online => true,
|
59
|
+
:thread_siblings_list => [ core_id - 8 ],
|
60
|
+
:name => name,
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
let(:info) { info }
|
65
|
+
end
|
66
|
+
|
67
|
+
# 2.6.32-431.5.1.el6.x86_64
|
68
|
+
# 2 x Intel(R) Xeon(R) CPU X5675 @ 3.07GHz
|
69
|
+
RSpec.shared_context 'sysfs_12core_wo_ht' do
|
70
|
+
before do
|
71
|
+
0.upto(11).each do |core_id|
|
72
|
+
mksysfs("cpu#{core_id}", 'topology/thread_siblings_list', "#{core_id}\n")
|
73
|
+
next if core_id == 0
|
74
|
+
mksysfs("cpu#{core_id}", 'online', "1\n")
|
75
|
+
end
|
76
|
+
12.upto(23).each do |core_id|
|
77
|
+
mksysfs("cpu#{core_id}", 'online', "0\n")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
RSpec.shared_context 'cpuinfo_12core_wo_ht' do
|
83
|
+
info = {}
|
84
|
+
0.upto(11).each do |core_id|
|
85
|
+
name = "cpu#{core_id}"
|
86
|
+
info[name.to_sym] = {
|
87
|
+
:core_id => core_id,
|
88
|
+
:online => true,
|
89
|
+
:name => name,
|
90
|
+
}
|
91
|
+
end
|
92
|
+
12.upto(23).each do |core_id|
|
93
|
+
name = "cpu#{core_id}"
|
94
|
+
info[name.to_sym] = {
|
95
|
+
:core_id => core_id,
|
96
|
+
:online => false,
|
97
|
+
:name => name,
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
let(:info) { info }
|
102
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hyperctl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Hoblitt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: docopt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-expectations
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-mocks
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fakefs
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.5.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.5.2
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mocha
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.8'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.8'
|
125
|
+
description: |-
|
126
|
+
This Gem provides a simple cli utility named `hyperctl`
|
127
|
+
that can check the status of and [with appropriate permissions] enable/disable
|
128
|
+
hyperthreading/SMT/sibling cores on Linux via the `sysfs` pseudo filesystem.
|
129
|
+
It should be compatible with most modern Linux distributions as long as `sysfs` is mounted at `/sysfs`.
|
130
|
+
email:
|
131
|
+
- jhoblitt@cpan.org
|
132
|
+
executables:
|
133
|
+
- hyperctl
|
134
|
+
extensions: []
|
135
|
+
extra_rdoc_files: []
|
136
|
+
files:
|
137
|
+
- ".gitignore"
|
138
|
+
- ".travis.yml"
|
139
|
+
- Gemfile
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- bin/hyperctl
|
143
|
+
- hyperctl.gemspec
|
144
|
+
- lib/hyperctl.rb
|
145
|
+
- lib/hyperctl/sysfs.rb
|
146
|
+
- lib/hyperctl/version.rb
|
147
|
+
- spec/hyperctl_spec.rb
|
148
|
+
- spec/hyperctl_sysfs_spec.rb
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
homepage: https://github.com/jhoblitt/hyperctl
|
151
|
+
licenses:
|
152
|
+
- Apache 2.0
|
153
|
+
metadata: {}
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 1.8.7
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 2.4.4
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: A utility for enabling/disabling hyperthreading
|
174
|
+
test_files:
|
175
|
+
- spec/hyperctl_spec.rb
|
176
|
+
- spec/hyperctl_sysfs_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
178
|
+
has_rdoc:
|