Skip to content

Commit

Permalink
(FACT-3149) Fix memory usage reporting on FreeBSD
Browse files Browse the repository at this point in the history
* In vmstat(8), "free memory" correspond to unused memory that does not
  contain any data, and does not include cache / inactive memory which
  has some data but is immediatly available to the system if memory is
  needed.
  Prefer to get active and wired memory page count form sysctl(3) which
  correpond to the used memory that can (active) and cannot (wired) be
  swapped out, and multiply these by the size of a memory page.  This
  give a better overview of the current memory usage.
* Prefer `vm.stats.vm.v_page_count` over `hw.physmem`:  The available
  memory can be lower that what is physically present in the system and
  the free / used memory is a portion of the usable memory more than a
  portion of the physical memory.
  • Loading branch information
smortex committed Jan 5, 2023
1 parent d3447d7 commit e584555
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 19 deletions.
22 changes: 15 additions & 7 deletions lib/facter/resolvers/freebsd/system_memory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,33 @@ def post_resolve(fact_name, _options)

def calculate_system_memory(fact_name)
read_total_memory_in_bytes
read_available_memory_in_bytes
read_used_memory_in_bytes

@fact_list[:used_bytes] = @fact_list[:total_bytes] - @fact_list[:available_bytes]
@fact_list[:available_bytes] = @fact_list[:total_bytes] - @fact_list[:used_bytes]
@fact_list[:capacity] = Facter::Util::Resolvers::FilesystemHelper
.compute_capacity(@fact_list[:used_bytes], @fact_list[:total_bytes])

@fact_list[fact_name]
end

def read_available_memory_in_bytes
output = Facter::Core::Execution.execute('vmstat -H --libxo json', logger: log)
data = JSON.parse(output)
@fact_list[:available_bytes] = data['memory']['free-memory'] * 1024
def pagesize
@pagesize ||= Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_page_size')
end

def read_used_memory_in_bytes
require_relative 'ffi/ffi_helper'

@fact_list[:used_bytes] = pagesize * (
Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_active_count') +
Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_wire_count')
)
end

def read_total_memory_in_bytes
require_relative 'ffi/ffi_helper'

@fact_list[:total_bytes] = Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'hw.physmem')
@fact_list[:total_bytes] = pagesize *
Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_page_count')
end
end
end
Expand Down
17 changes: 11 additions & 6 deletions spec/facter/resolvers/freebsd/system_memory_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@
before do
system_memory.instance_variable_set(:@log, log_spy)
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
.with(:long, 'hw.physmem')
.and_return(17_043_554_304)

allow(Facter::Core::Execution).to receive(:execute)
.with('vmstat -H --libxo json', { logger: log_spy })
.and_return(load_fixture('freebsd_vmstat').read)
.with(:long, 'vm.stats.vm.v_page_size')
.and_return(4096)
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
.with(:long, 'vm.stats.vm.v_page_count')
.and_return(4_161_024)
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
.with(:long, 'vm.stats.vm.v_active_count')
.and_return(2_335_139)
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
.with(:long, 'vm.stats.vm.v_wire_count')
.and_return(1_167_569)
end

it 'returns available system memory in bytes' do
Expand Down
6 changes: 0 additions & 6 deletions spec/fixtures/freebsd_vmstat

This file was deleted.

0 comments on commit e584555

Please sign in to comment.