cpuinfo 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/cpuinfo/LICENSE +21 -0
- data/cpuinfo/README.md +12 -0
- data/cpuinfo/Rakefile +11 -0
- data/cpuinfo/cpuinfo.gemspec +22 -0
- data/cpuinfo/lib/cpuinfo.rb +75 -0
- data/cpuinfo/test/fixtures/cpuinfo +216 -0
- data/cpuinfo/test/test.rb +30 -0
- data/lib/cp/cpu.rb +19 -0
- data/lib/cp/unix/sys/cpu.rb +372 -0
- data/lib/cp/windows/sys/cpu.rb +796 -0
- data/lib/sys-cpu.rb +1 -0
- data/test/test_sys_cpu_bsd.rb +97 -0
- data/test/test_sys_cpu_hpux.rb +49 -0
- data/test/test_sys_cpu_linux.rb +31 -0
- data/test/test_sys_cpu_sunos.rb +81 -0
- data/test/test_sys_cpu_version.rb +15 -0
- data/test/test_sys_cpu_windows.rb +72 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cd3fd6b47290969e1e19c3496854d3c342a0e56fa8e1fcbea7507c5a85ea8d35
|
4
|
+
data.tar.gz: 9571570022400c4c331d586258a586a1641d204ca843a223d496a542f675d07a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c0e005b310cb5bd98a833a889f7d9d5fe8858eae76635498b5be429062b2c6a9f83da019e3326982ad2991d3d3128565729794a288f6506ba23695eefe258b85
|
7
|
+
data.tar.gz: 3008f847eae9563e727ef684240a44466f6b445e844790c0b4952853857751fb2a1785c5adfcb69774c735048bd05ae0d6a35672037bb965d2783401291eeb1f
|
data/cpuinfo/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Matthias Winkelmann
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/cpuinfo/README.md
ADDED
data/cpuinfo/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'cpuinfo'
|
5
|
+
spec.version = '1.0.0'
|
6
|
+
spec.author = 'Matthias Winkelmann'
|
7
|
+
spec.email = 'm@matthi.coffee'
|
8
|
+
spec.license = 'MIT'
|
9
|
+
spec.homepage = 'https://github.com/MatthiasWinkelmann/cpuinfo'
|
10
|
+
spec.summary = 'A Ruby interface to system CPU info'
|
11
|
+
# spec.test_file = 'test/test.rb'
|
12
|
+
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
13
|
+
|
14
|
+
# spec.extra_rdoc_files = ['README.md']
|
15
|
+
|
16
|
+
spec.add_development_dependency('minitest', '~>5.11')
|
17
|
+
spec.add_development_dependency('rake', '~>12.3')
|
18
|
+
|
19
|
+
spec.description = <<-EOF
|
20
|
+
Very basic parsing of /proc/cpuinfo for now.
|
21
|
+
EOF
|
22
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module CPUInfo
|
2
|
+
|
3
|
+
class CPUS
|
4
|
+
|
5
|
+
def self.cpus
|
6
|
+
@@cpus ||= self.parse_cpuinfo
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.[](*parameters)
|
10
|
+
(self.cpus).public_send(:[], *parameters)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
self.cpus.map(&:to_s).join("\n\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.method_missing(sym, *parameters)
|
18
|
+
self.cpus.public_send(sym, *parameters) if self.cpus.respond_to? sym
|
19
|
+
end
|
20
|
+
|
21
|
+
class CPU
|
22
|
+
attr_reader :attributes
|
23
|
+
def initialize(cpuinfo)
|
24
|
+
@attributes = {}
|
25
|
+
cpuinfo.lines.each do |line|
|
26
|
+
matches = /^([^:]+):(.+)\n/.match(line)
|
27
|
+
next unless matches
|
28
|
+
attribute = matches[1].strip.gsub(/[^a-zA-Z_]/,'_')
|
29
|
+
value = matches[2].strip
|
30
|
+
if value =~ /^[0-9]+(\.0*)?$/
|
31
|
+
value = value.to_i
|
32
|
+
elsif value =~ /^[0-9\.]$/
|
33
|
+
value = value.to_f
|
34
|
+
elsif ['no', 'false'].include? value.downcase
|
35
|
+
value = false
|
36
|
+
elsif ['yes', 'true'].include? value.downcase
|
37
|
+
value = true
|
38
|
+
elsif attribute == 'flags'
|
39
|
+
value = CPUFlags.new value
|
40
|
+
end
|
41
|
+
@attributes[attribute.to_sym] = value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(sym, *parameters)
|
46
|
+
return @attributes[sym.to_sym] if parameters.empty? && @attributes.key?(sym.to_sym)
|
47
|
+
@attributes[:flags].public_send(sym, *parameters)
|
48
|
+
end
|
49
|
+
|
50
|
+
class CPUFlags
|
51
|
+
|
52
|
+
attr_reader :flags
|
53
|
+
|
54
|
+
def initialize(flagstring)
|
55
|
+
@flags = flagstring.split(' ')
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_missing(method, *params)
|
59
|
+
if method[-1] == '?'
|
60
|
+
return @flags.include? method[0..-2]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.read_cpuinfo
|
68
|
+
# IO.read("/proc/cpuinfo")
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.parse_cpuinfo
|
72
|
+
self.read_cpuinfo.split(/^processor:\w+\d+:\w+\n/).map {|cpu| CPU.new(cpu) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
processor : 0
|
2
|
+
vendor_id : GenuineIntel
|
3
|
+
cpu family : 6
|
4
|
+
model : 85
|
5
|
+
model name : Intel Xeon Processor (Skylake)
|
6
|
+
stepping : 4
|
7
|
+
microcode : 0x1
|
8
|
+
cpu MHz : 2100.000
|
9
|
+
cache size : 16384 KB
|
10
|
+
physical id : 0
|
11
|
+
siblings : 8
|
12
|
+
core id : 0
|
13
|
+
cpu cores : 8
|
14
|
+
apicid : 0
|
15
|
+
initial apicid : 0
|
16
|
+
fpu : yes
|
17
|
+
fpu_exception : yes
|
18
|
+
cpuid level : 13
|
19
|
+
wp : yes
|
20
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
21
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
22
|
+
bogomips : 4200.00
|
23
|
+
clflush size : 64
|
24
|
+
cache_alignment : 64
|
25
|
+
address sizes : 40 bits physical, 48 bits virtual
|
26
|
+
power management:
|
27
|
+
|
28
|
+
processor : 1
|
29
|
+
vendor_id : GenuineIntel
|
30
|
+
cpu family : 6
|
31
|
+
model : 85
|
32
|
+
model name : Intel Xeon Processor (Skylake)
|
33
|
+
stepping : 4
|
34
|
+
microcode : 0x1
|
35
|
+
cpu MHz : 2100.000
|
36
|
+
cache size : 16384 KB
|
37
|
+
physical id : 0
|
38
|
+
siblings : 8
|
39
|
+
core id : 1
|
40
|
+
cpu cores : 8
|
41
|
+
apicid : 1
|
42
|
+
initial apicid : 1
|
43
|
+
fpu : yes
|
44
|
+
fpu_exception : yes
|
45
|
+
cpuid level : 13
|
46
|
+
wp : yes
|
47
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
48
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
49
|
+
bogomips : 4200.00
|
50
|
+
clflush size : 64
|
51
|
+
cache_alignment : 64
|
52
|
+
address sizes : 40 bits physical, 48 bits virtual
|
53
|
+
power management:
|
54
|
+
|
55
|
+
processor : 2
|
56
|
+
vendor_id : GenuineIntel
|
57
|
+
cpu family : 6
|
58
|
+
model : 85
|
59
|
+
model name : Intel Xeon Processor (Skylake)
|
60
|
+
stepping : 4
|
61
|
+
microcode : 0x1
|
62
|
+
cpu MHz : 2100.000
|
63
|
+
cache size : 16384 KB
|
64
|
+
physical id : 0
|
65
|
+
siblings : 8
|
66
|
+
core id : 2
|
67
|
+
cpu cores : 8
|
68
|
+
apicid : 2
|
69
|
+
initial apicid : 2
|
70
|
+
fpu : yes
|
71
|
+
fpu_exception : yes
|
72
|
+
cpuid level : 13
|
73
|
+
wp : yes
|
74
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
75
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
76
|
+
bogomips : 4200.00
|
77
|
+
clflush size : 64
|
78
|
+
cache_alignment : 64
|
79
|
+
address sizes : 40 bits physical, 48 bits virtual
|
80
|
+
power management:
|
81
|
+
|
82
|
+
processor : 3
|
83
|
+
vendor_id : GenuineIntel
|
84
|
+
cpu family : 6
|
85
|
+
model : 85
|
86
|
+
model name : Intel Xeon Processor (Skylake)
|
87
|
+
stepping : 4
|
88
|
+
microcode : 0x1
|
89
|
+
cpu MHz : 2100.000
|
90
|
+
cache size : 16384 KB
|
91
|
+
physical id : 0
|
92
|
+
siblings : 8
|
93
|
+
core id : 3
|
94
|
+
cpu cores : 8
|
95
|
+
apicid : 3
|
96
|
+
initial apicid : 3
|
97
|
+
fpu : yes
|
98
|
+
fpu_exception : yes
|
99
|
+
cpuid level : 13
|
100
|
+
wp : yes
|
101
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
102
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
103
|
+
bogomips : 4200.00
|
104
|
+
clflush size : 64
|
105
|
+
cache_alignment : 64
|
106
|
+
address sizes : 40 bits physical, 48 bits virtual
|
107
|
+
power management:
|
108
|
+
|
109
|
+
processor : 4
|
110
|
+
vendor_id : GenuineIntel
|
111
|
+
cpu family : 6
|
112
|
+
model : 85
|
113
|
+
model name : Intel Xeon Processor (Skylake)
|
114
|
+
stepping : 4
|
115
|
+
microcode : 0x1
|
116
|
+
cpu MHz : 2100.000
|
117
|
+
cache size : 16384 KB
|
118
|
+
physical id : 0
|
119
|
+
siblings : 8
|
120
|
+
core id : 4
|
121
|
+
cpu cores : 8
|
122
|
+
apicid : 4
|
123
|
+
initial apicid : 4
|
124
|
+
fpu : yes
|
125
|
+
fpu_exception : yes
|
126
|
+
cpuid level : 13
|
127
|
+
wp : yes
|
128
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
129
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
130
|
+
bogomips : 4200.00
|
131
|
+
clflush size : 64
|
132
|
+
cache_alignment : 64
|
133
|
+
address sizes : 40 bits physical, 48 bits virtual
|
134
|
+
power management:
|
135
|
+
|
136
|
+
processor : 5
|
137
|
+
vendor_id : GenuineIntel
|
138
|
+
cpu family : 6
|
139
|
+
model : 85
|
140
|
+
model name : Intel Xeon Processor (Skylake)
|
141
|
+
stepping : 4
|
142
|
+
microcode : 0x1
|
143
|
+
cpu MHz : 2100.000
|
144
|
+
cache size : 16384 KB
|
145
|
+
physical id : 0
|
146
|
+
siblings : 8
|
147
|
+
core id : 5
|
148
|
+
cpu cores : 8
|
149
|
+
apicid : 5
|
150
|
+
initial apicid : 5
|
151
|
+
fpu : yes
|
152
|
+
fpu_exception : yes
|
153
|
+
cpuid level : 13
|
154
|
+
wp : yes
|
155
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
156
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
157
|
+
bogomips : 4200.00
|
158
|
+
clflush size : 64
|
159
|
+
cache_alignment : 64
|
160
|
+
address sizes : 40 bits physical, 48 bits virtual
|
161
|
+
power management:
|
162
|
+
|
163
|
+
processor : 6
|
164
|
+
vendor_id : GenuineIntel
|
165
|
+
cpu family : 6
|
166
|
+
model : 85
|
167
|
+
model name : Intel Xeon Processor (Skylake)
|
168
|
+
stepping : 4
|
169
|
+
microcode : 0x1
|
170
|
+
cpu MHz : 2100.000
|
171
|
+
cache size : 16384 KB
|
172
|
+
physical id : 0
|
173
|
+
siblings : 8
|
174
|
+
core id : 6
|
175
|
+
cpu cores : 8
|
176
|
+
apicid : 6
|
177
|
+
initial apicid : 6
|
178
|
+
fpu : yes
|
179
|
+
fpu_exception : yes
|
180
|
+
cpuid level : 13
|
181
|
+
wp : yes
|
182
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
183
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
184
|
+
bogomips : 4200.00
|
185
|
+
clflush size : 64
|
186
|
+
cache_alignment : 64
|
187
|
+
address sizes : 40 bits physical, 48 bits virtual
|
188
|
+
power management:
|
189
|
+
|
190
|
+
processor : 7
|
191
|
+
vendor_id : GenuineIntel
|
192
|
+
cpu family : 6
|
193
|
+
model : 85
|
194
|
+
model name : Intel Xeon Processor (Skylake)
|
195
|
+
stepping : 4
|
196
|
+
microcode : 0x1
|
197
|
+
cpu MHz : 2100.000
|
198
|
+
cache size : 16384 KB
|
199
|
+
physical id : 0
|
200
|
+
siblings : 8
|
201
|
+
core id : 7
|
202
|
+
cpu cores : 8
|
203
|
+
apicid : 7
|
204
|
+
initial apicid : 7
|
205
|
+
fpu : yes
|
206
|
+
fpu_exception : yes
|
207
|
+
cpuid level : 13
|
208
|
+
wp : yes
|
209
|
+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
|
210
|
+
bugs : cpu_meltdown spectre_v1 spectre_v2
|
211
|
+
bogomips : 4200.00
|
212
|
+
clflush size : 64
|
213
|
+
cache_alignment : 64
|
214
|
+
address sizes : 40 bits physical, 48 bits virtual
|
215
|
+
power management:
|
216
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require 'cpuinfo'
|
3
|
+
|
4
|
+
class TestCPUInfo < Minitest::Test
|
5
|
+
|
6
|
+
class CPUInfo::CPUS
|
7
|
+
def self.read_cpuinfo
|
8
|
+
File.read "test/fixtures/cpuinfo"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_readme
|
13
|
+
CPUInfo::CPUS.first.attributes.each do |name, value|
|
14
|
+
puts "%s : %s" % [name, value]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_number_of_cpus
|
19
|
+
assert_equal 1, CPUInfo::CPUS.size
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_number_of_attributes
|
23
|
+
assert_equal 25, CPUInfo::CPUS[0].attributes.keys.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_formats
|
27
|
+
puts CPUInfo::CPUS[0]
|
28
|
+
assert_kind_of Integer, CPUInfo::CPUS[0].core_id
|
29
|
+
end
|
30
|
+
end
|
data/lib/cp/cpu.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This is just a stub file that requires the appropriate version
|
2
|
+
# depending on which platform you're on.
|
3
|
+
require 'rbconfig'
|
4
|
+
|
5
|
+
module Sys
|
6
|
+
class CPU
|
7
|
+
# The version of the sys-cpu gem.
|
8
|
+
VERSION = '0.7.2'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
case RbConfig::CONFIG['host_os']
|
13
|
+
when /linux/i
|
14
|
+
require File.join(File.dirname(__FILE__), 'linux', 'sys', 'cpu')
|
15
|
+
when /windows|mswin|mingw|cygwin|dos/i
|
16
|
+
require File.join(File.dirname(__FILE__), 'windows', 'sys', 'cpu')
|
17
|
+
else
|
18
|
+
require File.join(File.dirname(__FILE__), 'unix', 'sys', 'cpu')
|
19
|
+
end
|
@@ -0,0 +1,372 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
module Sys
|
5
|
+
class CPU
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib FFI::Library::LIBC
|
8
|
+
|
9
|
+
# Error raised if any of the CPU methods fail.
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
CTL_HW = 6 # Generic hardware/cpu
|
13
|
+
|
14
|
+
HW_MACHINE = 1 # Machine class
|
15
|
+
HW_MODEL = 2 # Specific machine model
|
16
|
+
HW_NCPU = 3 # Number of CPU's
|
17
|
+
HW_CPU_FREQ = 15 # CPU frequency
|
18
|
+
|
19
|
+
if RbConfig::CONFIG['host_os'] =~ /bsd/
|
20
|
+
HW_MACHINE_ARCH = 11 # Machine architecture
|
21
|
+
else
|
22
|
+
HW_MACHINE_ARCH = 12 # Machine architecture
|
23
|
+
end
|
24
|
+
|
25
|
+
SI_MACHINE = 5
|
26
|
+
SI_ARCHITECTURE = 6
|
27
|
+
SC_NPROCESSORS_ONLN = 15
|
28
|
+
|
29
|
+
P_OFFLINE = 1
|
30
|
+
P_ONLINE = 2
|
31
|
+
P_FAULTED = 4
|
32
|
+
P_POWEROFF = 5
|
33
|
+
P_NOINTR = 6
|
34
|
+
P_SPARE = 7
|
35
|
+
|
36
|
+
CPU_ARCH_ABI64 = 0x01000000
|
37
|
+
CPU_TYPE_X86 = 7
|
38
|
+
CPU_TYPE_X86_64 = (CPU_TYPE_X86 | CPU_ARCH_ABI64)
|
39
|
+
CPU_TYPE_SPARC = 14
|
40
|
+
CPU_TYPE_POWERPC = 18
|
41
|
+
CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64
|
42
|
+
|
43
|
+
begin
|
44
|
+
attach_function(
|
45
|
+
:sysctl,
|
46
|
+
[:pointer, :uint, :pointer, :pointer, :pointer, :size_t],
|
47
|
+
:int
|
48
|
+
)
|
49
|
+
private_class_method :sysctl
|
50
|
+
rescue FFI::NotFoundError
|
51
|
+
# Do nothing, not supported on this platform.
|
52
|
+
end
|
53
|
+
|
54
|
+
begin
|
55
|
+
attach_function(
|
56
|
+
:sysctlbyname,
|
57
|
+
[:string, :pointer, :pointer, :pointer, :size_t],
|
58
|
+
:int
|
59
|
+
)
|
60
|
+
private_class_method :sysctlbyname
|
61
|
+
rescue FFI::NotFoundError
|
62
|
+
# Do nothing, not supported on this platform.
|
63
|
+
end
|
64
|
+
|
65
|
+
# Solaris
|
66
|
+
begin
|
67
|
+
attach_function :getloadavg, [:pointer, :int], :int
|
68
|
+
attach_function :processor_info, [:int, :pointer], :int
|
69
|
+
attach_function :sysconf, [:int], :long
|
70
|
+
attach_function :sysinfo, [:int, :pointer, :long], :int
|
71
|
+
|
72
|
+
private_class_method :getloadavg
|
73
|
+
private_class_method :processor_info
|
74
|
+
private_class_method :sysconf
|
75
|
+
private_class_method :sysinfo
|
76
|
+
rescue FFI::NotFoundError
|
77
|
+
# Do nothing, not supported on this platform.
|
78
|
+
end
|
79
|
+
|
80
|
+
class ProcInfo < FFI::Struct
|
81
|
+
layout(
|
82
|
+
:pi_state, :int,
|
83
|
+
:pi_processor_type, [:char, 16],
|
84
|
+
:pi_fputypes, [:char, 32],
|
85
|
+
:pi_clock, :int
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns the cpu's architecture. On most systems this will be identical
|
90
|
+
# to the CPU.machine method. On OpenBSD it will be identical to the CPU.model
|
91
|
+
# method.
|
92
|
+
#
|
93
|
+
def self.architecture
|
94
|
+
if respond_to?(:sysinfo, true)
|
95
|
+
buf = 0.chr * 257
|
96
|
+
|
97
|
+
if sysinfo(SI_ARCHITECTURE, buf, buf.size) < 0
|
98
|
+
raise Error, "sysinfo function failed"
|
99
|
+
end
|
100
|
+
|
101
|
+
buf.strip
|
102
|
+
elsif respond_to?(:sysctlbyname, true)
|
103
|
+
optr = FFI::MemoryPointer.new(:char, 256)
|
104
|
+
size = FFI::MemoryPointer.new(:size_t)
|
105
|
+
|
106
|
+
size.write_int(optr.size)
|
107
|
+
|
108
|
+
if RbConfig::CONFIG['host_os'] =~ /darwin/i
|
109
|
+
name = 'hw.machine'
|
110
|
+
else
|
111
|
+
name = 'hw.machine_arch'
|
112
|
+
end
|
113
|
+
|
114
|
+
if sysctlbyname(name, optr, size, nil, 0) < 0
|
115
|
+
raise Error, "sysctlbyname function failed"
|
116
|
+
end
|
117
|
+
|
118
|
+
optr.read_string
|
119
|
+
else
|
120
|
+
buf = 0.chr * 64
|
121
|
+
mib = FFI::MemoryPointer.new(:int, 2)
|
122
|
+
size = FFI::MemoryPointer.new(:long, 1)
|
123
|
+
|
124
|
+
mib.write_array_of_int([CTL_HW, HW_MACHINE_ARCH])
|
125
|
+
size.write_int(buf.size)
|
126
|
+
|
127
|
+
if sysctl(mib, 2, buf, size, nil, 0) < 0
|
128
|
+
raise Error, "sysctl function failed"
|
129
|
+
end
|
130
|
+
|
131
|
+
buf.strip
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns the number of cpu's on your system. Note that each core on
|
136
|
+
# multi-core systems are counted as a cpu, e.g. one dual core cpu would
|
137
|
+
# return 2, not 1.
|
138
|
+
#
|
139
|
+
def self.num_cpu
|
140
|
+
if respond_to?(:sysctlbyname, true)
|
141
|
+
optr = FFI::MemoryPointer.new(:long)
|
142
|
+
size = FFI::MemoryPointer.new(:size_t)
|
143
|
+
|
144
|
+
size.write_long(optr.size)
|
145
|
+
|
146
|
+
if sysctlbyname('hw.ncpu', optr, size, nil, 0) < 0
|
147
|
+
raise Error, "sysctlbyname failed"
|
148
|
+
end
|
149
|
+
|
150
|
+
optr.read_long
|
151
|
+
elsif respond_to?(:sysconf, true)
|
152
|
+
num = sysconf(SC_NPROCESSORS_ONLN)
|
153
|
+
|
154
|
+
if num < 0
|
155
|
+
raise Error, "sysconf function failed"
|
156
|
+
end
|
157
|
+
|
158
|
+
num
|
159
|
+
else
|
160
|
+
buf = 0.chr * 4
|
161
|
+
mib = FFI::MemoryPointer.new(:int, 2)
|
162
|
+
size = FFI::MemoryPointer.new(:long, 1)
|
163
|
+
|
164
|
+
mib.write_array_of_int([CTL_HW, HW_NCPU])
|
165
|
+
size.write_int(buf.size)
|
166
|
+
|
167
|
+
if sysctl(mib, 2, buf, size, nil, 0) < 0
|
168
|
+
raise Error, "sysctl function failed"
|
169
|
+
end
|
170
|
+
|
171
|
+
buf.strip.unpack("C").first
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns the cpu's class type. On most systems this will be identical
|
176
|
+
# to the CPU.architecture method. On OpenBSD it will be identical to the
|
177
|
+
# CPU.model method.
|
178
|
+
#
|
179
|
+
def self.machine
|
180
|
+
if respond_to?(:sysctl, true)
|
181
|
+
buf = 0.chr * 32
|
182
|
+
mib = FFI::MemoryPointer.new(:int, 2)
|
183
|
+
size = FFI::MemoryPointer.new(:long, 1)
|
184
|
+
|
185
|
+
mib.write_array_of_int([CTL_HW, HW_MACHINE])
|
186
|
+
size.write_int(buf.size)
|
187
|
+
|
188
|
+
if sysctl(mib, 2, buf, size, nil, 0) < 0
|
189
|
+
raise Error, "sysctl function failed"
|
190
|
+
end
|
191
|
+
|
192
|
+
buf.strip
|
193
|
+
else
|
194
|
+
buf = 0.chr * 257
|
195
|
+
|
196
|
+
if sysinfo(SI_MACHINE, buf, buf.size) < 0
|
197
|
+
raise Error, "sysinfo function failed"
|
198
|
+
end
|
199
|
+
|
200
|
+
buf.strip
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns a string indicating the cpu model.
|
205
|
+
#
|
206
|
+
def self.model
|
207
|
+
if RbConfig::CONFIG['host_os'] =~ /darwin/i
|
208
|
+
ptr = FFI::MemoryPointer.new(:long)
|
209
|
+
size = FFI::MemoryPointer.new(:size_t)
|
210
|
+
|
211
|
+
size.write_long(ptr.size)
|
212
|
+
|
213
|
+
if sysctlbyname("hw.cputype", ptr, size, nil, 0) < 0
|
214
|
+
raise "sysctlbyname function failed"
|
215
|
+
end
|
216
|
+
|
217
|
+
case ptr.read_long
|
218
|
+
when CPU_TYPE_X86, CPU_TYPE_X86_64
|
219
|
+
"Intel"
|
220
|
+
when CPU_TYPE_SPARC
|
221
|
+
"Sparc"
|
222
|
+
when CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64
|
223
|
+
"PowerPC"
|
224
|
+
else
|
225
|
+
"Unknown"
|
226
|
+
end
|
227
|
+
else
|
228
|
+
if respond_to?(:sysctl, true)
|
229
|
+
buf = 0.chr * 64
|
230
|
+
mib = FFI::MemoryPointer.new(:int, 2)
|
231
|
+
size = FFI::MemoryPointer.new(:long, 1)
|
232
|
+
|
233
|
+
mib.write_array_of_int([CTL_HW, HW_MODEL])
|
234
|
+
size.write_int(buf.size)
|
235
|
+
|
236
|
+
if sysctl(mib, 2, buf, size, nil, 0) < 0
|
237
|
+
raise Error, "sysctl function failed"
|
238
|
+
end
|
239
|
+
|
240
|
+
buf.strip
|
241
|
+
else
|
242
|
+
pinfo = ProcInfo.new
|
243
|
+
|
244
|
+
# Some systems start at 0, some at 1
|
245
|
+
if processor_info(0, pinfo) < 0
|
246
|
+
if processor_info(1, pinfo) < 0
|
247
|
+
raise Error, "process_info function failed"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
pinfo[:pi_processor_type].to_s
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Returns an integer indicating the speed of the CPU.
|
257
|
+
#
|
258
|
+
def self.freq
|
259
|
+
if respond_to?(:sysctlbyname, true)
|
260
|
+
optr = FFI::MemoryPointer.new(:long)
|
261
|
+
size = FFI::MemoryPointer.new(:size_t)
|
262
|
+
|
263
|
+
size.write_long(optr.size)
|
264
|
+
|
265
|
+
if RbConfig::CONFIG['host_os'] =~ /bsd/i
|
266
|
+
name = 'hw.clockrate'
|
267
|
+
else
|
268
|
+
name = 'hw.cpufrequency'
|
269
|
+
end
|
270
|
+
|
271
|
+
if sysctlbyname(name, optr, size, nil, 0) < 0
|
272
|
+
raise Error, "sysctlbyname failed"
|
273
|
+
end
|
274
|
+
|
275
|
+
if RbConfig::CONFIG['host_os'] =~ /darwin/i
|
276
|
+
optr.read_long / 1000000
|
277
|
+
else
|
278
|
+
optr.read_long
|
279
|
+
end
|
280
|
+
elsif respond_to?(:sysctl, true)
|
281
|
+
buf = 0.chr * 16
|
282
|
+
mib = FFI::MemoryPointer.new(:int, 2)
|
283
|
+
size = FFI::MemoryPointer.new(:long, 1)
|
284
|
+
|
285
|
+
mib.write_array_of_int([CTL_HW, HW_CPU_FREQ])
|
286
|
+
size.write_int(buf.size)
|
287
|
+
|
288
|
+
if sysctl(mib, 2, buf, size, nil, 0) < 0
|
289
|
+
raise Error, "sysctl function failed"
|
290
|
+
end
|
291
|
+
|
292
|
+
buf.unpack("I*").first / 1000000
|
293
|
+
else
|
294
|
+
pinfo = ProcInfo.new
|
295
|
+
|
296
|
+
# Some systems start at 0, some at 1
|
297
|
+
if processor_info(0, pinfo) < 0
|
298
|
+
if processor_info(1, pinfo) < 0
|
299
|
+
raise Error, "process_info function failed"
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
pinfo[:pi_clock].to_i
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# Returns an array of three floats indicating the 1, 5 and 15 minute load
|
308
|
+
# average.
|
309
|
+
#
|
310
|
+
def self.load_avg
|
311
|
+
if respond_to?(:getloadavg, true)
|
312
|
+
loadavg = FFI::MemoryPointer.new(:double, 3)
|
313
|
+
|
314
|
+
if getloadavg(loadavg, loadavg.size) < 0
|
315
|
+
raise Error, "getloadavg function failed"
|
316
|
+
end
|
317
|
+
|
318
|
+
loadavg.get_array_of_double(0, 3)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# Returns the floating point processor type.
|
323
|
+
#
|
324
|
+
# Not supported on all platforms.
|
325
|
+
#
|
326
|
+
def self.fpu_type
|
327
|
+
raise NoMethodError unless respond_to?(:processor_info, true)
|
328
|
+
|
329
|
+
pinfo = ProcInfo.new
|
330
|
+
|
331
|
+
if processor_info(0, pinfo) < 0
|
332
|
+
if processor_info(1, pinfo) < 0
|
333
|
+
raise Error, "process_info function failed"
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
pinfo[:pi_fputypes].to_s
|
338
|
+
end
|
339
|
+
|
340
|
+
# Returns the current state of processor +num+, or 0 if no number is
|
341
|
+
# specified.
|
342
|
+
#
|
343
|
+
# Not supported on all platforms.
|
344
|
+
#
|
345
|
+
def self.state(num = 0)
|
346
|
+
raise NoMethodError unless respond_to?(:processor_info, true)
|
347
|
+
|
348
|
+
pinfo = ProcInfo.new
|
349
|
+
|
350
|
+
if processor_info(num, pinfo) < 0
|
351
|
+
raise Error, "process_info function failed"
|
352
|
+
end
|
353
|
+
|
354
|
+
case pinfo[:pi_state].to_i
|
355
|
+
when P_ONLINE
|
356
|
+
"online"
|
357
|
+
when P_OFFLINE
|
358
|
+
"offline"
|
359
|
+
when P_POWEROFF
|
360
|
+
"poweroff"
|
361
|
+
when P_FAULTED
|
362
|
+
"faulted"
|
363
|
+
when P_NOINTR
|
364
|
+
"nointr"
|
365
|
+
when P_SPARE
|
366
|
+
"spare"
|
367
|
+
else
|
368
|
+
"unknown"
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|