This commit introduces a hugepages configuration for postgres via a rhizome lib+bin. At the moment, it uses the default huge page size (2M), and calculates the number of huge pages as 25% of the total available memory. The setup adjusts the shared_buffers accordingly to fit the shared memory within the allocated number of hugepages. The configuration happens as an `ExecStartPre` script added to the existing systemd unit managed by pg_ctlcluster. To keep the semantics of the `start` command unchanged, the hugepages script *does not* stop an existing cluster to configure hugepages, and only does it when the cluster is not running. In a subsequent change, we can consider adding the boot parameters to setup 1G hugepages for larger instances (possibly standard-30+), where they are most useful. [1]: https://www.postgresql.org/docs/current/kernel-resources.html#LINUX-HUGE-PAGES
48 lines
2.0 KiB
Ruby
48 lines
2.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "../lib/hugepages_setup"
|
|
|
|
RSpec.describe HugepagesSetup do
|
|
let(:logger) { instance_double(Logger, warn: nil) }
|
|
let(:hugepages_setup) { described_class.new("17-main", logger) }
|
|
|
|
describe "#setup_postgres_hugepages" do
|
|
it "calculates hugepages via overhead subtraction and rounding" do
|
|
# Mock hugepage info: 512 x 2MB hugepages = 1024MB total hugepage space
|
|
expect(hugepages_setup).to receive(:hugepage_info).and_return([512, 2048])
|
|
|
|
# shared_memory_size increases due to simulated overhead:
|
|
# 1024MB -> 1061MB (37MB overhead)
|
|
expect(hugepages_setup).to receive(:get_postgres_param)
|
|
.with("shared_memory_size").and_return(1061)
|
|
|
|
# Block size for rounding shared_buffers
|
|
expect(hugepages_setup).to receive(:get_postgres_param)
|
|
.with("block_size").and_return(8192) # 8KB blocks
|
|
|
|
# First call: set shared_buffers to total hugepage space
|
|
# (1024MB = 1,048,576 KiB)
|
|
expect(hugepages_setup).to receive(:update_postgres_hugepages_conf)
|
|
.with(1_048_576)
|
|
|
|
# Second call: back off by overhead and round down to block boundary
|
|
# overhead = (1061 - 1024) * 1024 = 37,888 KiB
|
|
# target = 1,048,576 - 37,888 = 1,010,688 KiB
|
|
expected_shared_buffers = 1_010_688
|
|
expect(hugepages_setup).to receive(:update_postgres_hugepages_conf)
|
|
.with(expected_shared_buffers)
|
|
expect(expected_shared_buffers & 0b111).to eq(0) # Divisible by 8
|
|
|
|
expect { hugepages_setup.setup_postgres_hugepages }.not_to raise_error
|
|
end
|
|
|
|
it "skips setup if no hugepages are configured" do
|
|
expect(hugepages_setup).to receive(:hugepage_info).and_return([0, 2048])
|
|
expect(hugepages_setup).not_to receive(:get_postgres_param)
|
|
expect(hugepages_setup).not_to receive(:update_postgres_hugepages_conf)
|
|
expect(logger).to receive(:warn).with("No hugepages configured, skipping setup.")
|
|
expect { hugepages_setup.setup_postgres_hugepages }.not_to raise_error
|
|
end
|
|
end
|
|
end
|