From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB0A910942 for ; Fri, 18 Jul 2025 04:26:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752812780; cv=none; b=pl3O9Cjo3e2sqNEL8Twmk6f1By6WV+IfSsiqA5ZcZ2zHcNLYnNRmt0THXjBOX6EkyIiFnkK838I6Cx4J4wYxWb4UbKpx1mb5xDd7SDeVVGRu/InHbXlhUyC0BybIjDwL/teC5jWYiZYju833Phm0M26c3EcyshUJY8G9VhoQYFA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752812780; c=relaxed/simple; bh=8J/01Tic/77Qrk9QoG63S4Dxod0Bt69qCU8dlvW/BBY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=PvXUU51Kkm0EQ/c6V+FAwcJqADfSGnAGNmQJIXemuosPLBWLbQev/z69eFuNndhMjCSt+Ozmil3dNKZ8rV2o2vOEVuSvBTofRuWb0SC78+kHF1HfSExjUgKwTtrgIT8mZJWbLkxjsO4zluaZmV1HiOryIJTIhbHFFdHkdFAxykw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=kernel.org; spf=none smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=R1dxuOhP; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=kernel.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="R1dxuOhP" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Sender:Content-Transfer-Encoding: MIME-Version:Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-Type: Content-ID:Content-Description:In-Reply-To:References; bh=pIGoRsuDfVXuc9hF86mkEELbfDhp4EYoCvpyw4srNc8=; b=R1dxuOhPA6zrSfKZ3BrOrR9Nc0 IjWm6k0HOv+ng59IxITgubJyHN1stPjB30rEAp3BI5ngsC/2gRhgLc/kOm8o8cXkHesl4w5ZSMN4t 8JC6CIvX62zw+oJoVdoNmswidQXp8beEf+d5IOfv3MSoBqDTd+sRIwwJfhP6sBxz4Zyeif1TBM+uc lhYVH2GaTncf3RrWjSE3WwbUksvAZlQdD45AA8cL99Q71DdRhygRB3+1ihqBYwdQGaW+W9AlTnjMl kADRuqp0hMHHt7QUfG+VSxmSL27cyWI3POAKm8C2ZV5VSsY9sg6+8g3M4wWN1bQlUuid+MIXNQfMd A2A4iDsA==; Received: from mcgrof by bombadil.infradead.org with local (Exim 4.98.2 #2 (Red Hat Linux)) id 1uccfh-0000000Bezs-3WGQ; Fri, 18 Jul 2025 04:26:09 +0000 From: Luis Chamberlain To: Chuck Lever , Daniel Gomez , Viacheslav Dubeyko , Mel Gorman , Jan Kara , David Bueso , Qazi@infradead.org, Shoaib Asif , "Liam R . Howlett" , Lorenzo Stoakes , Vlastimil Babka , Johannes Weiner , kdevops@lists.linux.dev Cc: Luis Chamberlain Subject: [PATCH] mmtests: add support for Mel Gorman's mmtests Date: Thu, 17 Jul 2025 21:26:05 -0700 Message-ID: <20250718042605.2779185-1-mcgrof@kernel.org> X-Mailer: git-send-email 2.49.0 Precedence: bulk X-Mailing-List: kdevops@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: Luis Chamberlain The mmtest test suite is used for production memory management testing. Add support for it, first with two target workflows to help evaluate memory fragmentation. We add support for the workloads which helped reproduce memory fragmentation easily back in year 2010 when Mel Gorman first added Linux kernel memory compaction support [0] merged on v2.6.35. * thpcompact * thpchallenge Generated-by: Claude AI Link: https://lore.kernel.org/all/1270224168-14775-1-git-send-email-mel@csn.ul.ie/T/#u # [0] Signed-off-by: Luis Chamberlain --- Yet more Software 3.0 work on kdevops. this time by Claude AI. Claude certainly did a better job than ChatGPT Codex. This has been in the kdevops backlog for years. I just never had time for it, and generative AI just makes it easy. I did do a bit of "design" enhancmeents like moving workload specific stuff to its own file like: workflows/mmtests/Kconfig.* The filesystem stuff was also a bit of a inspiration based on the existing sysbench workflow on kdevops but simplified further. I also run time tested both workflows against two VMs. Using this as base patch, it should be privial to extend support now for other mmtests workflows on kdevops. The next thing we need is to just add the option to the Linux kernel configuration option on kdevops so that when KDEVOPS_BASELINE_AND_DEV is used (for AB testing) that we can just pick a different kernel branch for B. For now we can easily manually switch kernels on B. Future things to do is run on the host the compare script and also visualize results somehow. Now that we have automatic testing going also based on Linus' tree and linux-next tags, it should be pretty trivial for us to add and extend the mmtests dashboard to start running tests if we need from mmtests. The https://kdevops.org dashboard would just show the results. Bare metal support should be rather easy, I already tested steady-state support on it and it wasn't much of a huge change. I think we just need to "select WORKFLOW_INFER_USER_AND_GROUP" so /data/ partition gets the inferred user and group based on the ssh configuration. That and the user will have to have had created that data and partition, and we just skip the data partition creation when on bare metal (SKIP_BRINGUP). Running on VMs on the cloud is super easy since we already have full cloud support. So that should already just work. We're adding this support to kdevops because Shoaib has some already compelling results on his analysis on memory fragmentation on answering the quesiton if LBS affects memory fragmentation. We now want to push the limits using exisiting prior workloads used to stress memory fragmentaiton. kconfigs/Kconfig.defaults | 4 + kconfigs/Kconfig.mirror | 19 ++ kconfigs/workflows/Kconfig | 27 ++ playbooks/mmtests.yml | 4 + playbooks/roles/gen_hosts/tasks/main.yml | 27 ++ .../roles/gen_hosts/templates/mmtests.j2 | 23 ++ playbooks/roles/gen_nodes/tasks/main.yml | 49 ++++ .../roles/linux-mirror/defaults/main.yml | 1 + .../linux-mirror/templates/mirrors.yaml.j2 | 3 + playbooks/roles/mmtests/defaults/main.yml | 37 +++ .../tasks/install-deps/debian/main.yml | 66 +++++ .../roles/mmtests/tasks/install-deps/main.yml | 16 ++ .../tasks/install-deps/redhat/main.yml | 57 ++++ .../mmtests/tasks/install-deps/suse/main.yml | 57 ++++ playbooks/roles/mmtests/tasks/main.yaml | 270 ++++++++++++++++++ .../mmtests/templates/thpchallenge-config.j2 | 76 +++++ .../mmtests/templates/thpcompact-config.j2 | 102 +++++++ workflows/Makefile | 4 + workflows/mmtests/Kconfig | 108 +++++++ workflows/mmtests/Kconfig.ext4 | 105 +++++++ workflows/mmtests/Kconfig.fs | 80 ++++++ workflows/mmtests/Kconfig.thpchallenge | 52 ++++ workflows/mmtests/Kconfig.thpcompact | 62 ++++ workflows/mmtests/Kconfig.xfs | 211 ++++++++++++++ workflows/mmtests/Makefile | 68 +++++ 25 files changed, 1528 insertions(+) create mode 100644 playbooks/mmtests.yml create mode 100644 playbooks/roles/gen_hosts/templates/mmtests.j2 create mode 100644 playbooks/roles/mmtests/defaults/main.yml create mode 100644 playbooks/roles/mmtests/tasks/install-deps/debian/main.yml create mode 100644 playbooks/roles/mmtests/tasks/install-deps/main.yml create mode 100644 playbooks/roles/mmtests/tasks/install-deps/redhat/main.yml create mode 100644 playbooks/roles/mmtests/tasks/install-deps/suse/main.yml create mode 100644 playbooks/roles/mmtests/tasks/main.yaml create mode 100644 playbooks/roles/mmtests/templates/thpchallenge-config.j2 create mode 100644 playbooks/roles/mmtests/templates/thpcompact-config.j2 create mode 100644 workflows/mmtests/Kconfig create mode 100644 workflows/mmtests/Kconfig.ext4 create mode 100644 workflows/mmtests/Kconfig.fs create mode 100644 workflows/mmtests/Kconfig.thpchallenge create mode 100644 workflows/mmtests/Kconfig.thpcompact create mode 100644 workflows/mmtests/Kconfig.xfs create mode 100644 workflows/mmtests/Makefile diff --git a/kconfigs/Kconfig.defaults b/kconfigs/Kconfig.defaults index a6f99bde..c43fee91 100644 --- a/kconfigs/Kconfig.defaults +++ b/kconfigs/Kconfig.defaults @@ -116,6 +116,10 @@ config DEFAULT_MODULES_HTTPS_GOOGLE_URL string default "https://kernel.googlesource.com/pub/scm/linux/kernel/git/modules/linux.git" +config DEFAULT_MMTESTS_GITHUB_HTTPS_URL + string + default "https://github.com/gormanm/mmtests.git" + config DEFAULT_MCGROF_LINUS_GIT_URL string default "https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git" diff --git a/kconfigs/Kconfig.mirror b/kconfigs/Kconfig.mirror index 14e86149..312de47e 100644 --- a/kconfigs/Kconfig.mirror +++ b/kconfigs/Kconfig.mirror @@ -657,5 +657,24 @@ config MIRROR_XFSPROGS_URL string default DEFAULT_XFSPROGS_URL +choice + prompt "Tools - mmtests.git mirror protocol/source" + default MIRROR_MMTESTS_HTTPS_GITHUB + depends on INSTALL_LOCAL_LINUX_MIRROR + +config MIRROR_MMTESTS_HTTPS_GITHUB + bool "HTTPS (GitHub)" + help + If you enable this option then GitHub HTTPS will be used as the + source of the mirror. The URL is: + + https://github.com/gormanm/mmtests.git + +endchoice + +config MIRROR_MMTESTS_URL + string + default DEFAULT_MMTESTS_GITHUB_HTTPS_URL if MIRROR_MMTESTS_HTTPS_GITHUB + endif # ENABLE_LOCAL_LINUX_MIRROR endif # TERRAFORM diff --git a/kconfigs/workflows/Kconfig b/kconfigs/workflows/Kconfig index d10ab6c9..a1d2c331 100644 --- a/kconfigs/workflows/Kconfig +++ b/kconfigs/workflows/Kconfig @@ -182,6 +182,13 @@ config KDEVOPS_WORKFLOW_DEDICATE_SYSBENCH This will dedicate your configuration to running only the sysbench workflow. +config KDEVOPS_WORKFLOW_DEDICATE_MMTESTS + bool "mmtests" + select KDEVOPS_WORKFLOW_ENABLE_MMTESTS + help + This will dedicate your configuration to running only the + mmtests workflow for memory fragmentation testing. + endchoice config KDEVOPS_WORKFLOW_NAME @@ -195,6 +202,7 @@ config KDEVOPS_WORKFLOW_NAME default "ltp" if KDEVOPS_WORKFLOW_DEDICATE_LTP default "nfstest" if KDEVOPS_WORKFLOW_DEDICATE_NFSTEST default "sysbench" if KDEVOPS_WORKFLOW_DEDICATE_SYSBENCH + default "mmtests" if KDEVOPS_WORKFLOW_DEDICATE_MMTESTS endif @@ -288,6 +296,14 @@ config KDEVOPS_WORKFLOW_NOT_DEDICATED_ENABLE_SYSBENCH Select this option if you want to provision sysbench on a single target node for by-hand testing. +config KDEVOPS_WORKFLOW_NOT_DEDICATED_ENABLE_MMTESTS + bool "mmtests" + select KDEVOPS_WORKFLOW_ENABLE_MMTESTS + depends on LIBVIRT || TERRAFORM_PRIVATE_NET + help + Select this option if you want to provision mmtests on a + single target node for by-hand testing. + endif # !WORKFLOWS_DEDICATED_WORKFLOW config KDEVOPS_WORKFLOW_ENABLE_FSTESTS @@ -390,6 +406,17 @@ source "workflows/sysbench/Kconfig" endmenu endif # KDEVOPS_WORKFLOW_ENABLE_SYSBENCH +config KDEVOPS_WORKFLOW_ENABLE_MMTESTS + bool + output yaml + default y if KDEVOPS_WORKFLOW_NOT_DEDICATED_ENABLE_MMTESTS || KDEVOPS_WORKFLOW_DEDICATE_MMTESTS + +if KDEVOPS_WORKFLOW_ENABLE_MMTESTS +menu "Configure and run the mmtests tests" +source "workflows/mmtests/Kconfig" +endmenu +endif # KDEVOPS_WORKFLOW_ENABLE_MMTESTS + config KDEVOPS_WORKFLOW_ENABLE_SSD_STEADY_STATE bool "Attain SSD steady state prior to tests" output yaml diff --git a/playbooks/mmtests.yml b/playbooks/mmtests.yml new file mode 100644 index 00000000..d341d246 --- /dev/null +++ b/playbooks/mmtests.yml @@ -0,0 +1,4 @@ +--- +- hosts: all + roles: + - role: mmtests \ No newline at end of file diff --git a/playbooks/roles/gen_hosts/tasks/main.yml b/playbooks/roles/gen_hosts/tasks/main.yml index 5f523459..58ebd1d4 100644 --- a/playbooks/roles/gen_hosts/tasks/main.yml +++ b/playbooks/roles/gen_hosts/tasks/main.yml @@ -312,6 +312,33 @@ - kdevops_workflow_enable_sysbench - ansible_hosts_template.stat.exists +- name: Infer enabled mmtests test types + set_fact: + mmtests_enabled_test_types: >- + {{ + lookup('file', topdir_path + '/.config') + | regex_findall('^CONFIG_MMTESTS_ENABLE_(.*)=y$', multiline=True) + | map('lower') + | list + }} + when: + - kdevops_workflows_dedicated_workflow + - kdevops_workflow_enable_mmtests + - ansible_hosts_template.stat.exists + +- name: Generate the Ansible hosts file for a dedicated mmtests setup + tags: [ 'hosts' ] + template: + src: "{{ kdevops_hosts_template }}" + dest: "{{ topdir_path }}/{{ kdevops_hosts }}" + force: yes + trim_blocks: True + lstrip_blocks: True + when: + - kdevops_workflows_dedicated_workflow + - kdevops_workflow_enable_mmtests + - ansible_hosts_template.stat.exists + - name: Verify if final host file exists stat: path: "{{ topdir_path }}/{{ kdevops_hosts }}" diff --git a/playbooks/roles/gen_hosts/templates/mmtests.j2 b/playbooks/roles/gen_hosts/templates/mmtests.j2 new file mode 100644 index 00000000..d32ffe40 --- /dev/null +++ b/playbooks/roles/gen_hosts/templates/mmtests.j2 @@ -0,0 +1,23 @@ +[all] +{% for test_type in mmtests_enabled_test_types %} +{{ kdevops_host_prefix }}-{{ test_type }} +{% if kdevops_baseline_and_dev %} +{{ kdevops_host_prefix }}-{{ test_type }}-dev +{% endif %} +{% endfor %} +[all:vars] +ansible_python_interpreter = "{{ kdevops_python_interpreter }}" +[baseline] +{% for test_type in mmtests_enabled_test_types %} +{{ kdevops_host_prefix }}-{{ test_type }} +{% endfor %} +[baseline:vars] +ansible_python_interpreter = "{{ kdevops_python_interpreter }}" +[dev] +{% if kdevops_baseline_and_dev %} + {% for test_type in mmtests_enabled_test_types %} +{{ kdevops_host_prefix }}-{{ test_type }}-dev + {% endfor %} +{% endif %} +[dev:vars] +ansible_python_interpreter = "{{ kdevops_python_interpreter }}" diff --git a/playbooks/roles/gen_nodes/tasks/main.yml b/playbooks/roles/gen_nodes/tasks/main.yml index ef68742f..457a070e 100644 --- a/playbooks/roles/gen_nodes/tasks/main.yml +++ b/playbooks/roles/gen_nodes/tasks/main.yml @@ -486,6 +486,55 @@ - kdevops_workflow_enable_sysbench - ansible_nodes_template.stat.exists +- name: Infer enabled mmtests test section types + set_fact: + mmtests_enabled_test_types: >- + {{ + [kdevops_host_prefix + '-'] + | product( + lookup('file', topdir_path + '/.config') + | regex_findall('^CONFIG_MMTESTS_ENABLE_(.*)=y$', multiline=True) + | map('lower') + ) + | map('join') + | list + }} + when: + - kdevops_workflows_dedicated_workflow + - kdevops_workflow_enable_mmtests + - ansible_nodes_template.stat.exists + - not kdevops_baseline_and_dev + +- name: Infer enabled mmtests test section types with dev hosts + vars: + kdevops_config_data: "{{ lookup('file', topdir_path + '/.config') }}" + config_val: "CONFIG_MMTESTS_ENABLE_" + config_mmtests_test_types: "{{ kdevops_config_data | regex_findall('^' + config_val + '(.*)=y$', multiline=True) }}" + config_mmtests_test_type_names: "{{ config_mmtests_test_types | lower }}" + all_nodes: "{{ [kdevops_host_prefix + '-'] | product(config_mmtests_test_type_names) | map('join') | list }}" + set_fact: + mmtests_enabled_test_types: "{{ all_nodes | product(['', '-dev']) | map('join') | list }}" + when: + - kdevops_workflows_dedicated_workflow + - kdevops_workflow_enable_mmtests + - ansible_nodes_template.stat.exists + - kdevops_baseline_and_dev + +- name: Generate the mmtests kdevops nodes file using {{ kdevops_nodes_template }} as jinja2 source template + tags: [ 'hosts' ] + vars: + node_template: "{{ kdevops_nodes_template | basename }}" + nodes: "{{ mmtests_enabled_test_types }}" + all_generic_nodes: "{{ mmtests_enabled_test_types }}" + template: + src: "{{ node_template }}" + dest: "{{ topdir_path }}/{{ kdevops_nodes }}" + force: yes + when: + - kdevops_workflows_dedicated_workflow + - kdevops_workflow_enable_mmtests + - ansible_nodes_template.stat.exists + - name: Get the control host's timezone ansible.builtin.command: "timedatectl show -p Timezone --value" register: kdevops_host_timezone diff --git a/playbooks/roles/linux-mirror/defaults/main.yml b/playbooks/roles/linux-mirror/defaults/main.yml index 16ec2e73..9f2e8355 100644 --- a/playbooks/roles/linux-mirror/defaults/main.yml +++ b/playbooks/roles/linux-mirror/defaults/main.yml @@ -10,6 +10,7 @@ defaults_dbench_git: "https://github.com/linux-kdevops/dbench.git" defaults_kdevops_results_archive_git: "https://github.com/linux-kdevops/kdevops-results-archive.git" defaults_git_git: "https://git.kernel.org/pub/scm/git/git.git" defaults_ltp_git: "https://github.com/linux-test-project/ltp.git" +defaults_mmtests_git: "https://github.com/gormanm/mmtests.git" defaults_nfstest_git: "git://git.linux-nfs.org/projects/mora/nfstest.git" defaults_pynfs_git: "git://git.linux-nfs.org/projects/cdmackay/pynfs.git" defaults_xfsprogs_git: "https://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git" diff --git a/playbooks/roles/linux-mirror/templates/mirrors.yaml.j2 b/playbooks/roles/linux-mirror/templates/mirrors.yaml.j2 index 92d9ee8f..9f3ee06f 100644 --- a/playbooks/roles/linux-mirror/templates/mirrors.yaml.j2 +++ b/playbooks/roles/linux-mirror/templates/mirrors.yaml.j2 @@ -55,6 +55,9 @@ mirrors: - short_name: "ltp" url: "{{ defaults_ltp_git }}" target: "ltp.git" + - short_name: "mmtests" + url: "{{ defaults_mmtests_git }}" + target: "mmtests.git" - short_name: "nfstest" url: "{{ defaults_nfstest_git }}" target: "nfstest.git" diff --git a/playbooks/roles/mmtests/defaults/main.yml b/playbooks/roles/mmtests/defaults/main.yml new file mode 100644 index 00000000..7cb7ef4e --- /dev/null +++ b/playbooks/roles/mmtests/defaults/main.yml @@ -0,0 +1,37 @@ +--- +# mmtests default configuration +mmtests_data_dir: "{{ data_path }}/mmtests" +mmtests_results_dir_basename: "{{ mmtests_data_dir }}/work/" +mmtests_results_dir: "{{ mmtests_results_dir_basename }}/log" + +# mmtests configuration +mmtests_git_url: "https://github.com/gormanm/mmtests.git" +mmtests_git_version: "master" + +# Test configuration +mmtests_test_type: "thpcompact" + +mmtests_thpcompact_threads_min: 1 +mmtests_thpcompact_threads_max: 32 +mmtests_thpcompact_threads_max_type_manual: False +mmtests_thpcompact_threads_max_type_auto: False +mmtests_thpcompact_anonymous_memory_percent: 80 +mmtests_thpcompact_filemap_memory_scale: 4 + +mmtests_iterations: 5 +mmtests_monitor_interval: 1 +mmtests_requires_mkfs_device: False +mmtests_device: "/dev/null" +mmtests_ext4_sector_size: 4k +mmtests_mkfs_type: "xfs" +mmtests_mkfs_cmd: "" + +# Monitoring configuration +mmtests_monitor_enable_ftrace: True +mmtests_monitor_enable_proc_monitoring: True +mmtests_monitor_enable_mpstat: True + +# System configuration +mmtests_pretest_compaction: False +mmtests_pretest_dropvmcaches: False +mmtests_pretest_thp_setting: "always" diff --git a/playbooks/roles/mmtests/tasks/install-deps/debian/main.yml b/playbooks/roles/mmtests/tasks/install-deps/debian/main.yml new file mode 100644 index 00000000..b1d6b381 --- /dev/null +++ b/playbooks/roles/mmtests/tasks/install-deps/debian/main.yml @@ -0,0 +1,66 @@ +--- +- name: Import optional extra_args file + include_vars: "{{ item }}" + ignore_errors: yes + with_first_found: + - files: + - "../extra_vars.yml" + - "../extra_vars.yaml" + - "../extra_vars.json" + skip: true + tags: vars + +- name: Update apt cache + become: yes + become_method: sudo + apt: + update_cache: yes + tags: deps + +- name: Install mmtests build dependencies + become: yes + become_method: sudo + apt: + name: + - build-essential + - git + - perl + - cpanminus + - libmath-gradient-perl + - r-base + - r-base-dev + - libnuma-dev + - libmath-gradient-perl + state: present + update_cache: true + tags: ['deps'] + +- name: Install mmtests runtime dependencies + become: yes + become_method: sudo + apt: + name: + - numactl + - fio + - sysstat + - procps + - util-linux + - coreutils + - time + - bc + - psmisc + state: present + update_cache: true + tags: ['deps'] + +- name: Install mmtests monitoring dependencies + become: yes + become_method: sudo + apt: + name: + - trace-cmd + - perf-tools-unstable + state: present + update_cache: true + tags: ['deps'] + ignore_errors: true diff --git a/playbooks/roles/mmtests/tasks/install-deps/main.yml b/playbooks/roles/mmtests/tasks/install-deps/main.yml new file mode 100644 index 00000000..d3972fae --- /dev/null +++ b/playbooks/roles/mmtests/tasks/install-deps/main.yml @@ -0,0 +1,16 @@ +--- +- include_role: + name: pkg + +# Distribution-specific setup for mmtests dependencies +- name: Debian/Ubuntu distribution specific setup + import_tasks: tasks/install-deps/debian/main.yml + when: ansible_facts['os_family']|lower == 'debian' + +- name: SUSE distribution specific setup + import_tasks: tasks/install-deps/suse/main.yml + when: ansible_facts['os_family']|lower == 'suse' + +- name: RedHat distribution specific setup + import_tasks: tasks/install-deps/redhat/main.yml + when: ansible_facts['os_family']|lower == 'redhat' \ No newline at end of file diff --git a/playbooks/roles/mmtests/tasks/install-deps/redhat/main.yml b/playbooks/roles/mmtests/tasks/install-deps/redhat/main.yml new file mode 100644 index 00000000..ddf2be5d --- /dev/null +++ b/playbooks/roles/mmtests/tasks/install-deps/redhat/main.yml @@ -0,0 +1,57 @@ +--- +- name: Import optional extra_args file + include_vars: "{{ item }}" + ignore_errors: yes + with_first_found: + - files: + - "../extra_vars.yml" + - "../extra_vars.yaml" + - "../extra_vars.json" + skip: true + tags: vars + +- name: Install mmtests build dependencies (RedHat/CentOS) + become: yes + become_method: sudo + yum: + name: + - gcc + - git + - perl + - perl-CPAN + - perl-Math-Gradient + - R + - R-devel + - libnuma-devel + - perl-Math-Gradient + state: present + tags: ['deps'] + +- name: Install mmtests runtime dependencies (RedHat/CentOS) + become: yes + become_method: sudo + yum: + name: + - numactl + - fio + - sysstat + - procps-ng + - util-linux + - coreutils + - time + - bc + - psmisc + state: present + tags: ['deps'] + +- name: Install mmtests monitoring dependencies (RedHat/CentOS) + become: yes + become_method: sudo + yum: + name: + - kernel-tools + - trace-cmd + - perf + state: present + tags: ['deps'] + ignore_errors: true diff --git a/playbooks/roles/mmtests/tasks/install-deps/suse/main.yml b/playbooks/roles/mmtests/tasks/install-deps/suse/main.yml new file mode 100644 index 00000000..2f0b7a2b --- /dev/null +++ b/playbooks/roles/mmtests/tasks/install-deps/suse/main.yml @@ -0,0 +1,57 @@ +--- +- name: Import optional extra_args file + include_vars: "{{ item }}" + ignore_errors: yes + with_first_found: + - files: + - "../extra_vars.yml" + - "../extra_vars.yaml" + - "../extra_vars.json" + skip: true + tags: vars + +- name: Install mmtests build dependencies (SUSE) + become: yes + become_method: sudo + zypper: + name: + - gcc + - git + - perl + - perl-CPAN + - perl-Math-Gradient + - R-base + - R-base-devel + - libnuma-devel + state: present + tags: ['deps'] + +- name: Install mmtests runtime dependencies (SUSE) + become: yes + become_method: sudo + zypper: + name: + - numactl + - fio + - sysstat + - procps + - util-linux + - coreutils + - time + - bc + - psmisc + - perl-Math-Gradient + state: present + tags: ['deps'] + +- name: Install mmtests monitoring dependencies (SUSE) + become: yes + become_method: sudo + zypper: + name: + - kernel-default-devel + - trace-cmd + - perf + state: present + tags: ['deps'] + ignore_errors: true diff --git a/playbooks/roles/mmtests/tasks/main.yaml b/playbooks/roles/mmtests/tasks/main.yaml new file mode 100644 index 00000000..93bc4bd9 --- /dev/null +++ b/playbooks/roles/mmtests/tasks/main.yaml @@ -0,0 +1,270 @@ +--- +# Install distribution-specific dependencies +- name: Install dependencies + include_tasks: install-deps/main.yml + tags: [ 'setup', 'deps' ] + +- include_role: + name: create_data_partition + tags: [ 'setup', 'data_partition' ] + +- include_role: + name: common + when: + - infer_uid_and_group|bool + +- name: Ensure data_dir has correct ownership + tags: [ 'setup' ] + become: yes + become_method: sudo + ansible.builtin.file: + path: "{{ data_path }}" + owner: "{{ data_user }}" + group: "{{ data_group }}" + recurse: yes + state: directory + +- name: Clone mmtests repository + tags: [ 'setup' ] + ansible.builtin.git: + repo: "{{ mmtests_git_url }}" + dest: "{{ mmtests_data_dir }}" + version: "{{ mmtests_git_version }}" + force: yes + +- name: Generate mmtests configuration + tags: [ 'setup' ] + become: yes + become_method: sudo + ansible.builtin.template: + src: "{{ mmtests_test_type }}-config.j2" + dest: "{{ mmtests_data_dir }}/configs/config-workload-{{ mmtests_test_type }}-kdevops" + owner: root + group: root + mode: '0644' + +- name: Fail if configured memory percentages overcommit available memory + fail: + msg: >- + Overcommit configuration: anonymous ({{ mmtests_anonymous_memory_percent }}%) + + file-backed ({{ mmtests_file_memory_percent }}%) exceeds 100% of available memory. + Adjust your mmtests_*_percent values in extra_vars.yaml. + when: (mmtests_anonymous_memory_percent + mmtests_file_memory_percent) > 100 + +- name: Run mmtests autogen in background + tags: [ 'setup' ] + become: true + become_method: sudo + ansible.builtin.command: ./bin/autogen-configs + args: + chdir: "{{ mmtests_data_dir }}" + +- name: Run mmtests autogen in background + tags: [ 'setup' ] + become: true + become_method: sudo + ansible.builtin.command: ./bin/autogen-configs + args: + chdir: "{{ mmtests_data_dir }}" + +- name: Get kernel version + tags: [ 'setup', 'run_tests' ] + ansible.builtin.command: uname -r + register: kernel_version + +- name: Show kernel version + tags: [ 'setup', 'run_tests' ] + debug: + msg: "Kernel version on {{ inventory_hostname }} : {{ kernel_version.stdout }}" + +- name: Build mmtests + tags: [ 'setup' ] + become: true + become_method: sudo + ansible.builtin.shell: > + yes yes | ./run-mmtests.sh -b + --config configs/config-workload-{{ mmtests_test_type }}-kdevops + {{ inventory_hostname }}-{{ kernel_version.stdout }} + args: + chdir: "{{ mmtests_data_dir }}" + register: mmtests_build_result + +- name: Fail if mmtests build failed + fail: + msg: > + mmtests build failed on {{ inventory_hostname }}. + Exit code: {{ mmtests_build_result.rc }} + Stdout: {{ mmtests_build_result.stdout }} + Stderr: {{ mmtests_build_result.stderr }} + when: mmtests_build_result.rc != 0 + tags: [ 'setup' ] + +- name: Check if {{ mmtests_device }} is mounted + tags: [ 'run_tests' ] + become: yes + become_method: sudo + command: findmnt --noheadings --output TARGET --source {{ mmtests_device }} + register: mountpoint_stat + failed_when: false + changed_when: false + when: mmtests_requires_mkfs_device | bool + +- name: Unmount {{ mmtests_device }} if mounted + tags: [ 'run_tests' ] + become: yes + become_method: sudo + command: umount {{ mmtests_device }} + when: + - mmtests_requires_mkfs_device | bool + - mountpoint_stat.stdout != "" + +# XXX: add variability for the different options for the governor +- name: Set CPU governor to performance + tags: [ 'run_tests' ] + become: yes + become_method: sudo + ansible.builtin.shell: | + for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do + if [ -f "$cpu" ]; then + echo "performance" > "$cpu" + fi + done + +- name: Drop caches before test + tags: [ 'run_tests' ] + become: yes + become_method: sudo + ansible.builtin.shell: | + sync + echo 3 > /proc/sys/vm/drop_caches + when: mmtests_pretest_dropvmcaches | bool + +- name: Configure THP + tags: [ 'run_tests' ] + become: yes + become_method: sudo + ansible.builtin.shell: | + echo "{{ mmtests_pretest_thp_setting }}" > /sys/kernel/mm/transparent_hugepage/enabled + +- name: Manually trigger memory compaction before run + tags: [ 'run_tests' ] + become: yes + become_method: sudo + ansible.builtin.shell: | + echo 1 > /proc/sys/vm/compact_memory + when: + - mmtests_pretest_compaction | bool + ignore_errors: true + +- name: Show kernel version + tags: [ 'run_tests' ] + debug: + msg: "Kernel version on {{ inventory_hostname }} : {{ kernel_version.stdout }}" + +- name: Run mmtests in background + tags: [ 'run_tests' ] + become: true + become_method: sudo + ansible.builtin.command: ./run-mmtests.sh --config configs/config-workload-{{ mmtests_test_type }}-kdevops {{ inventory_hostname }}-{{ kernel_version.stdout }} + args: + chdir: "{{ mmtests_data_dir }}" + async: 86400 # 24 hours + poll: 0 + register: mmtests_job + +- name: Wait for mmtests to complete + tags: [ 'run_tests' ] + become: true + become_method: sudo + ansible.builtin.async_status: + jid: "{{ mmtests_job.ansible_job_id }}" + register: mmtests_status + until: mmtests_status.finished + retries: 1440 # 12 hours + delay: 60 # check every 60 seconds + +- name: Create local results directory + delegate_to: localhost + ansible.builtin.file: + path: "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/" + state: directory + mode: '0755' + run_once: false + tags: ['results'] + +- name: Ensure old mmtests results archive is removed if it exists + become: yes + become_method: sudo + ansible.builtin.file: + path: "{{ mmtests_results_dir_basename }}/mmtests-results-{{ inventory_hostname }}.tar.gz" + state: absent + tags: [ 'results' ] + +- name: Archive mmtests results directory on remote host + become: yes + become_method: sudo + command: > + tar czf {{ mmtests_results_dir_basename }}/mmtests-results-{{ inventory_hostname }}.tar.gz -C {{ mmtests_results_dir }} . + args: + creates: "{{ mmtests_results_dir_basename }}/mmtests-results-{{ inventory_hostname }}.tar.gz" + tags: [ 'results' ] + +- name: Remove previously fetched mmtests results archive if it exists + become: no + delegate_to: localhost + ansible.builtin.file: + path: "{{ item }}" + state: absent + tags: [ 'results' ] + with_items: + - "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/mmtests-results-{{ inventory_hostname }}.tar.gz" + - "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/mmtests-results-{{ inventory_hostname }}" + +- name: Copy mmtests results + tags: [ 'results' ] + become: yes + become_method: sudo + ansible.builtin.fetch: + src: "{{ mmtests_results_dir_basename }}/mmtests-results-{{ inventory_hostname }}.tar.gz" + dest: "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/" + flat: yes + +- name: Ensure local mmtests results extraction directory exists + become: no + delegate_to: localhost + ansible.builtin.file: + path: "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/mmtests-results-{{ inventory_hostname }}" + state: directory + mode: '0755' + recurse: yes + tags: [ 'results' ] + +- name: Extract mmtests results archive locally + become: no + delegate_to: localhost + ansible.builtin.unarchive: + src: "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/mmtests-results-{{ inventory_hostname }}.tar.gz" + dest: "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}/mmtests-results-{{ inventory_hostname }}" + remote_src: no + tags: [ 'results' ] + +- name: Clean previous mmtests results on DUTs + tags: [ 'clean' ] + become: yes + become_method: sudo + ansible.builtin.file: + path: "{{ item }}" + state: absent + with_items: + - "{{ mmtests_results_dir }}" + +- name: Clean previous mmtests results on localhost + tags: [ 'clean' ] + become: yes + become_method: sudo + delegate_to: localhost + ansible.builtin.file: + path: "{{ item }}" + state: absent + with_items: + - "{{ topdir_path }}/workflows/mmtests/results/{{ inventory_hostname }}" diff --git a/playbooks/roles/mmtests/templates/thpchallenge-config.j2 b/playbooks/roles/mmtests/templates/thpchallenge-config.j2 new file mode 100644 index 00000000..3b4e6034 --- /dev/null +++ b/playbooks/roles/mmtests/templates/thpchallenge-config.j2 @@ -0,0 +1,76 @@ +### Automatically generated by kdevops {{ kdevops_version }} +### +### THPChallenge is a benchmark that allocates THPs while there is interference +### from a background workload. +### +### The THP test creates a number of threads, each of which faults a region that +### is THPCHALLENGE_THP_WSETSIZE/$NR_THREADS in size. Optionally the mapping +### will use madvise. The time to fault each page, the size allocated and the +### locality is recorded. +### +### The "challenge" load is fio inefficiently creating many small files, the +### total size of which is THPCHALLENGE_FIO_WSETSIZE +export MMTESTS="thpchallenge" + +{% if mmtests_requires_mkfs_device %} +export TESTDISK_PARTITION={{ mmtests_device }} +export TESTDISK_FILESYSTEM={{ mmtests_mkfs_type }} +export TESTDISK_MKFS_PARAM="{{ mmtests_mkfs_cmd }}" + +# Sadly there is no generic mkfs way to set sector size yet. +{% if mmtests_fs_xfs %} +export TESTDISK_MKFS_PARAM="$TESTDISK_MKFS_PARAM -s size={{ mmtests_xfs_sector_size }}" +{% elif mmtests_fs_ext4 %} +# ext4 has this odd environment variable thing. +export MKE2FS_DEVICE_SECTSIZE="{{ mmtests_ext4_sector_size }}" +{% endif %} + +export TESTDISK_MOUNT_ARGS= +{% endif %} + +{% if mmtests_monitor_enable_ftrace %} +# List of monitors +export MONITOR_FTRACE_EVENTS=" + compaction/mm_compaction_begin + compaction/mm_compaction_defer_compaction + compaction/mm_compaction_deferred + compaction/mm_compaction_defer_reset + compaction/mm_compaction_end + compaction/mm_compaction_finished + compaction/mm_compaction_isolate_freepages + compaction/mm_compaction_isolate_migratepages + compaction/mm_compaction_kcompactd_sleep + compaction/mm_compaction_kcompactd_wake + compaction/mm_compaction_migratepages + compaction/mm_compaction_suitable + compaction/mm_compaction_try_to_compact_pages + compaction/mm_compaction_wakeup_kcompactd + kmem/mm_page_alloc_extfrag" +{% endif %} + +{% if mmtests_monitor_enable_proc_monitoring %} +export MONITORS_GZIP="$MONITORS_GZIP proc-vmstat proc-buddyinfo proc-pagetypeinfo" +{% endif %} + +{% if mmtests_monitor_enable_mpstat %} +export MONITORS_GZIP="$MONITORS_GZIP mpstat" +{% endif %} + +export MONITORS_WITH_LATENCY="vmstat" +export MONITOR_UPDATE_FREQUENCY={{ mmtests_monitor_interval }} + +# Limit memory to 16GB per node to save storage and limit runtime +. $SHELLPACK_INCLUDE/include-sizes.sh +get_numa_details +limit_memory $((16*1048576*1024*NUMNODES)) + +# thpchallenge +export THPCHALLENGE_BACKGROUND="{{ mmtests_thpchallenge_background }}" +export THPCHALLENGE_FIO_THREADS={{ mmtests_thpchallenge_fio_threads }} +export THPCHALLENGE_MIN_THREADS=$((((NUMCPUS/NUMNODES)-THPCHALLENGE_FIO_THREADS)/4)) +export THPCHALLENGE_MAX_THREADS=$THPCHALLENGE_MIN_THREADS +if [ $THPCHALLENGE_MAX_THREADS -le 0 ]; then + die "Insufficient number of CPUs to run benchmark" +fi +export THPCHALLENGE_THP_WSETSIZE=$(( MEMTOTAL_BYTES * {{ mmtests_thpchallenge_thp_wsetsize }} / 100 )) +export THPCHALLENGE_FIO_WSETSIZE=$(( MEMTOTAL_BYTES * {{ mmtests_thpchallenge_fio_wsetsize }} / 100 )) diff --git a/playbooks/roles/mmtests/templates/thpcompact-config.j2 b/playbooks/roles/mmtests/templates/thpcompact-config.j2 new file mode 100644 index 00000000..001906b3 --- /dev/null +++ b/playbooks/roles/mmtests/templates/thpcompact-config.j2 @@ -0,0 +1,102 @@ +### Automatically generated by kdevops {{ kdevops_version }} +### +### This a benchmark that stresses THP allocations in a specific manner. +### +### THPCOMPACT_ANONSIZE is split based on the number of active threads at +### each stage of the test. The active memory for a thread is referred +### to as THREAD_ANONSIZE +### +### 1. It first creates a large THREAD_ANONSIZE anonymous mapping that is THP +### aligned, specifies madvise(MADV_HUGEPAGE) and faults it. It then punches +### holes in the (hopefully) THP mapping that are naturally aligned and +### half the size of a THP. This mapping is a migration source that frees +### pageblocks as the pages are moved. At this point, the migration source +### only has anonymous pages. +### +### 2. It then creates a THREAD_ANONSIZE/2 anonymous mapping that is not yet +### faulted. The size of this mapping represents the sum of the holes created +### in step 1. +### +### 3. A file mapping is created of size THREAD_FILE and the file is +### read-faulted. These are also potential migration sources as some of +### the holes will be used to store file-backed pages. +### +### 4. Finally the anonymous mapping created at step 2 is faulted while +### recording the time to fault, the locality and whether a huge page +### is used. +### +### The overall size of the workload is such that it should fit in memory while +### requiring compaction to allocate THPs for the final mapping. + +export MMTESTS="thpcompact" + +{% if mmtests_requires_mkfs_device %} +export TESTDISK_PARTITION={{ mmtests_device }} +export TESTDISK_FILESYSTEM={{ mmtests_mkfs_type }} +export TESTDISK_MKFS_PARAM="{{ mmtests_mkfs_cmd }}" + +# Sadly there is no generic mkfs way to set sector size yet. +{% if mmtests_fs_xfs %} +export TESTDISK_MKFS_PARAM="$TESTDISK_MKFS_PARAM -s size={{ mmtests_xfs_sector_size }}" +{% elif mmtests_fs_ext4 %} +# ext4 has this odd environment variable thing. +export MKE2FS_DEVICE_SECTSIZE="{{ mmtests_ext4_sector_size }}" +{% endif %} + +export TESTDISK_MOUNT_ARGS= +{% endif %} + +{% if mmtests_monitor_enable_ftrace %} +# List of monitors +export MONITOR_FTRACE_EVENTS=" + compaction/mm_compaction_begin + compaction/mm_compaction_defer_compaction + compaction/mm_compaction_deferred + compaction/mm_compaction_defer_reset + compaction/mm_compaction_end + compaction/mm_compaction_finished + compaction/mm_compaction_isolate_freepages + compaction/mm_compaction_isolate_migratepages + compaction/mm_compaction_kcompactd_sleep + compaction/mm_compaction_kcompactd_wake + compaction/mm_compaction_migratepages + compaction/mm_compaction_suitable + compaction/mm_compaction_try_to_compact_pages + compaction/mm_compaction_wakeup_kcompactd + kmem/mm_page_alloc_extfrag" +{% endif %} + +export RUN_MONITOR=yes +export MONITORS_ALWAYS= +export MONITORS_GZIP="" + +{% if mmtests_monitor_enable_proc_monitoring %} +export MONITORS_GZIP="$MONITORS_GZIP proc-vmstat proc-buddyinfo proc-pagetypeinfo" +{% endif %} + +{% if mmtests_monitor_enable_mpstat %} +export MONITORS_GZIP="$MONITORS_GZIP mpstat" +{% endif %} + +export MONITORS_WITH_LATENCY="vmstat" +export MONITOR_UPDATE_FREQUENCY={{ mmtests_monitor_interval }} + +export THPCOMPACT_MIN_THREADS={{ mmtests_thpcompact_threads_min }} + +{% if mmtests_thpcompact_threads_max_type_auto %} +export THPCOMPACT_MAX_THREADS={{ ansible_facts.processor_vcpus * 4 }} +{% elif mmtests_thpcompact_threads_max_type_manual %} +export THPCOMPACT_MAX_THREADS={{ mmtests_thpcompact_threads_max }} +{% endif %} + +export THPCOMPACT_ITERATIONS={{ mmtests_iterations }} + +# Memory configuration +export THPCOMPACT_ANONSIZE=$((MEMTOTAL_BYTES * {{ mmtests_thpcompact_anonymous_memory_percent }} / 100)) +export THPCOMPACT_FILESIZE=$((THPCOMPACT_ANONSIZE / {{ mmtests_thpcompact_filemap_memory_scale }} )) +export TESTDISK_MIN_SIZE=$((THPCOMPACT_FILESIZE*5/4)) + +RUN_WARMUP=no + +# Workload configuration - match original thpcompact behavior +THPCOMPACT_WORKLOAD="thpcompact" diff --git a/workflows/Makefile b/workflows/Makefile index 89f6d317..ef3cc2d1 100644 --- a/workflows/Makefile +++ b/workflows/Makefile @@ -54,6 +54,10 @@ ifeq (y,$(CONFIG_KDEVOPS_WORKFLOW_ENABLE_SYSBENCH)) include workflows/sysbench/Makefile endif # CONFIG_KDEVOPS_WORKFLOW_ENABLE_SYSBENCH == y +ifeq (y,$(CONFIG_KDEVOPS_WORKFLOW_ENABLE_MMTESTS)) +include workflows/mmtests/Makefile +endif # CONFIG_KDEVOPS_WORKFLOW_ENABLE_MMTESTS == y + ifeq (y,$(CONFIG_KDEVOPS_WORKFLOW_ENABLE_SSD_STEADY_STATE)) include workflows/steady_state/Makefile endif # CONFIG_KDEVOPS_WORKFLOW_ENABLE_SSD_STEADY_STATE == y diff --git a/workflows/mmtests/Kconfig b/workflows/mmtests/Kconfig new file mode 100644 index 00000000..6093bd0e --- /dev/null +++ b/workflows/mmtests/Kconfig @@ -0,0 +1,108 @@ +if KDEVOPS_WORKFLOW_ENABLE_MMTESTS + +config HAVE_MIRROR_MMTESTS + bool + depends on USE_LIBVIRT_MIRROR + default $(shell, scripts/check_mirror_present.sh /mirror/mmtests.git) + +config MMTESTS_GIT_URL + string "The mmtests git tree to clone" + output yaml + default $(shell, scripts/append-makefile-vars.sh git:// $(KDEVOPS_DEFAULT_BRIDGE_IP_GUESTFS) /mirror/mmtests.git) if HAVE_MIRROR_MMTESTS && GUESTFS + default DEFAULT_MMTESTS_GITHUB_HTTPS_URL if !HAVE_MIRROR_MMTESTS + help + The mmtests git tree to clone. + +config MMTESTS_TEST_TYPE + string + output yaml + default "thpcompact" if MMTESTS_ENABLE_THPCOMPACT + default "thpchallenge" if MMTESTS_ENABLE_THPCHALLENGE + +choice + prompt "mmtests test type" + default MMTESTS_ENABLE_THPCOMPACT + help + Select the type of mmtests test to run. + +config MMTESTS_ENABLE_THPCOMPACT + bool "thpcompact" + help + Run thpcompact test to stress THP allocations through multi-stage + memory allocation and migration. This test is designed to exercise + memory compaction and huge page allocation under various thread + counts while staying within system memory limits. + +config MMTESTS_ENABLE_THPCHALLENGE + bool "thpchallenge" + help + Run thpchallenge fio test which uses fio for background I/O + workload while testing THP allocation performance. + +endchoice + +config MMTESTS_ITERATIONS + int "Number of iterations per test" + default 5 + range 1 100 + output yaml + help + The number of iterations to run for each mmtests configuration. + +config MMTESTS_MONITOR_INTERVAL + int "Monitor update interval in seconds" + default 1 + range 1 60 + output yaml + help + The interval in seconds between monitoring updates during + mmtests execution. + +config MMTESTS_MONITOR_ENABLE_FTRACE + bool "Enable ftrace monitoring" + default y + output yaml + help + Enable ftrace events for compaction and kernel memory monitoring + during mmtests execution. + +config MMTESTS_MONITOR_ENABLE_PROC_MONITORING + bool "Enable /proc monitoring" + default y + output yaml + help + Enable monitoring of /proc/vmstat, /proc/buddyinfo, and + /proc/pagetypeinfo during mmtests execution. + +config MMTESTS_MONITOR_ENABLE_MPSTAT + bool "Enable mpstat monitoring" + default y + output yaml + help + Enable mpstat monitoring during mmtests execution. + +config MMTESTS_PRETEST_DROPVMCACHES + bool "Trigger to drop vm cache before the test" + output yaml + help + Manually trigger to drop the vm cache before the test. + +config MMTESTS_PRETEST_COMPACTION + bool "Trigger memory compaction before the test" + output yaml + help + Manually trigger memory comapction before run. + +config MMTESTS_PRETEST_THP_SETTING + string "THP setting" + default "always" + output yaml + help + Transparent huge page setting for all nodes. + Options: always, madvise, never + +source "workflows/mmtests/Kconfig.thpcompact" +source "workflows/mmtests/Kconfig.thpchallenge" +source "workflows/mmtests/Kconfig.fs" + +endif # KDEVOPS_WORKFLOW_ENABLE_MMTESTS diff --git a/workflows/mmtests/Kconfig.ext4 b/workflows/mmtests/Kconfig.ext4 new file mode 100644 index 00000000..58880a97 --- /dev/null +++ b/workflows/mmtests/Kconfig.ext4 @@ -0,0 +1,105 @@ +if MMTESTS_FS_EXT4 + +choice + prompt "ext4 filesystem configuration to use" + +config MMTESTS_FS_EXT4_4K_4KS + bool "ext4 4k - 4k sector size" + select MMTESTS_EXT4_SECTOR_SIZE_4K + output yaml + help + ext4 4k FSB with 4k sector size. + +config MMTESTS_FS_EXT4_4K_4KS_BIGALLOC_16K + bool "ext4 4k block size bigalloc 16k cluster sizes - 4k sector size" + select MMTESTS_EXT4_SECTOR_SIZE_4K + select MMTESTS_EXT4_SECTION_4K_BIGALLOC_16K + output yaml + help + ext4 4 KiB FSB with 4 KiB sector size, 16 KiB cluster sizes. + +config MMTESTS_FS_EXT4_4K_4KS_BIGALLOC_32K + bool "ext4 4k block size bigalloc 32k cluster sizes - 4k sector size" + select MMTESTS_EXT4_SECTOR_SIZE_4K + select MMTESTS_EXT4_SECTION_4K_BIGALLOC_32K + output yaml + help + ext4 4 KiB FSB with 4 KiB sector size, 32 KiB cluster sizes. + +config MMTESTS_FS_EXT4_4K_4KS_BIGALLOC_64K + bool "ext4 4k block size bigalloc 64k cluster sizes - 4k sector size" + select MMTESTS_EXT4_SECTOR_SIZE_4K + select MMTESTS_EXT4_SECTION_4K_BIGALLOC_64K + output yaml + help + ext4 4 KiB FSB with 4 KiB sector size, 64 KiB cluster sizes. + +endchoice + +choice + prompt "EXT4 filesystem sector size to use" + default MMTESTS_EXT4_SECTOR_SIZE_4K + +config MMTESTS_EXT4_SECTOR_SIZE_512 + bool "512 bytes" + output yaml + depends on EXTRA_STORAGE_SUPPORTS_512 + help + Use 512 byte sector size. + +config MMTESTS_EXT4_SECTOR_SIZE_4K + bool "4 KiB" + output yaml + depends on EXTRA_STORAGE_SUPPORTS_4K + help + Use 4 KiB sector size. + +endchoice + +config MMTESTS_EXT4_SECTOR_SIZE + string + output yaml + default "512" if MMTESTS_EXT4_SECTOR_SIZE_512 + default "4k" if MMTESTS_EXT4_SECTOR_SIZE_4K + +config MMTESTS_EXT4_SECTION_4K + bool + +config MMTESTS_EXT4_SECTION_4K_CMD + string + depends on MMTESTS_EXT4_SECTION_4K + default "-F -b 4k" + +config MMTESTS_EXT4_SECTION_4K_BIGALLOC_16K + bool + +config MMTESTS_EXT4_SECTION_4K_BIGALLOC_16K_CMD + string + depends on MMTESTS_EXT4_SECTION_4K_BIGALLOC_16K + default "-F -b 4k -O bigalloc -C 16k" + +config MMTESTS_EXT4_SECTION_4K_BIGALLOC_32K + bool + +config MMTESTS_EXT4_SECTION_4K_BIGALLOC_32K_CMD + string + depends on MMTESTS_EXT4_SECTION_4K_BIGALLOC_32K + default "-F -b 4k -O bigalloc -C 32k" + +config MMTESTS_EXT4_SECTION_4K_BIGALLOC_64K + bool + +config MMTESTS_EXT4_SECTION_4K_BIGALLOC_64K_CMD + string + depends on MMTESTS_EXT4_SECTION_4K_BIGALLOC_64K + default "-F -b 4k -O bigalloc -C 64k" + +config MMTESTS_EXT4_CMD + string + output yaml + default MMTESTS_EXT4_SECTION_4K_CMD if MMTESTS_FS_EXT4_4K_4KS + default MMTESTS_EXT4_SECTION_4K_BIGALLOC_16K_CMD if MMTESTS_FS_EXT4_4K_4KS_BIGALLOC_16K + default MMTESTS_EXT4_SECTION_4K_BIGALLOC_32K_CMD if MMTESTS_FS_EXT4_4K_4KS_BIGALLOC_32K + default MMTESTS_EXT4_SECTION_4K_BIGALLOC_64K_CMD if MMTESTS_FS_EXT4_4K_4KS_BIGALLOC_64K + +endif # MMTESTS_FS_EXT4 diff --git a/workflows/mmtests/Kconfig.fs b/workflows/mmtests/Kconfig.fs new file mode 100644 index 00000000..9ebd1f6d --- /dev/null +++ b/workflows/mmtests/Kconfig.fs @@ -0,0 +1,80 @@ +config MMTESTS_REQUIRES_MKFS_DEVICE + bool + output yaml + +choice + prompt "Filesystem configuration to use" + default MMTESTS_FS_XFS + help + The target type of filesystem test to use or none. + +config MMTESTS_FS_SKIP + bool "Skip - don't use a filesystem" + output yaml + help + Disable filesystem testing. + +config MMTESTS_FS_XFS + bool "XFS" + output yaml + select MMTESTS_REQUIRES_MKFS_DEVICE + help + Enable if you want to test mmtests against XFS. + +config MMTESTS_FS_EXT4 + bool "ext4" + output yaml + select MMTESTS_REQUIRES_MKFS_DEVICE + help + Enable if you want to test mmtests against ext4. + +endchoice + +if MMTESTS_REQUIRES_MKFS_DEVICE + +source "workflows/mmtests/Kconfig.xfs" +source "workflows/mmtests/Kconfig.ext4" + +config MMTESTS_MKFS_TYPE + output yaml + default "xfs" if MMTESTS_FS_XFS + default "ext4" if MMTESTS_FS_EXT4 + +config MMTESTS_MKFS_CMD + string "mkfs command to use" + output yaml + default MMTESTS_XFS_CMD if MMTESTS_FS_XFS + default MMTESTS_EXT4_CMD if MMTESTS_FS_EXT4 + help + The filesystem mkfs configuration command to run + +config MMTESTS_DEVICE + string "Device to use to create a filesystem for sysbench tests" + output yaml + default "/dev/disk/by-id/nvme-QEMU_NVMe_Ctrl_kdevops1" if LIBVIRT && LIBVIRT_EXTRA_STORAGE_DRIVE_NVME + default "/dev/disk/by-id/virtio-kdevops1" if LIBVIRT && LIBVIRT_EXTRA_STORAGE_DRIVE_VIRTIO + default "/dev/disk/by-id/ata-QEMU_HARDDISK_kdevops1" if LIBVIRT && LIBVIRT_EXTRA_STORAGE_DRIVE_IDE + default "/dev/nvme2n1" if TERRAFORM_AWS_INSTANCE_M5AD_2XLARGE + default "/dev/nvme2n1" if TERRAFORM_AWS_INSTANCE_M5AD_4XLARGE + default "/dev/nvme1n1" if TERRAFORM_GCE + default "/dev/sdd" if TERRAFORM_AZURE + default TERRAFORM_OCI_SPARSE_VOLUME_DEVICE_FILE_NAME if TERRAFORM_OCI + help + The device to use to create a filesystem where we will place the + database. + +config MMTESTS_LABEL + string "The label to use" + output yaml + default "mmtests" + help + The label to use when creating the filesystem. + +config MMTESTS_MNT + string "Mount point for the database" + output yaml + default "/mmtests-test" + help + The path where to mount the filesystem testing. + +endif diff --git a/workflows/mmtests/Kconfig.thpchallenge b/workflows/mmtests/Kconfig.thpchallenge new file mode 100644 index 00000000..f0053c21 --- /dev/null +++ b/workflows/mmtests/Kconfig.thpchallenge @@ -0,0 +1,52 @@ +if MMTESTS_ENABLE_THPCHALLENGE + +config MMTESTS_THPCHALLENGE_BACKGROUND + string "Background workload for THP challenge" + output yaml + default "fio-random-reader-inefficient" + help + Name of the background workload to use during the THP challenge. + This workload is typically one that causes memory fragmentation. + +config MMTESTS_THPCHALLENGE_FIO_THREADS + int "Number of FIO threads for THP challenge background workload" + output yaml + default 4 + help + The number of FIO threads used for the background memory + fragmentation workload during the THP challenge benchmark. + +config MMTESTS_THPCHALLENGE_MIN_THREADS + int "Minimum number of threads for THP workload" + output yaml + default 1 + help + Minimum number of threads used in the THP challenge benchmark. + This is typically computed as a function of NUMCPUS and NUMNODES. + If unsure, leave at default and let the runtime environment compute it. + +config MMTESTS_THPCHALLENGE_MAX_THREADS + int "Maximum number of threads for THP workload" + output yaml + default 1 + help + Maximum number of threads used in the THP challenge benchmark. + Should be equal to or greater than MIN_THREADS. + +config MMTESTS_THPCHALLENGE_THP_WSETSIZE + int "Working set size for THP workload - percertage" + output yaml + range 1 100 + help + Working set size for the main THP challenge workload. + Typically 80% of total system memory. + +config MMTESTS_THPCHALLENGE_FIO_WSETSIZE + int "Working set size for FIO workload - percentage" + output yaml + range 1 200 + help + Working set size for the background FIO workload in the THP challenge. + Typically 150% of total system memory. + +endif # MMTESTS_ENABLE_THPCHALLENGE diff --git a/workflows/mmtests/Kconfig.thpcompact b/workflows/mmtests/Kconfig.thpcompact new file mode 100644 index 00000000..1c458335 --- /dev/null +++ b/workflows/mmtests/Kconfig.thpcompact @@ -0,0 +1,62 @@ +if MMTESTS_ENABLE_THPCOMPACT + +config MMTESTS_THPCOMPACT_THREADS_MIN + int "Minimum number of threads to use for mmtests" + default 1 + range 1 128 + output yaml + help + The minimum number of threads to use for mmtests runs. + +choice + prompt "mmtests max thread count strategy" + default MMTESTS_THREADS_MAX_TYPE_AUTO + help + Select the strategy to set the maximum number of threads we'll use. + +config MMTESTS_THPCOMPACT_THREADS_MAX_TYPE_AUTO + bool "auto" + output yaml + help + We use a heuristic to use 4 times the number of threads the system has + so 4 * $(nproc). + +config MMTESTS_THPCOMPACT_THREADS_MAX_TYPE_MANUAL + bool "manual" + output yaml + help + Lets you select the max number of threads mmtests will use. + +endchoice + +if MMTESTS_THPCOMPACT_THREADS_MAX_TYPE_MANUAL + +config MMTESTS_THPCOMPACT_THREADS_MAX + int "Maximum number of threads to use for mmtests" + default 32 + range 1 128 + output yaml + help + The maximum number of threads to use for mmtests runs. + +endif + +config MMTESTS_THPCOMPACT_ANONYMOUS_MEMORY_PERCENT + int "Percentage of system memory to use for anonymous memory" + default 80 + range 10 95 + output yaml + help + The percentage of total system memory to use for anonymous + memory allocation during tests. + +config MMTESTS_THPCOMPACT_FILEMAP_MEMORY_SCALE + int "How much to scale file memory used" + default 4 + output yaml + help + The amount of scaling of memory in comparison to anonymous memory to + use for file mappings. Is set set to 4 then we'll use the 1/4th the + amount of set for MMTESTS_ANONYMOUS_MEMORY_PERCENT. + +endif # MMTESTS_ENABLE_THPCOMPACT diff --git a/workflows/mmtests/Kconfig.xfs b/workflows/mmtests/Kconfig.xfs new file mode 100644 index 00000000..0a68d020 --- /dev/null +++ b/workflows/mmtests/Kconfig.xfs @@ -0,0 +1,211 @@ +if MMTESTS_FS_XFS + +choice + prompt "XFS filesystem configuration to use" + default MMTESTS_FS_XFS_4K_4KS + +config MMTESTS_FS_XFS_4K_4KS + bool "XFS 4k LBS - 4k sector size" + select MMTESTS_XFS_SECTOR_SIZE_4K + select MMTESTS_XFS_SECTION_REFLINK_4K + output yaml + help + XFS with 4k FSB with 4k sector size. + +config MMTESTS_FS_XFS_8K_4KS + bool "XFS 8k LBS - 4k sector size" + select MMTESTS_XFS_SECTOR_SIZE_4K + select MMTESTS_XFS_SECTION_REFLINK_16K + output yaml + help + XFS with 8k FSB with 4k sector size. + +config MMTESTS_FS_XFS_16K_4KS + bool "XFS 16k LBS - 4k sector size" + select MMTESTS_XFS_SECTOR_SIZE_4K + select MMTESTS_XFS_SECTION_REFLINK_16K + output yaml + help + XFS with 16k FSB with 4k sector size. + +config MMTESTS_FS_XFS_32K_4KS + bool "XFS 32k LBS - 4k sector size" + select MMTESTS_XFS_SECTOR_SIZE_4K + select MMTESTS_XFS_SECTION_REFLINK_32K + output yaml + help + XFS with 32k FSB with 4k sector size. + +config MMTESTS_FS_XFS_64K_4KS + bool "XFS 64k LBS - 4k sector size" + select MMTESTS_XFS_SECTOR_SIZE_4K + select MMTESTS_XFS_SECTION_REFLINK_64K + output yaml + help + XFS with 64k FSB with 8k sector size. + +config MMTESTS_FS_XFS_8K_8KS + bool "XFS 8k LBS - 8k sector size" + select MMTESTS_XFS_SECTOR_SIZE_8K + select MMTESTS_XFS_SECTION_REFLINK_16K + output yaml + help + XFS with 8k FSB with 8k sector size. + +config MMTESTS_FS_XFS_16K_8KS + bool "XFS 16k LBS - 8k sector size" + select MMTESTS_XFS_SECTOR_SIZE_8K + select MMTESTS_XFS_SECTION_REFLINK_16K + output yaml + help + XFS with 16k FSB with 8k sector size. + +config MMTESTS_FS_XFS_32K_8KS + bool "XFS 32k LBS - 8k sector size" + select MMTESTS_XFS_SECTOR_SIZE_8K + select MMTESTS_XFS_SECTION_REFLINK_32K + output yaml + help + XFS with 32k FSB with 8k sector size. + +config MMTESTS_FS_XFS_64K_8KS + bool "XFS 64k LBS - 8k sector size" + select MMTESTS_XFS_SECTOR_SIZE_8K + select MMTESTS_XFS_SECTION_REFLINK_64K + output yaml + help + XFS with 64k FSB with 8k sector size. + +config MMTESTS_FS_XFS_16K_16KS + bool "XFS 16k LBS - 16k sector size" + select MMTESTS_XFS_SECTOR_SIZE_16K + select MMTESTS_XFS_SECTION_REFLINK_16K + output yaml + help + XFS with 16k FSB with 16k sector size. + +config MMTESTS_FS_XFS_32K_16KS + bool "XFS 32k LBS - 16k sector size" + select MMTESTS_XFS_SECTOR_SIZE_16K + select MMTESTS_XFS_SECTION_REFLINK_32K + output yaml + help + XFS with 32k FSB with 16k sector size. + +config MMTESTS_FS_XFS_64K_16KS + bool "XFS 64k LBS - 16k sector size" + select MMTESTS_XFS_SECTOR_SIZE_16K + select MMTESTS_XFS_SECTION_REFLINK_64K + output yaml + help + XFS with 64k FSB with 16k sector size. + +config MMTESTS_FS_XFS_32K_32KS + bool "XFS 32k LBS - 32k sector size" + select MMTESTS_XFS_SECTOR_SIZE_32K + select MMTESTS_XFS_SECTION_REFLINK_32K + output yaml + help + XFS with 32k FSB with 32k sector size. + +config MMTESTS_FS_XFS_64K_32KS + bool "XFS 64k LBS - 32k sector size" + select MMTESTS_XFS_SECTOR_SIZE_32K + select MMTESTS_XFS_SECTION_REFLINK_64K + output yaml + help + XFS with 64k FSB with 32k sector size. + +endchoice + +choice + prompt "XFS filesystem sector size to use" + default MMTESTS_XFS_SECTOR_SIZE_4K + +config MMTESTS_XFS_SECTOR_SIZE_512 + bool "512 bytes" + output yaml + depends on EXTRA_STORAGE_SUPPORTS_512 + help + Use 512 byte sector size. + +config MMTESTS_XFS_SECTOR_SIZE_4K + bool "4 KiB" + output yaml + depends on EXTRA_STORAGE_SUPPORTS_4K + help + Use 4 KiB sector size. + +config MMTESTS_XFS_SECTOR_SIZE_16K + bool "16 KiB" + output yaml + depends on EXTRA_STORAGE_SUPPORTS_LARGEIO + help + Use 16 KiB sector size. + +config MMTESTS_XFS_SECTOR_SIZE_32K + bool "32 KiB" + output yaml + depends on EXTRA_STORAGE_SUPPORTS_LARGEIO + help + Use 32 KiB sector size. + +endchoice + +config MMTESTS_XFS_SECTOR_SIZE + string + output yaml + default "512" if MMTESTS_XFS_SECTOR_SIZE_512 + default "4k" if MMTESTS_XFS_SECTOR_SIZE_4K + default "16k" if MMTESTS_XFS_SECTOR_SIZE_16K + default "32k" if MMTESTS_XFS_SECTOR_SIZE_32K + +config MMTESTS_XFS_SECTION_REFLINK_4K + bool + +config MMTESTS_XFS_SECTION_REFLINK_4K_CMD + string + depends on MMTESTS_XFS_SECTION_REFLINK_4K + default "-f -m reflink=1,rmapbt=1, -i sparse=1 -b size=4k" + +config MMTESTS_XFS_SECTION_REFLINK_8K + bool + +config MMTESTS_XFS_SECTION_REFLINK_8K_CMD + string + depends on MMTESTS_XFS_SECTION_REFLINK_8K + default "-f -m reflink=1,rmapbt=1 -i sparse=1 -b size=8k" + +config MMTESTS_XFS_SECTION_REFLINK_16K + bool + +config MMTESTS_XFS_SECTION_REFLINK_16K_CMD + string + depends on MMTESTS_XFS_SECTION_REFLINK_16K + default "-f -m reflink=1,rmapbt=1 -i sparse=1 -b size=16k" + +config MMTESTS_XFS_SECTION_REFLINK_32K + bool + +config MMTESTS_XFS_SECTION_REFLINK_32K_CMD + string + depends on MMTESTS_XFS_SECTION_REFLINK_32K + default "-f -m reflink=1,rmapbt=1 -i sparse=1 -b size=32k" + +config MMTESTS_XFS_SECTION_REFLINK_64K + bool + +config MMTESTS_XFS_SECTION_REFLINK_64K_CMD + string + depends on MMTESTS_XFS_SECTION_REFLINK_64K + default "-f -m reflink=1,rmapbt=1 -i sparse=1 -b size=64k" + +config MMTESTS_XFS_CMD + string + default MMTESTS_XFS_SECTION_REFLINK_4K_CMD if MMTESTS_FS_XFS_4K_4KS + default MMTESTS_XFS_SECTION_REFLINK_8K_CMD if MMTESTS_XFS_SECTION_REFLINK_8K + default MMTESTS_XFS_SECTION_REFLINK_16K_CMD if MMTESTS_XFS_SECTION_REFLINK_16K + default MMTESTS_XFS_SECTION_REFLINK_32K_CMD if MMTESTS_XFS_SECTION_REFLINK_32K + default MMTESTS_XFS_SECTION_REFLINK_64K_CMD if MMTESTS_XFS_SECTION_REFLINK_64K + +endif # MMTESTS_FS_XFS diff --git a/workflows/mmtests/Makefile b/workflows/mmtests/Makefile new file mode 100644 index 00000000..cfccd6b2 --- /dev/null +++ b/workflows/mmtests/Makefile @@ -0,0 +1,68 @@ +MMTESTS_ARGS := + +ifeq (y,$(CONFIG_WORKFLOWS_DEDICATED_WORKFLOW)) +export KDEVOPS_HOSTS_TEMPLATE := mmtests.j2 +endif + +mmtests: + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \ + -i hosts playbooks/mmtests.yml \ + --extra-vars=@./extra_vars.yaml \ + --tags deps,setup + $(MMTESTS_ARGS) + +mmtests-baseline: + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \ + -i hosts -l baseline playbooks/mmtests.yml + --extra-vars=@./extra_vars.yaml \ + --tags run_tests \ + $(MMTESTS_ARGS) + +mmtests-dev: + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \ + -i hosts -l dev playbooks/mmtests.yml \ + --extra-vars=@./extra_vars.yaml \ + --tags run_tests \ + $(MMTESTS_ARGS) + +mmtests-test: mmtests + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \ + -i hosts playbooks/mmtests.yml \ + --extra-vars=@./extra_vars.yaml \ + --tags run_tests,results \ + $(MMTESTS_ARGS) + +mmtests-results: + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \ + -i hosts playbooks/mmtests.yml \ + --extra-vars=@./extra_vars.yaml \ + --tags results \ + $(MMTESTS_ARGS) + +mmtests-clean: + $(Q)ansible-playbook $(ANSIBLE_VERBOSE) \ + -i hosts playbooks/mmtests.yml \ + --extra-vars=@./extra_vars.yaml \ + --tags clean \ + $(MMTESTS_ARGS) + +mmtests-help: + @echo "mmtests targets:" + @echo "mmtests : Setup and install mmtests" + @echo "mmtests-baseline : Setup mmtests with baseline configuration" + @echo "mmtests-dev : Setup mmtests with dev configuration" + @echo "mmtests-test : Run mmtests tests" + @echo "mmtests-results : Copy results from guests" + @echo "mmtests-clean : Clean up mmtests installation" + @echo "" + +HELP_TARGETS += mmtests-help + +PHONY +: mmtests +PHONY +: mmtests-baseline +PHONY +: mmtests-dev +PHONY +: mmtests-test +PHONY +: mmtests-results +PHONY +: mmtests-clean +PHONY +: mmtests-help +.PHONY: $(PHONY) -- 2.47.2