Skip to content

Commit

Permalink
Automatically configure "vm.nr_hugepages"
Browse files Browse the repository at this point in the history
  • Loading branch information
vitabaks committed Aug 1, 2024
1 parent 8c7d2b0 commit b4560af
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 1 deletion.
132 changes: 132 additions & 0 deletions roles/pre-checks/tasks/huge_pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
---
# Automatically configure "vm.nr_hugepages" for shared_buffers of 8GB or more,
# if 'sysctl_set' is 'true', "vm.nr_hugepages" is undefined or insufficient in sysctl_conf,
# and "huge_pages" is not 'off' in postgresql_parameters.

- block:
- name: "HugePages | Get shared_buffers value from postgresql_parameters variable"
ansible.builtin.set_fact:
shared_buffers: "{{ postgresql_parameters_shared_buffers }}"
shared_buffers_value: "{{ postgresql_parameters_shared_buffers | regex_search('[0-9]+') | int }}"
shared_buffers_unit: "{{ postgresql_parameters_shared_buffers | regex_search('[A-Za-z]+') | lower }}"
vars:
postgresql_parameters_shared_buffers: >-
{{
(postgresql_parameters
| selectattr('option', 'equalto', 'shared_buffers')
| map(attribute='value')
| first | default('128MB'))
}}
- name: "HugePages | Set variable: shared_buffers_gb"
ansible.builtin.set_fact:
shared_buffers_gb: "{{ (shared_buffers_value | int) // 1024 }}"
when: shared_buffers_unit == 'mb'

- name: "HugePages | Set variable: shared_buffers_gb"
ansible.builtin.set_fact:
shared_buffers_gb: "{{ shared_buffers_value }}"
when: shared_buffers_unit == 'gb'

- name: "HugePages | No configuration is required"
run_once: true
ansible.builtin.debug:
msg: >-
Current shared_buffers size: {{ shared_buffers }} (less than {{ min_shared_buffers_gb | default(8) }}GB).
No HugePages configuration is required.
when:
- (shared_buffers_gb | default(0) | int) < (min_shared_buffers_gb | default(8) | int)

- name: "HugePages | Get Hugepagesize value from /proc/meminfo"
ansible.builtin.command: "awk '/Hugepagesize/ {print $2}' /proc/meminfo"
changed_when: false
register: huge_page_size
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))

- name: "HugePages | Get HugePages_Total value from /proc/meminfo"
ansible.builtin.command: "awk '/HugePages_Total/ {print $2}' /proc/meminfo"
changed_when: false
register: huge_pages_total
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))

Check failure on line 53 in roles/pre-checks/tasks/huge_pages.yml

View workflow job for this annotation

GitHub Actions / build

yaml[trailing-spaces]

Trailing spaces

Check failure on line 53 in roles/pre-checks/tasks/huge_pages.yml

View workflow job for this annotation

GitHub Actions / build

53:1 [trailing-spaces] trailing spaces
- name: "HugePages | Calculate required HugePages"
ansible.builtin.set_fact:
huge_pages_required: >-
{{
((shared_buffers_gb | default(0) | int + (additional_huge_pages_gb | default(1)))
* 1024 * 1024) // huge_page_size.stdout | int | default(2048)
}}
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))

- name: "HugePages | Check if vm.nr_hugepages is already set sufficiently in sysctl_conf variable"
ansible.builtin.set_fact:
sysctl_conf_vm_nr_hugepages: >-
{{
(sysctl_conf.postgres_cluster
| selectattr('name', 'equalto', 'vm.nr_hugepages')
| map(attribute='value')
| first | default('0') | int)
}}
sysctl_conf_vm_nr_hugepages_sufficient: >-
{{
(sysctl_conf.postgres_cluster
| selectattr('name', 'equalto', 'vm.nr_hugepages')
| map(attribute='value')
| first | default('0') | int) >= huge_pages_required | int
}}
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))

