diff --git a/.gitignore b/.gitignore index 58b6f0b..b00c4c4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ .config .yardoc .DS_Store -Gemfile.lock InstalledFiles _yardoc coverage diff --git a/.ruby-version b/.ruby-version index 530cdd9..bda8fbe 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.2.4 +2.2.6 diff --git a/.travis.yml b/.travis.yml index 2dbb705..f293b89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: ruby os: - linux rvm: - - ruby-2.2.5 + - ruby-2.2.6 - ruby-head env: - TRAVIS=true diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..e68fa0c --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,73 @@ +PATH + remote: . + specs: + vmstat (2.3.0) + +GEM + remote: https://rubygems.org/ + specs: + coderay (1.1.1) + diff-lcs (1.2.5) + ffi (1.9.14) + formatador (0.2.5) + guard (2.14.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (~> 1.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + lumberjack (1.0.10) + method_source (0.8.2) + nenv (0.3.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) + pry (0.10.4) + coderay (~> 1.1.0) + method_source (~> 0.8.1) + slop (~> 3.4) + rake (11.3.0) + rake-compiler (1.0.3) + rake + rb-fsevent (0.9.8) + rb-inotify (0.9.7) + ffi (>= 0.5.0) + rspec (2.99.0) + rspec-core (~> 2.99.0) + rspec-expectations (~> 2.99.0) + rspec-mocks (~> 2.99.0) + rspec-core (2.99.2) + rspec-expectations (2.99.2) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.99.4) + ruby_dep (1.5.0) + shellany (0.0.1) + slop (3.6.0) + thor (0.19.4) + timecop (0.8.1) + +PLATFORMS + ruby + +DEPENDENCIES + guard-rspec + rake (~> 11.3) + rake-compiler + rspec (~> 2.9) + timecop + vmstat! + +BUNDLED WITH + 1.13.6 diff --git a/lib/vmstat.rb b/lib/vmstat.rb index abba610..007f9e6 100644 --- a/lib/vmstat.rb +++ b/lib/vmstat.rb @@ -15,6 +15,7 @@ module Vmstat autoload :Disk, "vmstat/disk" autoload :LinuxDisk, "vmstat/linux_disk" autoload :Memory, "vmstat/memory" + autoload :LinuxMemory, "vmstat/linux_memory" autoload :Task, "vmstat/task" autoload :LoadAverage, "vmstat/load_average" autoload :ProcFS, "vmstat/procfs" diff --git a/lib/vmstat/linux_memory.rb b/lib/vmstat/linux_memory.rb new file mode 100644 index 0000000..2b52fbc --- /dev/null +++ b/lib/vmstat/linux_memory.rb @@ -0,0 +1,13 @@ +# @attr [Fixnum] available +# The estimated available memory (linux) +# See: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 +class Vmstat::LinuxMemory < Vmstat::Memory + attr_accessor :available + + # Calculate the available bytes based of the active pages. + # @return [Fixnum] active bytes + def available_bytes + available * pagesize + end +end + diff --git a/lib/vmstat/memory.rb b/lib/vmstat/memory.rb index 0e32d01..6de2346 100644 --- a/lib/vmstat/memory.rb +++ b/lib/vmstat/memory.rb @@ -19,7 +19,7 @@ class Memory < Struct.new(:pagesize, :wired, :active, :inactive, :free, # Calculate the wired bytes based of the wired pages. # @return [Fixnum] wired bytes def wired_bytes - wired * pagesize + wired * pagesize end # Calculate the active bytes based of the active pages. @@ -43,7 +43,20 @@ def free_bytes # Calculate the total bytes based of all pages # @return [Fixnum] total bytes def total_bytes - (wired + active + inactive + free) * pagesize + (wired + active + inactive + free) * pagesize + end + end + + # @attr [Fixnum] available + # The estimated available memory (linux) + # See: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 + class LinuxMemory < Memory + attr_accessor :available + + # Calculate the available bytes based of the active pages. + # @return [Fixnum] active bytes + def available_bytes + available * pagesize end end end diff --git a/lib/vmstat/procfs.rb b/lib/vmstat/procfs.rb index a5f84f3..3e18993 100644 --- a/lib/vmstat/procfs.rb +++ b/lib/vmstat/procfs.rb @@ -45,17 +45,21 @@ def cpu # Vmstat.memory # => # def memory @pagesize ||= Vmstat.pagesize + has_available = false - total = free = active = inactive = pageins = pageouts = 0 + total = free = active = inactive = pageins = pageouts = available = 0 procfs_file("meminfo") do |file| content = file.read(2048) # the requested information is in the first bytes - content.scan(/(\w+):\s+(\d+) kB/) do |name, kbytes| + content.scan(/(\w+):\s+(\d+) kB/) do |name, kbytes| pages = (kbytes.to_i * 1024) / @pagesize case name when "MemTotal" then total = pages when "MemFree" then free = pages + when "MemAvailable" + available = pages + has_available = true when "Active" then active = pages when "Inactive" then inactive = pages end @@ -74,8 +78,11 @@ def memory end end - Memory.new @pagesize, total-free-active-inactive, active, inactive, free, - pageins, pageouts + mem_klass = has_available ? LinuxMemory : Memory + mem_klass.new(@pagesize, total-free-active-inactive, active, + inactive, free, pageins, pageouts).tap do |mem| + mem.available = available if has_available + end end # Fetches the information for all available network devices. @@ -91,8 +98,8 @@ def network_interfaces when /^lo/ then NetworkInterface::LOOPBACK_TYPE end - netifcs << NetworkInterface.new(columns[0].to_sym, columns[1].to_i, - columns[3].to_i, columns[4].to_i, + netifcs << NetworkInterface.new(columns[0].to_sym, columns[1].to_i, + columns[3].to_i, columns[4].to_i, columns[9].to_i, columns[11].to_i, type) end @@ -107,7 +114,7 @@ def task procfs_file("self", "stat") do |file| data = file.read.split(/ /) - Task.new(data[22].to_i / @pagesize, data[23].to_i, + Task.new(data[22].to_i / @pagesize, data[23].to_i, data[13].to_i * 1000, data[14].to_i * 1000) end end diff --git a/lib/vmstat/version.rb b/lib/vmstat/version.rb index 64cf9ac..15f665a 100644 --- a/lib/vmstat/version.rb +++ b/lib/vmstat/version.rb @@ -1,3 +1,3 @@ module Vmstat - VERSION = "2.2.1" + VERSION = "2.3.0" end diff --git a/spec/memavail_procfs/meminfo b/spec/memavail_procfs/meminfo new file mode 100644 index 0000000..2b6caad --- /dev/null +++ b/spec/memavail_procfs/meminfo @@ -0,0 +1,43 @@ +MemTotal: 1884428 kB +MemFree: 252452 kB +MemAvailable: 458368 kB +Buffers: 76 kB +Cached: 321752 kB +SwapCached: 4 kB +Active: 1307912 kB +Inactive: 177976 kB +Active(anon): 1074332 kB +Inactive(anon): 106548 kB +Active(file): 233580 kB +Inactive(file): 71428 kB +Unevictable: 21100 kB +Mlocked: 21100 kB +SwapTotal: 2097148 kB +SwapFree: 2097140 kB +Dirty: 60 kB +Writeback: 0 kB +AnonPages: 1185204 kB +Mapped: 101384 kB +Shmem: 8760 kB +Slab: 59380 kB +SReclaimable: 27064 kB +SUnreclaim: 32316 kB +KernelStack: 4528 kB +PageTables: 21592 kB +NFS_Unstable: 0 kB +Bounce: 0 kB +WritebackTmp: 0 kB +CommitLimit: 3039360 kB +Committed_AS: 2906080 kB +VmallocTotal: 34359738367 kB +VmallocUsed: 269704 kB +VmallocChunk: 34359466492 kB +HardwareCorrupted: 0 kB +AnonHugePages: 659456 kB +HugePages_Total: 0 +HugePages_Free: 0 +HugePages_Rsvd: 0 +HugePages_Surp: 0 +Hugepagesize: 2048 kB +DirectMap4k: 26624 kB +DirectMap2M: 2070528 kB diff --git a/spec/memavail_procfs/vmstat b/spec/memavail_procfs/vmstat new file mode 100644 index 0000000..db6b1ed --- /dev/null +++ b/spec/memavail_procfs/vmstat @@ -0,0 +1,89 @@ +nr_free_pages 107062 +nr_inactive_anon 60 +nr_active_anon 1557 +nr_inactive_file 8341 +nr_active_file 4939 +nr_unevictable 0 +nr_mlock 0 +nr_anon_pages 1579 +nr_mapped 1461 +nr_file_pages 13346 +nr_dirty 1 +nr_writeback 0 +nr_slab_reclaimable 1628 +nr_slab_unreclaimable 1885 +nr_page_table_pages 101 +nr_kernel_stack 88 +nr_unstable 0 +nr_bounce 0 +nr_vmscan_write 0 +nr_vmscan_immediate_reclaim 0 +nr_writeback_temp 0 +nr_isolated_anon 0 +nr_isolated_file 0 +nr_shmem 67 +nr_dirtied 185 +nr_written 182 +nr_anon_transparent_hugepages 0 +nr_dirty_threshold 24392 +nr_dirty_background_threshold 12196 +pgpgin 64599 +pgpgout 1104 +pswpin 0 +pswpout 0 +pgalloc_dma 2 +pgalloc_normal 190973 +pgalloc_high 0 +pgalloc_movable 0 +pgfree 298439 +pgactivate 5802 +pgdeactivate 0 +pgfault 581461 +pgmajfault 42 +pgrefill_dma 0 +pgrefill_normal 0 +pgrefill_high 0 +pgrefill_movable 0 +pgsteal_dma 0 +pgsteal_normal 0 +pgsteal_high 0 +pgsteal_movable 0 +pgscan_kswapd_dma 0 +pgscan_kswapd_normal 0 +pgscan_kswapd_high 0 +pgscan_kswapd_movable 0 +pgscan_direct_dma 0 +pgscan_direct_normal 0 +pgscan_direct_high 0 +pgscan_direct_movable 0 +pginodesteal 0 +slabs_scanned 0 +kswapd_steal 0 +kswapd_inodesteal 0 +kswapd_low_wmark_hit_quickly 0 +kswapd_high_wmark_hit_quickly 0 +kswapd_skip_congestion_wait 0 +pageoutrun 1 +allocstall 0 +pgrotated 0 +compact_blocks_moved 0 +compact_pages_moved 0 +compact_pagemigrate_failed 0 +compact_stall 0 +compact_fail 0 +compact_success 0 +htlb_buddy_alloc_success 0 +htlb_buddy_alloc_fail 0 +unevictable_pgs_culled 0 +unevictable_pgs_scanned 0 +unevictable_pgs_rescued 0 +unevictable_pgs_mlocked 0 +unevictable_pgs_munlocked 0 +unevictable_pgs_cleared 0 +unevictable_pgs_stranded 0 +unevictable_pgs_mlockfreed 0 +thp_fault_alloc 0 +thp_fault_fallback 0 +thp_collapse_alloc 0 +thp_collapse_alloc_failed 0 +thp_split 0 diff --git a/spec/vmstat/memavail_spec.rb b/spec/vmstat/memavail_spec.rb new file mode 100644 index 0000000..def381f --- /dev/null +++ b/spec/vmstat/memavail_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Vmstat::LinuxMemory do + let(:procfs) do + Class.new do + extend Vmstat::ProcFS + + def self.procfs_path + File.expand_path("../../memavail_procfs", __FILE__) + end + end + end + + context "#memory" do + subject { procfs.memory } + + it { should be_a(Vmstat::LinuxMemory) } + if `getconf PAGESIZE`.chomp.to_i == 4096 + it do + should == Vmstat::LinuxMemory.new(4096, 36522, 326978, + 44494, 63113, 64599, 1104) + end + + it "should have the right total" do + (subject.wired_bytes + subject.active_bytes + + subject.inactive_bytes + subject.free_bytes).should == 1929654272 + end + end + end +end + diff --git a/vmstat.gemspec b/vmstat.gemspec index 4974b58..77e7800 100644 --- a/vmstat.gemspec +++ b/vmstat.gemspec @@ -21,8 +21,8 @@ Gem::Specification.new do |gem| gem.require_paths = ["lib"] gem.extensions = ["ext/vmstat/extconf.rb"] - gem.add_development_dependency('rake') - gem.add_development_dependency('rspec', "~> 2.9") + gem.add_development_dependency('rake', '~> 11.3') + gem.add_development_dependency('rspec', '~> 2.9') gem.add_development_dependency('rake-compiler') gem.add_development_dependency('guard-rspec') gem.add_development_dependency('timecop')