sys-memory 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: eb58ad679007156871e4cc8b3906546c10a634a04537b69b6021c9b83a7be18b
4
+ data.tar.gz: 464f3d02c1e96915808772ac2d66652d62c956a05f03054e246af893e8316a64
5
+ SHA512:
6
+ metadata.gz: d5125dcc2e250ba8d4e4e513901321b397fd473f1934e5c7d3155bdda00ee5c75cd51d2e90e2cd7b7797d97279699237a3b574004f00f63a4bb2bb2788ed9f3a
7
+ data.tar.gz: 472f13e448c5ce16c7750a88f93e65283b22fce862bbe2c010210fbca2be2b0465bdd7c82dae4c08457773f026da10ccd5ac3157cf4c5c334c1daeb8f77dca42
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ ^Rt% Ǟ� �ѿx �Z��F�]�RəP�M'ӌ��'!Z��A��6����ʣ����8B*,��J��pÍ�h�?{
2
+ �욶��ay��Otm�ʓ�Ę�<���B~�d���[��
3
+ Ez����TM����X��9W��&$6BN����I�韥o�"v&�=-V���Xcf<��"$����ϟ��n������n��#��I$@���������B��Y��m!�Ԡ!la�h��+S��6U�d�"���1tM
data.tar.gz.sig ADDED
Binary file
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,177 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ ## Description
2
+ A Ruby interface for getting memory information.
3
+
4
+ ## Supported Platforms
5
+ * Linux
6
+ * Windows
7
+ * OSX
8
+
9
+ ## Installation
10
+ `gem install sys-memory`
11
+
12
+ ## Synopsis
13
+ ```
14
+ require 'sys-memory'
15
+
16
+ p Sys::Memory.memory # Hash of all information
17
+
18
+ p Sys::Memory.total # Total memory, no swap
19
+ p Sys::Memory.total(extended: true) # Total memory, include swap
20
+ ```
21
+
22
+ There's also the `free`, `used` and `load` module methods.
23
+
24
+ ## Adding the trusted cert
25
+ `gem cert --add <(curl -Ls https://raw.githubusercontent.com/djberg96/sys-memory/ffi/certs/djberg96_pub.pem)`
26
+
27
+ ## Notes
28
+ I realize there are some philosophical differences about what constitutes
29
+ "available memory". I've tried to accomodate both of the approaches to it
30
+ that I saw debated online. In short, you can choose to include swap memory
31
+ as part of memory calculations or not as you see fit via an optional argument.
32
+
33
+ You can also just use `Sys::Memory.memory` and collate the various hash data
34
+ pieces as you see fit.
35
+
36
+ ## Known Bugs
37
+ None that I'm aware of. Please report bugs on the project page at:
38
+
39
+ https://github.com/djberg96/sys-cpu
40
+
41
+ ## License
42
+ Apache-2.0
43
+
44
+ ## Copyright
45
+ (C) 2021 Daniel J. Berger, All Rights Reserved
46
+
47
+ ## Warranty
48
+ This package is provided "as is" and without any express or
49
+ implied warranties, including, without limitation, the implied
50
+ warranties of merchantability and fitness for a particular purpose.
51
+
52
+ ## Author
53
+ Daniel J. Berger
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rspec/core/rake_task'
4
+
5
+ CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx', '**/*.lock')
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ namespace 'gem' do
10
+ desc "Create the sys-memory gem"
11
+ task :create => [:clean] do
12
+ require 'rubygems/package'
13
+ spec = Gem::Specification.load('sys-memory.gemspec')
14
+ spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
15
+ Gem::Package.build(spec)
16
+ end
17
+
18
+ desc "Install the sys-memory gem"
19
+ task :install => [:create] do
20
+ file = Dir["*.gem"].first
21
+ sh "gem install -l #{file}"
22
+ end
23
+ end
24
+
25
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
3
+ cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
4
+ MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
5
+ ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
6
+ bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
7
+ A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
8
+ u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
9
+ 75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
10
+ 6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
11
+ iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
12
+ ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
13
+ 74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
14
+ 058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
15
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
16
+ AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
17
+ YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
18
+ /3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
19
+ h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
20
+ 6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
21
+ ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
22
+ 1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
23
+ DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
24
+ ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
25
+ WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
26
+ -----END CERTIFICATE-----
data/lib/sys-memory.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'sys/memory'
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sys
4
+ module Memory
5
+ MEMORY_FILE = '/proc/meminfo'
6
+ MEMINFO_REGEX = /(.*)?:\s+?(\d+)/.freeze
7
+
8
+ private_constant :MEMORY_FILE
9
+ private_constant :MEMINFO_REGEX
10
+
11
+ # Obtain detailed memory information about your host in the form of a hash.
12
+ # Note that the exact nature of this hash is largely dependent on your
13
+ # operating system.
14
+ #
15
+ def memory
16
+ hash = {}
17
+
18
+ IO.foreach(MEMORY_FILE) do |line|
19
+ key, value = MEMINFO_REGEX.match(line.chomp).captures
20
+ hash[key] = value.to_i
21
+ end
22
+
23
+ hash
24
+ end
25
+
26
+ # Total memory in bytes. By default this is only physical memory, but
27
+ # if the +extended+ option is set to true, then swap memory is included
28
+ # as part of the total.
29
+ #
30
+ def total(extended: false)
31
+ hash = memory
32
+ extended ? (hash['MemTotal'] + hash['SwapTotal']) * 1024 : hash['MemTotal'] * 1024
33
+ end
34
+
35
+ # The memory currently available, in bytes. By default this is only
36
+ # physical memory, but if the +extended+ option is set to true, then free
37
+ # swap memory is also included.
38
+ #
39
+ def free(extended: false)
40
+ hash = memory
41
+ extended ? (hash['MemFree'] + hash['SwapFree']) * 1024 : hash['MemFree'] * 1024
42
+ end
43
+
44
+ # The memory, in bytes, currently in use. By default this is only
45
+ # physical memory, but if the +extended+ option is set to true then
46
+ # swap is included in the calculation.
47
+ #
48
+ def used(extended: false)
49
+ hash = memory
50
+ (total(extended: extended) - free(extended: extended) - hash['Buffers'] - hash['Cached'] - hash['Slab']) * 1024
51
+ end
52
+
53
+ # A number between 0 and 100 that specifies the approximate percentage of
54
+ # memory that is in use. If the +extended+ option is set to true then
55
+ # swap memory is included in the calculation.
56
+ #
57
+ def load(extended: false)
58
+ (used(extended: extended) / total(extended: extended).to_f).round(2) * 100
59
+ end
60
+
61
+ module_function :memory, :total, :free, :used, :load
62
+ end
63
+ end
data/lib/sys/memory.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rbconfig'
4
+ require_relative 'version'
5
+
6
+ case RbConfig::CONFIG['host_os']
7
+ when /linux/i
8
+ require_relative 'linux/memory'
9
+ when /darwin|macos/i
10
+ require_relative 'osx/memory'
11
+ when /windows|win32|mingw/i
12
+ require_relative 'windows/memory'
13
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ # The Sys module serves only as a namespace.
6
+ module Sys
7
+ # The Memory module is a house for memory related singleton methods that don't require state.
8
+ module Memory
9
+ extend FFI::Library
10
+ ffi_lib FFI::Library::LIBC
11
+
12
+ HOST_VM_INFO64 = 4
13
+ HOST_VM_INFO64_COUNT = 38
14
+
15
+ private_constant :HOST_VM_INFO64
16
+ private_constant :HOST_VM_INFO64_COUNT
17
+
18
+ attach_function :sysctlbyname, %i[string pointer pointer pointer size_t], :int
19
+ attach_function :host_page_size, %i[pointer pointer], :int
20
+ attach_function :host_statistics64, %i[pointer int pointer pointer], :int
21
+ attach_function :mach_host_self, [], :pointer
22
+
23
+ private_class_method :sysctlbyname, :host_page_size
24
+ private_class_method :host_statistics64, :mach_host_self
25
+
26
+ typedef :uint, :natural_t
27
+
28
+ class Swap < FFI::Struct
29
+ layout(
30
+ :xsu_total, :uint64_t,
31
+ :xsu_avail, :uint64_t,
32
+ :xsu_used, :uint64_t,
33
+ :xsu_pagesize, :uint32_t,
34
+ :xsu_encrypted, :bool
35
+ )
36
+ end
37
+
38
+ private_constant :Swap
39
+
40
+ class VmStat < FFI::Struct
41
+ layout(
42
+ :free_count, :natural_t, # of pages free
43
+ :active_count, :natural_t, # of pages active
44
+ :inactive_count, :natural_t, # of pages inactive
45
+ :wire_count, :natural_t, # of pages wired down
46
+ :zero_fill_count, :uint64_t, # of zero fill pages
47
+ :reactivations, :uint64_t, # of pages reactivated
48
+ :pageins, :uint64_t, # of pageins
49
+ :pageouts, :uint64_t, # of pageouts
50
+ :faults, :uint64_t, # of faults
51
+ :cow_faults, :uint64_t, # of copy-on-writes
52
+ :lookups, :uint64_t, # object cache lookups
53
+ :hits, :uint64_t, # object cache hits
54
+ :purges, :uint64_t, # of pages purged
55
+ :purgeable_count, :natural_t, # of pages purgeable
56
+ :speculative_count, :natural_t, # of pages speculative
57
+ :decompressions, :uint64_t, # of pages decompressed
58
+ :compressions, :uint64_t, # of pages compressed
59
+ :swapins, :uint64_t, # of pages swapped in (via compression segments)
60
+ :swapouts, :uint64_t, # of pages swapped out (via compression segments)
61
+ :compressor_page_count, :natural_t, # of pages used by the compressed pager to hold all the compressed data
62
+ :throttled_count, :natural_t, # of pages throttled
63
+ :external_page_count, :natural_t, # of pages that are file-backed (non-swap)
64
+ :internal_page_count, :natural_t, # of pages that are anonymous
65
+ :total_uncompressed_pages_in_compressor, :uint64_t # of pages (uncompressed) held within the compressor
66
+ )
67
+ end
68
+
69
+ private_constant :VmStat
70
+
71
+ # Obtain detailed memory information about your host in the form of a hash.
72
+ # Note that the exact nature of this hash is largely dependent on your
73
+ # operating system.
74
+ #
75
+ def memory
76
+ hash = {}
77
+ page_size = 4096 # Possibly changed later
78
+
79
+ begin
80
+ optr = FFI::MemoryPointer.new(:uint64_t)
81
+ size = FFI::MemoryPointer.new(:size_t)
82
+ size.write_int(optr.size)
83
+
84
+ if sysctlbyname('hw.memsize', optr, size, nil, 0) < 0
85
+ raise SystemCallError.new('sysctlbyname', FFI.errno)
86
+ end
87
+
88
+ hash[:total] = optr.read_uint64
89
+ ensure
90
+ optr.free if optr && !optr.null?
91
+ size.clear
92
+ end
93
+
94
+ begin
95
+ swap = Swap.new
96
+ size.write_int(swap.size)
97
+
98
+ if sysctlbyname('vm.swapusage', swap, size, nil, 0) < 0
99
+ raise SystemCallError.new('sysctlbyname', FFI.errno)
100
+ end
101
+
102
+ hash[:swap_total] = swap[:xsu_total]
103
+ hash[:swap_available] = swap[:xsu_avail]
104
+ hash[:swap_used] = swap[:xsu_used]
105
+ page_size = swap[:xsu_pagesize]
106
+ ensure
107
+ size.free if size && !size.null?
108
+ end
109
+
110
+ host_self = mach_host_self()
111
+ vmstat = VmStat.new
112
+ count = FFI::MemoryPointer.new(:size_t)
113
+ count.write_int(vmstat.size)
114
+
115
+ rv = host_statistics64(host_self, HOST_VM_INFO64, vmstat, count)
116
+ raise SystemCallError.new('host_statistics64', rv) if rv != 0
117
+
118
+ hash[:free] = vmstat[:free_count] * page_size
119
+ hash[:active] = vmstat[:active_count] * page_size
120
+ hash[:inactive] = vmstat[:inactive_count] * page_size
121
+ hash[:speculative] = vmstat[:speculative_count] * page_size
122
+ hash[:wire] = vmstat[:wire_count] * page_size
123
+ hash[:compressed] = vmstat[:compressor_page_count] * page_size
124
+
125
+ hash
126
+ ensure
127
+ count.free if count && !count.null?
128
+ end
129
+
130
+ # Total memory in bytes. By default this is only physical memory, but
131
+ # if the +extended+ option is set to true, then swap memory is included as
132
+ # part of the total.
133
+ #
134
+ def total(extended: false)
135
+ hash = memory
136
+ extended ? hash[:total] + hash[:swap_total] : hash[:total]
137
+ end
138
+
139
+ # The memory currently available, in bytes. By default this is only
140
+ # physical memory, but if the +extended+ option is set to true, then free
141
+ # swap memory is also included.
142
+ #
143
+ def free(extended: false)
144
+ hash = memory
145
+ extended ? hash[:free] + hash[:swap_available] : hash[:free]
146
+ end
147
+
148
+ # The memory, in bytes, currently in use. By default this is only
149
+ # physical memory, but if the +extended+ option is set to true then
150
+ # swap is included in the calculation.
151
+ #
152
+ def used(extended: false)
153
+ total(extended: extended) - free(extended: extended)
154
+ end
155
+
156
+ # A number between 0 and 100 that specifies the approximate percentage of
157
+ # memory that is in use. If the +extended+ option is set to true then
158
+ # swap memory is included in the calculation.
159
+ #
160
+ def load(extended: false)
161
+ (used(extended: extended) / total(extended: extended).to_f).round(2) * 100
162
+ end
163
+
164
+ module_function :memory, :total, :free, :load, :used
165
+ end
166
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sys
4
+ module Memory
5
+ # The version of the sys-memory library.
6
+ VERSION = '0.1.0'
7
+ end
8
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sys
4
+ module Memory
5
+ require 'ffi'
6
+ extend FFI::Library
7
+ ffi_lib 'kernel32'
8
+
9
+ private
10
+
11
+ typedef :uint32, :dword
12
+ typedef :uint64, :dwordlong
13
+
14
+ class MemoryStatusEx < FFI::Struct
15
+ layout(
16
+ :dwLength, :dword,
17
+ :dwMemoryLoad, :dword,
18
+ :ullTotalPhys, :dwordlong,
19
+ :ullAvailPhys, :dwordlong,
20
+ :ullTotalPageFile, :dwordlong,
21
+ :ullAvailPageFile, :dwordlong,
22
+ :ullTotalVirtual, :dwordlong,
23
+ :ullAvailVirtual, :dwordlong,
24
+ :ullAvailExtendedVirtual, :dwordlong
25
+ )
26
+ end
27
+
28
+ attach_function :GlobalMemoryStatusEx, [MemoryStatusEx], :bool
29
+
30
+ ffi_lib 'psapi'
31
+
32
+ class PerformanceInformation < FFI::Struct
33
+ layout(
34
+ :cb, :dword,
35
+ :CommitTotal, :size_t,
36
+ :CommitLimit, :size_t,
37
+ :CommitPeak, :size_t,
38
+ :PhysicalTotal, :size_t,
39
+ :PhysicalAvailable, :size_t,
40
+ :SystemCache, :size_t,
41
+ :KernelTotal, :size_t,
42
+ :KernelPaged, :size_t,
43
+ :KernelNonpaged, :size_t,
44
+ :PageSize, :size_t,
45
+ :HandleCount, :dword,
46
+ :ProcessCount, :dword,
47
+ :ThreadCount, :dword
48
+ )
49
+ end
50
+
51
+ attach_function :GetPerformanceInfo, [PerformanceInformation, :dword], :bool
52
+
53
+ public
54
+
55
+ # Obtain detailed memory information about your host in the form of a hash.
56
+ # Note that the exact nature of this hash is largely dependent on your
57
+ # operating system.
58
+ #
59
+ def memory
60
+ struct = MemoryStatusEx.new
61
+ struct[:dwLength] = struct.size
62
+
63
+ unless GlobalMemoryStatusEx(struct)
64
+ raise SystemCallError.new('GlobalMemoryStatusEx', FFI.errno)
65
+ end
66
+
67
+ hash = {}
68
+
69
+ struct.members.each do |member|
70
+ key = member.to_s.sub(/^ull|^dw/, '')
71
+ hash[key] = struct[member]
72
+ end
73
+
74
+ hash.delete('Length')
75
+
76
+ perf = PerformanceInformation.new
77
+
78
+ unless GetPerformanceInfo(perf, perf.size)
79
+ raise SystemCallError.new('GetPerformanceInfo', FFI.errno)
80
+ end
81
+
82
+ perf.members.each do |member|
83
+ key = member.to_s
84
+ hash[key] = perf[member]
85
+ end
86
+
87
+ hash.delete('cb')
88
+
89
+ hash
90
+ end
91
+
92
+ # Total memory in bytes. By default this is only physical memory, but
93
+ # if the +extended+ option is set to true then swap (pagefile) memory is
94
+ # included as part of the total.
95
+ #
96
+ def total(extended: false)
97
+ hash = memory
98
+ extended ? hash['TotalPhys'] + hash['TotalPageFile'] : hash['TotalPhys']
99
+ end
100
+
101
+ # The physical memory currently available, in bytes. This is the amount of
102
+ # physical memory that can be immediately reused without having to write
103
+ # its contents to disk first.
104
+ #
105
+ # If the +extended+ option is set to true then available swap (pagefile)
106
+ # memory is included as part of the total.
107
+ #
108
+ def free(extended: false)
109
+ hash = memory
110
+ extended ? hash['AvailPhys'] + hash['AvailPageFile'] : hash['AvailPhys']
111
+ end
112
+
113
+ # The memory, in bytes, currently in use. By default this is only
114
+ # physical memory, but if the +extended+ option is set to true then
115
+ # swap (pagefile) is included in the calculation.
116
+ #
117
+ def used(extended: false)
118
+ total(extended: extended) - free(extended: extended)
119
+ end
120
+
121
+ # A number between 0 and 100 that specifies the approximate percentage of
122
+ # physical memory that is in use.
123
+ #
124
+ # If the +extended+ option is set to true then swap memory is included in
125
+ # the calculation.
126
+ #
127
+ def load(extended: false)
128
+ memory['MemoryLoad']
129
+ end
130
+
131
+ module_function :memory, :total, :free, :load, :used
132
+ end
133
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_support/core_ext/numeric/bytes'
2
+ require 'sys-memory'
3
+
4
+ RSpec.describe Sys::Memory do
5
+ context 'Sys::Memory::VERSION' do
6
+ example 'the version constant is set to the expected value' do
7
+ expect(described_class::VERSION).to eq('0.1.0')
8
+ expect(described_class::VERSION).to be_frozen
9
+ end
10
+ end
11
+
12
+ context 'Sys::Memory.memory' do
13
+ example 'the memory singleton method is defined' do
14
+ expect(described_class).to respond_to(:memory)
15
+ end
16
+
17
+ example 'the memory singleton method returns the expected hash' do
18
+ expect(described_class.memory).to be_kind_of(Hash)
19
+ expect(described_class.memory.size).to be > 4
20
+ end
21
+ end
22
+
23
+ context 'Sys::Memory.total' do
24
+ example 'the total singleton method is defined' do
25
+ expect(described_class).to respond_to(:total)
26
+ end
27
+
28
+ example 'the total singleton method returns a sane value' do
29
+ expect(described_class.total).to be > 64.megabytes
30
+ end
31
+ end
32
+
33
+ context 'Sys::Memory.free' do
34
+ example 'the free singleton method is defined' do
35
+ expect(described_class).to respond_to(:free)
36
+ end
37
+
38
+ example 'the free singleton method returns a sane value' do
39
+ expect(described_class.free).to be > 64.megabytes
40
+ end
41
+ end
42
+
43
+ context 'Sys::Memory.used' do
44
+ example 'the used singleton method is defined' do
45
+ expect(described_class).to respond_to(:used)
46
+ end
47
+
48
+ example 'the used singleton method returns a sane value' do
49
+ expect(described_class.used).to be > 64.megabytes
50
+ end
51
+ end
52
+
53
+ context 'Sys::Memory.load' do
54
+ example 'the load singleton method is defined' do
55
+ expect(described_class).to respond_to(:load)
56
+ end
57
+
58
+ example 'the load singleton method returns a sane value' do
59
+ expect(described_class.load).to be > 1
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'sys-memory'
5
+ spec.version = '0.1.0'
6
+ spec.author = 'Daniel J. Berger'
7
+ spec.email = 'djberg96@gmail.com'
8
+ spec.license = 'Apache-2.0'
9
+ spec.homepage = 'https://github.com/djberg96/sys-memory'
10
+ spec.summary = 'A Ruby interface for providing memory information'
11
+ spec.test_file = 'spec/sys_memory_spec.rb'
12
+ spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
13
+ spec.cert_chain = ['certs/djberg96_pub.pem']
14
+
15
+ spec.extra_rdoc_files = Dir['*.rdoc']
16
+
17
+ spec.add_dependency('ffi', "~> 1.1")
18
+ spec.add_dependency('activesupport', "~> 6.0")
19
+ spec.add_development_dependency('rspec', "~> 3.9")
20
+ spec.add_development_dependency('rake', "~> 13.0")
21
+
22
+ spec.metadata = {
23
+ 'homepage_uri' => 'https://github.com/djberg96/sys-memory',
24
+ 'bug_tracker_uri' => 'https://github.com/djberg96/sys-memory/issues',
25
+ 'changelog_uri' => 'https://github.com/djberg96/sys-memory/blob/main/CHANGES.md',
26
+ 'documentation_uri' => 'https://github.com/djberg96/sys-memory/wiki',
27
+ 'source_code_uri' => 'https://github.com/djberg96/sys-memory',
28
+ 'wiki_uri' => 'https://github.com/djberg96/sys-memory/wiki'
29
+ }
30
+
31
+ spec.description = <<-EOF
32
+ The sys-memory library provides an interface for gathering information
33
+ about your system's memory. Information includes total physical memory,
34
+ swap, free memory, and so on.
35
+ EOF
36
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sys-memory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel J. Berger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
14
+ cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
15
+ MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
16
+ ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
17
+ bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
18
+ A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
19
+ u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
20
+ 75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
21
+ 6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
22
+ iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
23
+ ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
24
+ 74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
25
+ 058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
26
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
27
+ AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
28
+ YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
29
+ /3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
30
+ h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
31
+ 6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
32
+ ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
33
+ 1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
34
+ DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
35
+ ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
+ WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
+ -----END CERTIFICATE-----
38
+ date: 2021-08-16 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: ffi
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.1'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.1'
54
+ - !ruby/object:Gem::Dependency
55
+ name: activesupport
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '6.0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '6.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rspec
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.9'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.9'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '13.0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '13.0'
96
+ description: |2
97
+ The sys-memory library provides an interface for gathering information
98
+ about your system's memory. Information includes total physical memory,
99
+ swap, free memory, and so on.
100
+ email: djberg96@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - Gemfile
106
+ - LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - certs/djberg96_pub.pem
110
+ - lib/sys-memory.rb
111
+ - lib/sys/linux/memory.rb
112
+ - lib/sys/memory.rb
113
+ - lib/sys/osx/memory.rb
114
+ - lib/sys/version.rb
115
+ - lib/sys/windows/memory.rb
116
+ - spec/sys_memory_spec.rb
117
+ - sys-memory.gemspec
118
+ homepage: https://github.com/djberg96/sys-memory
119
+ licenses:
120
+ - Apache-2.0
121
+ metadata:
122
+ homepage_uri: https://github.com/djberg96/sys-memory
123
+ bug_tracker_uri: https://github.com/djberg96/sys-memory/issues
124
+ changelog_uri: https://github.com/djberg96/sys-memory/blob/main/CHANGES.md
125
+ documentation_uri: https://github.com/djberg96/sys-memory/wiki
126
+ source_code_uri: https://github.com/djberg96/sys-memory
127
+ wiki_uri: https://github.com/djberg96/sys-memory/wiki
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.2.25
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: A Ruby interface for providing memory information
147
+ test_files:
148
+ - spec/sys_memory_spec.rb
metadata.gz.sig ADDED
Binary file