- name: "HugePages | info"
ansible.builtin.debug:
var: hugepages_info
vars:
hugepages_info:
shared_buffers_gb: "{{ shared_buffers_gb }}"
huge_page_size_kb: "{{ huge_page_size.stdout | int | default(2048) }}"
huge_pages_total: "{{ huge_pages_total.stdout | int | default(0) }}"
huge_pages_required: "{{ huge_pages_required }}"
huge_pages_sufficient: "{{ sysctl_conf_vm_nr_hugepages_sufficient }}"
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))

# if huge_pages_auto_conf is true
- name: "HugePages | Specify \"vm.nr_hugepages\" with value \"{{ huge_pages_required }}\" in sysctl_conf variable"
ansible.builtin.set_fact:
sysctl_conf:
postgres_cluster: >-
{{
(sysctl_conf.postgres_cluster
| rejectattr('name', 'equalto', 'vm.nr_hugepages')
| list)
+ [ { 'name': 'vm.nr_hugepages', 'value': huge_pages_required } ]
}}
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))
- huge_pages_total.stdout | int | default(0) < huge_pages_required | int
- not sysctl_conf_vm_nr_hugepages_sufficient
- huge_pages_auto_conf | bool

# Stop, if the current vm.nr_hugepages value is insufficient in sysctl_conf variable and huge_pages_auto_conf is false
- name: "HugePages | The current HugePages setting is insufficient"
ansible.builtin.fail:
msg: >-
Insufficient HugePages. Current: {{ huge_pages_current }}. Required: {{ huge_pages_required }}.
Please adjust the vm.nr_hugepages kernel parameter.
vars:
huge_pages_current: >-
{{
(sysctl_conf_vm_nr_hugepages if sysctl_conf_vm_nr_hugepages | int > huge_pages_total.stdout | int
else huge_pages_total.stdout | int) | default(0)
}}
when:
- shared_buffers_gb | default(0) | int >= (min_shared_buffers_gb | default(8))
- huge_pages_total.stdout | int | default(0) < huge_pages_required | int
- not sysctl_conf_vm_nr_hugepages_sufficient
- not huge_pages_auto_conf | bool
when:
- sysctl_set | bool
- (postgresql_parameters | selectattr('option', 'equalto', 'huge_pages') | map(attribute='value') | first | default('try')) != 'off'
5 changes: 5 additions & 0 deletions roles/pre-checks/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
when:
- inventory_hostname in groups['postgres_cluster']

- name: Perform pre-checks for huge_pages
ansible.builtin.import_tasks: huge_pages.yml
when:
- inventory_hostname in groups['postgres_cluster']

- name: Perform pre-checks for pgbackrest
ansible.builtin.import_tasks: pgbackrest.yml
when:
Expand Down
2 changes: 1 addition & 1 deletion vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ postgresql_parameters:
- { option: "password_encryption", value: "{{ postgresql_password_encryption_algorithm }}" }
- { option: "max_locks_per_transaction", value: "512" }
- { option: "max_prepared_transactions", value: "0" }
- { option: "huge_pages", value: "try" } # or "on" if you set "vm_nr_hugepages" in kernel parameters
- { option: "huge_pages", value: "try" } # "vm.nr_hugepages" is auto-configured for shared_buffers >= 8GB (if huge_pages_auto_conf is true)
- { option: "shared_buffers", value: "{{ (ansible_memtotal_mb * 0.25) | int }}MB" } # by default, 25% of RAM
- { option: "effective_cache_size", value: "{{ (ansible_memtotal_mb * 0.75) | int }}MB" } # by default, 75% of RAM
- { option: "work_mem", value: "128MB" } # please change this value
Expand Down
5 changes: 5 additions & 0 deletions vars/system.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ sysctl_conf:
# - { name: "net.netfilter.nf_conntrack_max", value: "1048576" }
# - { name: "", value: "" }

# Huge Pages
# this setting will automatically configure "vm.nr_hugepages" for shared_buffers of 8GB or more
# if 'sysctl_set' is 'true', "vm.nr_hugepages" is undefined or insufficient in sysctl_conf,
# and "huge_pages" is not 'off' in postgresql_parameters.
huge_pages_auto_conf: true

# Transparent Huge Pages
disable_thp: true # or 'false'
Expand Down

0 comments on commit b4560af

Please sign in to comment.