Skip to content

Commit 392cc65

Browse files
committed
(FACT-3149) Fix memory usage reporting on FreeBSD
* 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.
1 parent a3d61a3 commit 392cc65

File tree

3 files changed

+26
-19
lines changed

3 files changed

+26
-19
lines changed

lib/facter/resolvers/freebsd/system_memory.rb

+15-7
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,33 @@ def post_resolve(fact_name, _options)
1515

1616
def calculate_system_memory(fact_name)
1717
read_total_memory_in_bytes
18-
read_available_memory_in_bytes
18+
read_used_memory_in_bytes
1919

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

2424
@fact_list[fact_name]
2525
end
2626

27-
def read_available_memory_in_bytes
28-
output = Facter::Core::Execution.execute('vmstat -H --libxo json', logger: log)
29-
data = JSON.parse(output)
30-
@fact_list[:available_bytes] = data['memory']['free-memory'] * 1024
27+
def pagesize
28+
@pagesize ||= Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_page_size')
29+
end
30+
31+
def read_used_memory_in_bytes
32+
require_relative 'ffi/ffi_helper'
33+
34+
@fact_list[:used_bytes] = pagesize * (
35+
Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_active_count') +
36+
Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_wire_count')
37+
)
3138
end
3239

3340
def read_total_memory_in_bytes
3441
require_relative 'ffi/ffi_helper'
3542

36-
@fact_list[:total_bytes] = Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'hw.physmem')
43+
@fact_list[:total_bytes] = pagesize *
44+
Facter::Freebsd::FfiHelper.sysctl_by_name(:long, 'vm.stats.vm.v_page_count')
3745
end
3846
end
3947
end

spec/facter/resolvers/freebsd/system_memory_spec.rb

+11-6
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@
1212
before do
1313
system_memory.instance_variable_set(:@log, log_spy)
1414
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
15-
.with(:long, 'hw.physmem')
16-
.and_return(17_043_554_304)
17-
18-
allow(Facter::Core::Execution).to receive(:execute)
19-
.with('vmstat -H --libxo json', { logger: log_spy })
20-
.and_return(load_fixture('freebsd_vmstat').read)
15+
.with(:long, 'vm.stats.vm.v_page_size')
16+
.and_return(4096)
17+
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
18+
.with(:long, 'vm.stats.vm.v_page_count')
19+
.and_return(4_161_024)
20+
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
21+
.with(:long, 'vm.stats.vm.v_active_count')
22+
.and_return(2_335_139)
23+
allow(Facter::Freebsd::FfiHelper).to receive(:sysctl_by_name)
24+
.with(:long, 'vm.stats.vm.v_wire_count')
25+
.and_return(1_167_569)
2126
end
2227

2328
it 'returns available system memory in bytes' do

spec/fixtures/freebsd_vmstat

-6
This file was deleted.

0 commit comments

Comments
 (0)