From 5a3ca6f24c6e7e975739fa35840965f44f8a842a Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 22 Nov 2024 14:20:21 +0100 Subject: [PATCH 01/52] start doc #90 --- docs/modules/tutorial/pages/index.adoc | 68 ++++++++++++++++++++++++++ docs/modules/tutorial/pages/nav.adoc | 0 2 files changed, 68 insertions(+) create mode 100644 docs/modules/tutorial/pages/index.adoc create mode 100644 docs/modules/tutorial/pages/nav.adoc diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc new file mode 100644 index 00000000..7e7d39a2 --- /dev/null +++ b/docs/modules/tutorial/pages/index.adoc @@ -0,0 +1,68 @@ += feelpp.benchmarkign project + +== Introduction + +The _Feel++ benchmarking_ project provides a framework for automating, centralizing and organizing performance evaluation of scientific simulations on HPC systems. +This project, based on the ReFrame-hpc[TODO: Link] framework, enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. +It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. +TODO... + +== Getting started + +=== Installation + +. Clone the Repository +[source,cmd] +---- +git clone https://github.com/feelpp/benchmarking.git +---- + +. Use a python virtual environment [Optional] +[source,cmd] +---- +python3 -m venv .venv +source .venv/bin/activate +---- + +. Build the project +[source,cmd] +---- +pip3 wheel --no-deps --wheel-dir dist . +---- + +. Install requirements + +This will install necessary dependencies as well as the built project from the previous step. +[source,cmd] +---- +python3 -m pip install -r requirements.txt +---- + +=== Initial setup +TODO + +== Configuration guide + +=== System configuration + +=== Magic strings + +=== Machine configuration + +=== Benchmark configuration + +=== Overview configuration + +=== Plots configuration + +== Benchmarking Workflow + +== Interpreting Benchmarks + +== CI/CD and Automation + +== Versioning + +== Advanced usage + +== Examples \ No newline at end of file diff --git a/docs/modules/tutorial/pages/nav.adoc b/docs/modules/tutorial/pages/nav.adoc new file mode 100644 index 00000000..e69de29b From 3ae7e5e0e68b25e426cbc3af831877c18efa8020 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 10:26:54 +0100 Subject: [PATCH 02/52] start quickstart #90 --- docs/modules/tutorial/pages/index.adoc | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index 7e7d39a2..f915e366 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -1,11 +1,14 @@ = feelpp.benchmarkign project -== Introduction +== Welcome to Feel++ Benchmarking The _Feel++ benchmarking_ project provides a framework for automating, centralizing and organizing performance evaluation of scientific simulations on HPC systems. -This project, based on the ReFrame-hpc[TODO: Link] framework, enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. +This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. -TODO... + +== How it works + + == Getting started @@ -38,8 +41,20 @@ This will install necessary dependencies as well as the built project from the p python3 -m pip install -r requirements.txt ---- -=== Initial setup -TODO +=== Quickstart + +The framwork includes a sample C++/MPI application that can be used to get familiar with the framework's core concepts. It can be found under _tests/data/parallelSum.cpp_. + +This Feel++ Benchmarking "Hello World" application will compute the sum of an array distributed across multiple MPI processes. Each process will compute a partial sum, and then it will be summed to get the total sum. + +Additionally, the app will measure the time taken to perform the partial sum, and will save it under a _scalability.json_ file. + +The executable is already provided as _tests/data/parallelSum_. + +- Where configs are, (also reframe config). +- execute-benchmark + + == Configuration guide From a619c0e799d7b6ab1880873bcfe663e832faf345 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:11:17 +0100 Subject: [PATCH 03/52] up local config --- .../benchmarking/reframe/config/machineConfigs/local.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py b/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py index 4f84464b..113e96db 100644 --- a/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py +++ b/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py @@ -10,7 +10,7 @@ 'name': 'default', 'scheduler': 'local', 'launcher': 'mpiexec', - 'environs': ['env_local'], + 'environs': ['builtin'], 'processor': { 'num_cpus': 8 }, @@ -26,10 +26,9 @@ ], 'environments': [ { - 'name': 'env_local', - 'cc': 'gcc', - 'cxx': 'g++', - 'ftn': 'gfortran', + 'name': 'builtin', + 'cc': 'clang', + 'cxx': 'clang++', 'target_systems': ['local:default'] } ] From 92bd14c397fde4b7a2c9ba5ce4bc1f6ead3d2fdd Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:11:49 +0100 Subject: [PATCH 04/52] add local config --- config/machines/local.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 config/machines/local.json diff --git a/config/machines/local.json b/config/machines/local.json new file mode 100644 index 00000000..a49c7cc2 --- /dev/null +++ b/config/machines/local.json @@ -0,0 +1,17 @@ +{ + "machine": "local", + "execution_policy": "async", + "partitions":["default"], + "prog_environment":"builtin", + "reframe_base_dir":"$PWD/build/reframe", + "reports_base_dir":"$PWD/reports/", + "input_dataset_base_dir":"$HOME/Documents", + "output_app_dir":"$HOME/Documents/Repos/benchmarking" + // "containers":{ + // "apptainer":{ + // "cachedir": "/home/u2/cladellash/.apptainer/cache", + // "tmpdir": "/data/scratch/cladellash/images/tmp", + // "image_base_dir":"/data/scratch/cladellash/images" + // } + // } +} \ No newline at end of file From 009383d3fee90c62266b042d5f2095bd3a5a0f00 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:12:07 +0100 Subject: [PATCH 05/52] dont use pwd --- config/machines/local.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/machines/local.json b/config/machines/local.json index a49c7cc2..29f5c144 100644 --- a/config/machines/local.json +++ b/config/machines/local.json @@ -3,8 +3,8 @@ "execution_policy": "async", "partitions":["default"], "prog_environment":"builtin", - "reframe_base_dir":"$PWD/build/reframe", - "reports_base_dir":"$PWD/reports/", + "reframe_base_dir":"$HOME/Documents/Repos/benchmarking/build/reframe", + "reports_base_dir":"$HOME/Documents/Repos/benchmarking/reports/", "input_dataset_base_dir":"$HOME/Documents", "output_app_dir":"$HOME/Documents/Repos/benchmarking" // "containers":{ From 5c79185ae443e7792226946aad964eda306aa043 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:28:55 +0100 Subject: [PATCH 06/52] up test app --- tests/data/parallelSum | Bin 106040 -> 83880 bytes tests/data/parallelSum.cpp | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/data/parallelSum b/tests/data/parallelSum index be65dfb02801e0cab061cdafd61566eef9997ec0..1083c78bb8d1841101b6eab721bb377128efad04 100755 GIT binary patch literal 83880 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 diff --git a/tests/data/parallelSum.cpp b/tests/data/parallelSum.cpp index 11bad835..1d9a5508 100644 --- a/tests/data/parallelSum.cpp +++ b/tests/data/parallelSum.cpp @@ -79,11 +79,12 @@ int main(int argc, char** argv) } else std::cerr << "[OOPSIE] Error opening file for writing [outputs]." << std::endl; + + std::cout << "[SUCCESS]" << std::endl; } MPI_Finalize(); - std::cout << "[SUCCESS]" << std::endl; return 0; } \ No newline at end of file From 9352822bdabffab1d168acd534ee69e9865394a2 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:29:43 +0100 Subject: [PATCH 07/52] up config (lower cores) --- config/tests_parallelSum/parallelSum.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/config/tests_parallelSum/parallelSum.json b/config/tests_parallelSum/parallelSum.json index 109a0975..88214b61 100644 --- a/config/tests_parallelSum/parallelSum.json +++ b/config/tests_parallelSum/parallelSum.json @@ -1,5 +1,5 @@ { - "executable": "/data/home/cladellash/benchmarking/tests/data/parallelSum", + "executable": "$PWD/tests/data/parallelSum", "output_directory": "{{machine.output_app_dir}}/tests/parallelSum", "use_case_name": "parallel_sum", "timeout":"0-0:5:0", @@ -26,7 +26,7 @@ }, "sanity": { "success": ["[SUCCESS]"], - "error": ["[OOPSIE]","Error"] + "error": ["OOPSIE","Error"] }, "parameters": [ { @@ -35,8 +35,7 @@ {"tasks" : 1, "nodes":1, "exclusive_access":true}, {"tasks" : 2, "nodes":1, "exclusive_access":true}, {"tasks" : 4, "nodes":1, "exclusive_access":true}, - {"tasks" : 8, "nodes":1, "exclusive_access":true}, - {"tasks" : 16, "nodes":1, "exclusive_access":true} + {"tasks" : 8, "nodes":1, "exclusive_access":true} ] }, { From 121e79f5c56dae8e5d9dc998ec1c0955e92fff2f Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:45:11 +0100 Subject: [PATCH 08/52] start config guide #90 --- docs/modules/tutorial/pages/index.adoc | 44 ++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index f915e366..8b4aad3e 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -6,10 +6,6 @@ The _Feel++ benchmarking_ project provides a framework for automating, centraliz This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. -== How it works - - - == Getting started === Installation @@ -49,17 +45,51 @@ This Feel++ Benchmarking "Hello World" application will compute the sum of an ar Additionally, the app will measure the time taken to perform the partial sum, and will save it under a _scalability.json_ file. -The executable is already provided as _tests/data/parallelSum_. +The executable is already provided as _tests/data/parallelSum_. You can update it for a specific config +[source,cmd] +---- +mpic++ -std=c++17 -o test/data/parallelSum test/data/parallelSum.cpp +---- + +Local configuration files can be found under _config/test_parallelSum/_. They are explained more in detail in the following sections. +They might require specific configurations depending on the system you are running the framework. + +Finally, to benchmark the test application, generate the reports and plot the figures, run +[source,cmd] +---- +execute-benchmark --machine-config config/machines/local.json --benchmark-config config/test_parallelSum/parallelSum.json --plots-config config/test_parallelSum/plots.json --website +---- -- Where configs are, (also reframe config). -- execute-benchmark +The `--website` option will start an http-server on localhost, so the website can be visualized, check the console for more information. +== How it works +TODO: == Configuration guide +TODO: intro +- Different config files, introduce special syntaxes, supported envs, + === System configuration +The system configuration files need to be placed under _src/feelpp/benchmarking/reframe/config/machineConfigs_, and are strictly ReFrame dependent. A single Python file should be provided per machine. Please follow https://reframe-hpc.readthedocs.io/en/stable/config_reference.html[ReFrame's configuration file reference] for precise settings. + +Example configurations are provided for the _Gaya_ machine and for a simple single node 8-core system. + +[NOTE] +Processor bindings and other launcher options should be specified as a resource under the desired partition, with the `launcher_options` name field value for example. For example, + +[source,json] +---- +"resources": [ + { + "name":"launcher_options", + "options":["-bind-to","core"] + } +] +---- + === Magic strings === Machine configuration From 7aeddc641040e23a22fdf1e7fab589062b9789e0 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:53:07 +0100 Subject: [PATCH 09/52] add docs as module #90 --- docs/antora.yml | 2 +- docs/modules/ROOT/nav.adoc | 2 ++ docs/modules/nav.adoc | 1 + docs/modules/tutorial/{pages => }/nav.adoc | 0 4 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/modules/ROOT/nav.adoc create mode 100644 docs/modules/nav.adoc rename docs/modules/tutorial/{pages => }/nav.adoc (100%) diff --git a/docs/antora.yml b/docs/antora.yml index c00d4998..576711cc 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -17,4 +17,4 @@ ext: collector: nav: - modules/ROOT/nav.adoc - + - modules/tutorial/nav.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc new file mode 100644 index 00000000..f3ea0b6c --- /dev/null +++ b/docs/modules/ROOT/nav.adoc @@ -0,0 +1,2 @@ +* xref:ROOT:index.adoc[Benchmarks] +* xref:tutorial:index.adoc[Documentation] \ No newline at end of file diff --git a/docs/modules/nav.adoc b/docs/modules/nav.adoc new file mode 100644 index 00000000..8f7da779 --- /dev/null +++ b/docs/modules/nav.adoc @@ -0,0 +1 @@ +* xref:tutorial/index.adoc[Documentation] \ No newline at end of file diff --git a/docs/modules/tutorial/pages/nav.adoc b/docs/modules/tutorial/nav.adoc similarity index 100% rename from docs/modules/tutorial/pages/nav.adoc rename to docs/modules/tutorial/nav.adoc From 03b59862bcbd70340ca9c993911bc609dd033eb0 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 26 Nov 2024 11:55:57 +0100 Subject: [PATCH 10/52] small doc fix #90 --- docs/modules/tutorial/pages/index.adoc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index 8b4aad3e..10f5962f 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -10,26 +10,26 @@ It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking === Installation -. Clone the Repository +1. Clone the Repository [source,cmd] ---- git clone https://github.com/feelpp/benchmarking.git ---- -. Use a python virtual environment [Optional] +2. Use a python virtual environment [Optional] [source,cmd] ---- python3 -m venv .venv source .venv/bin/activate ---- -. Build the project +3. Build the project [source,cmd] ---- pip3 wheel --no-deps --wheel-dir dist . ---- -. Install requirements +4. Install requirements This will install necessary dependencies as well as the built project from the previous step. [source,cmd] @@ -78,8 +78,8 @@ The system configuration files need to be placed under _src/feelpp/benchmarking/ Example configurations are provided for the _Gaya_ machine and for a simple single node 8-core system. [NOTE] +==== Processor bindings and other launcher options should be specified as a resource under the desired partition, with the `launcher_options` name field value for example. For example, - [source,json] ---- "resources": [ @@ -89,6 +89,7 @@ Processor bindings and other launcher options should be specified as a resource } ] ---- +==== === Magic strings From 9b528ddba5416e4667421495f05cd0266b55a1cd Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 11:49:24 +0100 Subject: [PATCH 11/52] Merge branch '139-add-integration-tests-for-ci' into 90-add-documentation --- .github/workflows/ci.yml | 2 +- .gitignore | 6 ++++- config/machines/gaya_ci.json | 21 ++++++++++++++++++ config/tests_parallelSum/parallelSum.json | 10 ++++----- requirements.txt | 2 +- src/feelpp/benchmarking/reframe/validation.py | 5 +++-- .../report/config/overviewConfig.json | 6 ++--- tests/data/parallelSum | Bin 83880 -> 106048 bytes tests/data/parallelSum.cpp | 2 +- 9 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 config/machines/gaya_ci.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c838dce..9aaa1ff5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: - name: Test benchmarks run: | source .venv/bin/activate - execute-benchmark -mc config/machines/gaya.json -bc config/tests_parallelSum/parallelSum.json -pc config/tests_parallelSum/plots.json + execute-benchmark -mc config/machines/gaya_ci.json -bc config/tests_parallelSum/parallelSum.json -pc config/tests_parallelSum/plots.json echo $? - name: Dry-run reports run: | diff --git a/.gitignore b/.gitignore index 968a91e7..a9ec23ce 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,8 @@ project/report/* #Docs docs/modules/ROOT/pages/ -!docs/modules/ROOT/pages/index.adoc \ No newline at end of file +!docs/modules/ROOT/pages/index.adoc +reports/ + +#Test Outputs +tests/data/outputs/ \ No newline at end of file diff --git a/config/machines/gaya_ci.json b/config/machines/gaya_ci.json new file mode 100644 index 00000000..824cb2ff --- /dev/null +++ b/config/machines/gaya_ci.json @@ -0,0 +1,21 @@ +{ + "machine": "gaya", + "targets":["production:builtin:"], + // "partitions":["*"], + // "platform":"apptainer", + // "prog_environments":["*"], + "execution_policy": "async", + "reframe_base_dir":"$PWD/build/reframe", + "reports_base_dir":"$PWD/reports/", + "input_dataset_base_dir":"$PWD", + "output_app_dir":"$PWD", + "containers":{ + "apptainer":{ + "image_base_dir":"/data/scratch/", + "options":[ + "--sharens", + "--bind /opt/:/opt/" + ] + } + } +} \ No newline at end of file diff --git a/config/tests_parallelSum/parallelSum.json b/config/tests_parallelSum/parallelSum.json index b48a44a1..987b611f 100644 --- a/config/tests_parallelSum/parallelSum.json +++ b/config/tests_parallelSum/parallelSum.json @@ -1,20 +1,20 @@ { - "executable": "$PWD/tests/data/parallelSum", - "output_directory": "{{machine.output_app_dir}}/tests/parallelSum", + "executable": "{{machine.input_dataset_base_dir}}/tests/data/parallelSum", + "output_directory": "{{machine.output_app_dir}}/tests/data/outputs/parallelSum", "use_case_name": "parallel_sum", "timeout":"0-0:5:0", "options": [ "{{parameters.elements.value}}", - "{{output_directory}}/outputs/{{instance}}" + "{{output_directory}}/{{instance}}" ], "outputs": [ { - "filepath":"{{output_directory}}/outputs/{{instance}}/outputs.csv", + "filepath":"{{output_directory}}/{{instance}}/outputs.csv", "format":"csv" } ], "scalability": { - "directory": "{{output_directory}}/outputs/{{instance}}/", + "directory": "{{output_directory}}/{{instance}}/", "stages": [ { "name":"", diff --git a/requirements.txt b/requirements.txt index 2aa26942..1de900d8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ plotly setuptools nbformat Jinja2 -ReFrame-HPC +ReFrame-HPC==4.6.3 pandas nbmake traitlets diff --git a/src/feelpp/benchmarking/reframe/validation.py b/src/feelpp/benchmarking/reframe/validation.py index ce8520fb..58de63a5 100644 --- a/src/feelpp/benchmarking/reframe/validation.py +++ b/src/feelpp/benchmarking/reframe/validation.py @@ -1,4 +1,5 @@ import reframe.utility.sanity as sn +import re class ValidationHandler: """ Class to handle test validation and sanity functions""" @@ -8,8 +9,8 @@ def __init__(self, sanity_config): def check_success(self,stdout): """ Checks that all given regex patterns are found in an output (can be sn.stdout) """ - return all(sn.assert_found(rf"{pattern}",stdout) for pattern in self.success) + return all(sn.assert_found(rf"{re.escape(pattern)}",stdout) for pattern in self.success) def check_errors(self,stdout): """ Checks that no given regex patterns are found in an output (can be sn.stdout) """ - return all(sn.assert_not_found(rf"{pattern}",stdout) for pattern in self.errors) \ No newline at end of file + return all(sn.assert_not_found(rf"{re.escape(pattern)}",stdout) for pattern in self.errors) \ No newline at end of file diff --git a/src/feelpp/benchmarking/report/config/overviewConfig.json b/src/feelpp/benchmarking/report/config/overviewConfig.json index ed5f086d..0251bcd8 100644 --- a/src/feelpp/benchmarking/report/config/overviewConfig.json +++ b/src/feelpp/benchmarking/report/config/overviewConfig.json @@ -66,7 +66,7 @@ ] }, { - "title": "Execution by environment", + "title": "Execution by environment (latest benchmarks)", "plot_types": ["stacked_bar"], "transformation": "performance", "names": ["performance"], @@ -150,7 +150,7 @@ ] }, { - "title": "Execution by environment", + "title": "Execution by environment (latest benchmarks)", "plot_types": ["stacked_bar"], "transformation": "performance", "names": ["performance"], @@ -234,7 +234,7 @@ ] }, { - "title": "Execution by environment", + "title": "Execution by environment (latest benchmarks)", "plot_types": ["stacked_bar"], "transformation": "performance", "names": ["performance"], diff --git a/tests/data/parallelSum b/tests/data/parallelSum index 1083c78bb8d1841101b6eab721bb377128efad04..8460bddfe95498297f0a6110a7f55d0b073e9999 100755 GIT binary patch literal 106048 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 Date: Fri, 29 Nov 2024 14:20:19 +0100 Subject: [PATCH 12/52] rm nav --- docs/modules/nav.adoc | 1 - 1 file changed, 1 deletion(-) delete mode 100644 docs/modules/nav.adoc diff --git a/docs/modules/nav.adoc b/docs/modules/nav.adoc deleted file mode 100644 index 8f7da779..00000000 --- a/docs/modules/nav.adoc +++ /dev/null @@ -1 +0,0 @@ -* xref:tutorial/index.adoc[Documentation] \ No newline at end of file From 355578ae4a6616bc6170aeb3bde5e112ba9e45f6 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 14:23:22 +0100 Subject: [PATCH 13/52] split docs --- .../modules/tutorial/pages/configuration.adoc | 105 ++++++++++++++++++ .../tutorial/pages/gettingStarted.adoc | 61 ++++++++++ docs/modules/tutorial/pages/index.adoc | 89 +-------------- docs/modules/tutorial/pages/plots.adoc | 0 4 files changed, 168 insertions(+), 87 deletions(-) create mode 100644 docs/modules/tutorial/pages/configuration.adoc create mode 100644 docs/modules/tutorial/pages/gettingStarted.adoc create mode 100644 docs/modules/tutorial/pages/plots.adoc diff --git a/docs/modules/tutorial/pages/configuration.adoc b/docs/modules/tutorial/pages/configuration.adoc new file mode 100644 index 00000000..c3131e82 --- /dev/null +++ b/docs/modules/tutorial/pages/configuration.adoc @@ -0,0 +1,105 @@ += Configuration guide + +The core of the _Feel++ benchmarking_ framework are its configuration files. +Users must provide the following configuration files: +- A complete system description, based on ReFrame's configuration files. +- A machine specific configuration, defining HOW to execute benchmarks. +- A benchmark (or application) specific configuration, defining WHAT should be executed. +- A figure description, containing information of what to display on the final reports. + +These files, with the exeption of ReFrame configuration, are equiped with a special placeholder syntax, allowing to dynamically update the files along the tests execution. +Aditionally, multiple environments can be specified, including Apptainer containers. + +== System configuration + +The system configuration files need to be placed under _src/feelpp/benchmarking/reframe/config/machineConfigs_, and are strictly ReFrame dependent. A single Python file should be provided per machine. Please follow https://reframe-hpc.readthedocs.io/en/stable/config_reference.html[ReFrame's configuration file reference] for precise settings. + +Example configurations are provided for the _Gaya_ machine and for a simple single node 8-core system. + +[NOTE] +==== +Processor bindings and other launcher options should be specified as a resource under the desired partition, with the `launcher_options` name field value for example. For example, +[source,json] +---- +"resources": [ + { + "name":"launcher_options", + "options":["-bind-to","core"] + } +] +---- +==== + +== Magic strings + +Benchmarking configuration files support a special *placeholder* syntax, using double curly braces `{{placeholder}}`. +This syntax is specially useful for: +- Refactoring configuration fields. +- Replacing with values from other configuration files, such as the machine config. +- Making use of code variables modified at runtime, by having reserved keywords. +- Fetching defined parameters values that change during runtime. + +To get a value of a field in the same file, the field path must be separated by dots. For example, +[source,json] +---- +"field_a":{ + "field_b":{ + "field_c": "my value" + } +} + +"example_placeholder": "{{field_a.field_b.field_c}}" +---- + +For replacing a value coming from the machine configuration, simply prepend any placeholder path with `machine.` + +=== Reserved Keywords + +The framework is equiped with the following reserved keywords for placeholders: +- `{{instance}}` : Returns the hashcode of the current ReFrame test. +- `{{.value}}`: The value keyword must be appended to a parameter name. + + +[NOTE] +==== +Nested placeholders are supported. + +For example, lets say you have a _machine_ configuration containing +[source,json] +---- +"platform":"builtin" +---- + +And a benchmark configuration: + +[source,json] +---- +"platforms":{ + "builtin":"my_builtin_value", + "other":"my_other_value" +}, +"nested_placeholder":"My platform dependent value is {{ platforms.{{machine.platform}} }}" +---- + +==== + +The `nested_placeholder` field will then take the value of "My platform dependent value is my_buildin_value", because the machine config specifies that "platform" is "builtin". But this will change if "platform" is set to "other". + +[NOTE] +==== +Environment variables can be specifed in any configuration file by prepending a `$`. +For example, + +[source,json] +---- +"my_home": "$HOME" +---- +==== + +== Machine configuration + +== Benchmark configuration + +== Overview configuration + +== Plots configuration \ No newline at end of file diff --git a/docs/modules/tutorial/pages/gettingStarted.adoc b/docs/modules/tutorial/pages/gettingStarted.adoc new file mode 100644 index 00000000..878978ce --- /dev/null +++ b/docs/modules/tutorial/pages/gettingStarted.adoc @@ -0,0 +1,61 @@ += Getting started + +== Installation + +1. Clone the Repository +[source,cmd] +---- +git clone https://github.com/feelpp/benchmarking.git +---- + +2. Use a python virtual environment [Optional] +[source,cmd] +---- +python3 -m venv .venv +source .venv/bin/activate +---- + +3. Build the project +[source,cmd] +---- +pip3 wheel --no-deps --wheel-dir dist . +---- + +4. Install requirements + +This will install necessary dependencies as well as the built project from the previous step. +[source,cmd] +---- +python3 -m pip install -r requirements.txt +---- + +== Quickstart + +The framwork includes a sample C++/MPI application that can be used to get familiar with the framework's core concepts. It can be found under _tests/data/parallelSum.cpp_. + +This Feel++ Benchmarking "Hello World" application will compute the sum of an array distributed across multiple MPI processes. Each process will compute a partial sum, and then it will be summed to get the total sum. + +Additionally, the app will measure the time taken to perform the partial sum, and will save it under a _scalability.json_ file. + +The executable is already provided as _tests/data/parallelSum_. You can update it and recompile it for a specific config as needed. +[source,cmd] +---- +mpic++ -std=c++17 -o test/data/parallelSum test/data/parallelSum.cpp +---- + +Local configuration files can be found under _config/test_parallelSum/_. They are explained more in detail in the following configuration section. +This folder cantins a _parallelSum.json_ file holding are benchmark related configurations. That is, instructions on what the benchmark should be. It also contains a `plots.json` file holding descriptions on the figures that should be generated for this benchmark. +Additionally, machine specific configurations are found under _config/machines/_. These files contain general information on the environments to run the tests on, including containers, special options and base directories for inputs and outputs of the applications. +It is important to know that these configuration files are user dependent, and will most certainly vary depending on the resource you will execute benchmarks on. For a simple example, the _local.json_ file can be used for running the application on a personal Linux or MacOS computer. + +Configuration files might require some changes for specific configurations depending on the system you are running the framework. + +Finally, to benchmark the test application, generate the reports and plot the figures, run +[source,cmd] +---- +execute-benchmark --machine-config config/machines/local.json --benchmark-config config/test_parallelSum/parallelSum.json --plots-config config/test_parallelSum/plots.json --website +---- + +The `--website` option will start an http-server on localhost, so the website can be visualized, check the console for more information. + + diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index 10f5962f..ed4e3d67 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -6,100 +6,15 @@ The _Feel++ benchmarking_ project provides a framework for automating, centraliz This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. -== Getting started +[TODO] +Add ToC -=== Installation - -1. Clone the Repository -[source,cmd] ----- -git clone https://github.com/feelpp/benchmarking.git ----- - -2. Use a python virtual environment [Optional] -[source,cmd] ----- -python3 -m venv .venv -source .venv/bin/activate ----- - -3. Build the project -[source,cmd] ----- -pip3 wheel --no-deps --wheel-dir dist . ----- - -4. Install requirements - -This will install necessary dependencies as well as the built project from the previous step. -[source,cmd] ----- -python3 -m pip install -r requirements.txt ----- - -=== Quickstart - -The framwork includes a sample C++/MPI application that can be used to get familiar with the framework's core concepts. It can be found under _tests/data/parallelSum.cpp_. - -This Feel++ Benchmarking "Hello World" application will compute the sum of an array distributed across multiple MPI processes. Each process will compute a partial sum, and then it will be summed to get the total sum. - -Additionally, the app will measure the time taken to perform the partial sum, and will save it under a _scalability.json_ file. - -The executable is already provided as _tests/data/parallelSum_. You can update it for a specific config -[source,cmd] ----- -mpic++ -std=c++17 -o test/data/parallelSum test/data/parallelSum.cpp ----- - -Local configuration files can be found under _config/test_parallelSum/_. They are explained more in detail in the following sections. -They might require specific configurations depending on the system you are running the framework. - -Finally, to benchmark the test application, generate the reports and plot the figures, run -[source,cmd] ----- -execute-benchmark --machine-config config/machines/local.json --benchmark-config config/test_parallelSum/parallelSum.json --plots-config config/test_parallelSum/plots.json --website ----- - -The `--website` option will start an http-server on localhost, so the website can be visualized, check the console for more information. == How it works -TODO: - -== Configuration guide - -TODO: intro -- Different config files, introduce special syntaxes, supported envs, - -=== System configuration - -The system configuration files need to be placed under _src/feelpp/benchmarking/reframe/config/machineConfigs_, and are strictly ReFrame dependent. A single Python file should be provided per machine. Please follow https://reframe-hpc.readthedocs.io/en/stable/config_reference.html[ReFrame's configuration file reference] for precise settings. - -Example configurations are provided for the _Gaya_ machine and for a simple single node 8-core system. - -[NOTE] -==== -Processor bindings and other launcher options should be specified as a resource under the desired partition, with the `launcher_options` name field value for example. For example, -[source,json] ----- -"resources": [ - { - "name":"launcher_options", - "options":["-bind-to","core"] - } -] ----- -==== - -=== Magic strings - -=== Machine configuration -=== Benchmark configuration -=== Overview configuration -=== Plots configuration == Benchmarking Workflow diff --git a/docs/modules/tutorial/pages/plots.adoc b/docs/modules/tutorial/pages/plots.adoc new file mode 100644 index 00000000..e69de29b From 0b5c0aa7d8049eb1d512d401a9c1aaaf2f700142 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 15:23:44 +0100 Subject: [PATCH 14/52] rename --- .../tutorial/pages/{gettingStarted.adoc => gettingstarted.adoc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/modules/tutorial/pages/{gettingStarted.adoc => gettingstarted.adoc} (100%) diff --git a/docs/modules/tutorial/pages/gettingStarted.adoc b/docs/modules/tutorial/pages/gettingstarted.adoc similarity index 100% rename from docs/modules/tutorial/pages/gettingStarted.adoc rename to docs/modules/tutorial/pages/gettingstarted.adoc From 563cea3989b80eca9bfa3d5b97b9e385b602684c Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 15:45:19 +0100 Subject: [PATCH 15/52] some tweaks #90 --- docs/modules/ROOT/nav.adoc | 3 +-- docs/modules/tutorial/nav.adoc | 5 +++++ .../modules/tutorial/pages/configuration.adoc | 19 ++++++++++++------- .../tutorial/pages/gettingstarted.adoc | 13 ++++++++----- docs/modules/tutorial/pages/index.adoc | 2 -- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index f3ea0b6c..8501a798 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -1,2 +1 @@ -* xref:ROOT:index.adoc[Benchmarks] -* xref:tutorial:index.adoc[Documentation] \ No newline at end of file +* xref:ROOT:index.adoc[Benchmarks] \ No newline at end of file diff --git a/docs/modules/tutorial/nav.adoc b/docs/modules/tutorial/nav.adoc index e69de29b..e56a7158 100644 --- a/docs/modules/tutorial/nav.adoc +++ b/docs/modules/tutorial/nav.adoc @@ -0,0 +1,5 @@ + +* xref:tutorial:index.adoc[Documentation] +** xref:tutorial:gettingstarted.adoc[Getting Started] +** xref:tutorial:configuration.adoc[Configuration Guide] +** xref:tutorial:plots.adoc[Figures Guide] \ No newline at end of file diff --git a/docs/modules/tutorial/pages/configuration.adoc b/docs/modules/tutorial/pages/configuration.adoc index c3131e82..22e6d7c6 100644 --- a/docs/modules/tutorial/pages/configuration.adoc +++ b/docs/modules/tutorial/pages/configuration.adoc @@ -2,6 +2,7 @@ The core of the _Feel++ benchmarking_ framework are its configuration files. Users must provide the following configuration files: + - A complete system description, based on ReFrame's configuration files. - A machine specific configuration, defining HOW to execute benchmarks. - A benchmark (or application) specific configuration, defining WHAT should be executed. @@ -34,6 +35,7 @@ Processor bindings and other launcher options should be specified as a resource Benchmarking configuration files support a special *placeholder* syntax, using double curly braces `{{placeholder}}`. This syntax is specially useful for: + - Refactoring configuration fields. - Replacing with values from other configuration files, such as the machine config. - Making use of code variables modified at runtime, by having reserved keywords. @@ -56,12 +58,12 @@ For replacing a value coming from the machine configuration, simply prepend any === Reserved Keywords The framework is equiped with the following reserved keywords for placeholders: + - `{{instance}}` : Returns the hashcode of the current ReFrame test. -- `{{.value}}`: The value keyword must be appended to a parameter name. +- `{{.value}}`: The value keyword must be appended to a parameter name (e.g. `{{parameters.my_param.value}}`). It fetches the current value of a given runtime variable (such as a parameter). More information on [Parameters TODO link] +=== Nested placeholders -[NOTE] -==== Nested placeholders are supported. For example, lets say you have a _machine_ configuration containing @@ -81,12 +83,10 @@ And a benchmark configuration: "nested_placeholder":"My platform dependent value is {{ platforms.{{machine.platform}} }}" ---- -==== - The `nested_placeholder` field will then take the value of "My platform dependent value is my_buildin_value", because the machine config specifies that "platform" is "builtin". But this will change if "platform" is set to "other". -[NOTE] -==== +=== Using environment variables + Environment variables can be specifed in any configuration file by prepending a `$`. For example, @@ -94,6 +94,11 @@ For example, ---- "my_home": "$HOME" ---- + +[NOTE] +==== +Shorthand representations, such as `~` are not supported, and relative paths starting by `.` are not supported. +For relative file or folder paths, use `$PWD` instead. ==== == Machine configuration diff --git a/docs/modules/tutorial/pages/gettingstarted.adoc b/docs/modules/tutorial/pages/gettingstarted.adoc index 878978ce..7f9cbb22 100644 --- a/docs/modules/tutorial/pages/gettingstarted.adoc +++ b/docs/modules/tutorial/pages/gettingstarted.adoc @@ -43,17 +43,20 @@ The executable is already provided as _tests/data/parallelSum_. You can update i mpic++ -std=c++17 -o test/data/parallelSum test/data/parallelSum.cpp ---- -Local configuration files can be found under _config/test_parallelSum/_. They are explained more in detail in the following configuration section. -This folder cantins a _parallelSum.json_ file holding are benchmark related configurations. That is, instructions on what the benchmark should be. It also contains a `plots.json` file holding descriptions on the figures that should be generated for this benchmark. -Additionally, machine specific configurations are found under _config/machines/_. These files contain general information on the environments to run the tests on, including containers, special options and base directories for inputs and outputs of the applications. -It is important to know that these configuration files are user dependent, and will most certainly vary depending on the resource you will execute benchmarks on. For a simple example, the _local.json_ file can be used for running the application on a personal Linux or MacOS computer. +// Local configuration files can be found under _config/test_parallelSum/_. They are explained more in detail in the following configuration section. +// This folder cantins a _parallelSum.json_ file holding are benchmark related configurations. That is, instructions on what the benchmark should be. It also contains a `plots.json` file holding descriptions on the figures that should be generated for this benchmark. +// Additionally, machine specific configurations are found under _config/machines/_. These files contain general information on the environments to run the tests on, including containers, special options and base directories for inputs and outputs of the applications. +// It is important to know that these configuration files are user dependent, and will most certainly vary depending on the resource you will execute benchmarks on. For a simple example, the _local.json_ file can be used for running the application on a personal Linux or MacOS computer. Configuration files might require some changes for specific configurations depending on the system you are running the framework. Finally, to benchmark the test application, generate the reports and plot the figures, run [source,cmd] ---- -execute-benchmark --machine-config config/machines/local.json --benchmark-config config/test_parallelSum/parallelSum.json --plots-config config/test_parallelSum/plots.json --website +execute-benchmark --machine-config config/machines/local.json \ + --benchmark-config config/test_parallelSum/parallelSum.json \ + --plots-config config/test_parallelSum/plots.json \ + --website ---- The `--website` option will start an http-server on localhost, so the website can be visualized, check the console for more information. diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index ed4e3d67..22f6e7fb 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -1,7 +1,5 @@ = feelpp.benchmarkign project -== Welcome to Feel++ Benchmarking - The _Feel++ benchmarking_ project provides a framework for automating, centralizing and organizing performance evaluation of scientific simulations on HPC systems. This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. From f433df9140d86733ae5d349255d1033ad31bb0e1 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 16:19:55 +0100 Subject: [PATCH 16/52] make exec_policy optioanl (default serial) --- src/feelpp/benchmarking/reframe/config/configMachines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feelpp/benchmarking/reframe/config/configMachines.py b/src/feelpp/benchmarking/reframe/config/configMachines.py index dda5b8df..b291e364 100644 --- a/src/feelpp/benchmarking/reframe/config/configMachines.py +++ b/src/feelpp/benchmarking/reframe/config/configMachines.py @@ -21,7 +21,7 @@ class MachineConfig(BaseModel): machine:str targets:Optional[str | List[str]] = None active: Optional[bool] = True - execution_policy:Literal["serial","async"] + execution_policy:Optional[Literal["serial","async"]] = "serial" reframe_base_dir:str reports_base_dir:str input_dataset_base_dir:str From ec2b230dd9db539972f27261a6b6aff723cfd31b Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 17:04:48 +0100 Subject: [PATCH 17/52] split configs and wrote machine config doc #90 --- .../modules/tutorial/pages/configuration.adoc | 98 +---------- .../pages/configurationfiles/benchmark.adoc | 1 + .../pages/configurationfiles/machine.adoc | 152 ++++++++++++++++++ .../configurationfiles/magicstrings.adoc | 69 ++++++++ .../pages/configurationfiles/overviews.adoc | 1 + .../pages/configurationfiles/plots.adoc | 1 + .../pages/configurationfiles/system.adoc | 19 +++ .../tutorial/pages/gettingstarted.adoc | 3 + docs/modules/tutorial/pages/index.adoc | 2 - 9 files changed, 251 insertions(+), 95 deletions(-) create mode 100644 docs/modules/tutorial/pages/configurationfiles/benchmark.adoc create mode 100644 docs/modules/tutorial/pages/configurationfiles/machine.adoc create mode 100644 docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc create mode 100644 docs/modules/tutorial/pages/configurationfiles/overviews.adoc create mode 100644 docs/modules/tutorial/pages/configurationfiles/plots.adoc create mode 100644 docs/modules/tutorial/pages/configurationfiles/system.adoc diff --git a/docs/modules/tutorial/pages/configuration.adoc b/docs/modules/tutorial/pages/configuration.adoc index 22e6d7c6..e560cf66 100644 --- a/docs/modules/tutorial/pages/configuration.adoc +++ b/docs/modules/tutorial/pages/configuration.adoc @@ -11,100 +11,12 @@ Users must provide the following configuration files: These files, with the exeption of ReFrame configuration, are equiped with a special placeholder syntax, allowing to dynamically update the files along the tests execution. Aditionally, multiple environments can be specified, including Apptainer containers. -== System configuration +include::configurationfiles/system.adoc[leveloffset=+1] -The system configuration files need to be placed under _src/feelpp/benchmarking/reframe/config/machineConfigs_, and are strictly ReFrame dependent. A single Python file should be provided per machine. Please follow https://reframe-hpc.readthedocs.io/en/stable/config_reference.html[ReFrame's configuration file reference] for precise settings. +include::configurationfiles/magicstrings.adoc[leveloffset=+1] -Example configurations are provided for the _Gaya_ machine and for a simple single node 8-core system. +include::configurationfiles/machine.adoc[leveloffset=+1] -[NOTE] -==== -Processor bindings and other launcher options should be specified as a resource under the desired partition, with the `launcher_options` name field value for example. For example, -[source,json] ----- -"resources": [ - { - "name":"launcher_options", - "options":["-bind-to","core"] - } -] ----- -==== +include::configurationfiles/benchmark.adoc[leveloffset=+1] -== Magic strings - -Benchmarking configuration files support a special *placeholder* syntax, using double curly braces `{{placeholder}}`. -This syntax is specially useful for: - -- Refactoring configuration fields. -- Replacing with values from other configuration files, such as the machine config. -- Making use of code variables modified at runtime, by having reserved keywords. -- Fetching defined parameters values that change during runtime. - -To get a value of a field in the same file, the field path must be separated by dots. For example, -[source,json] ----- -"field_a":{ - "field_b":{ - "field_c": "my value" - } -} - -"example_placeholder": "{{field_a.field_b.field_c}}" ----- - -For replacing a value coming from the machine configuration, simply prepend any placeholder path with `machine.` - -=== Reserved Keywords - -The framework is equiped with the following reserved keywords for placeholders: - -- `{{instance}}` : Returns the hashcode of the current ReFrame test. -- `{{.value}}`: The value keyword must be appended to a parameter name (e.g. `{{parameters.my_param.value}}`). It fetches the current value of a given runtime variable (such as a parameter). More information on [Parameters TODO link] - -=== Nested placeholders - -Nested placeholders are supported. - -For example, lets say you have a _machine_ configuration containing -[source,json] ----- -"platform":"builtin" ----- - -And a benchmark configuration: - -[source,json] ----- -"platforms":{ - "builtin":"my_builtin_value", - "other":"my_other_value" -}, -"nested_placeholder":"My platform dependent value is {{ platforms.{{machine.platform}} }}" ----- - -The `nested_placeholder` field will then take the value of "My platform dependent value is my_buildin_value", because the machine config specifies that "platform" is "builtin". But this will change if "platform" is set to "other". - -=== Using environment variables - -Environment variables can be specifed in any configuration file by prepending a `$`. -For example, - -[source,json] ----- -"my_home": "$HOME" ----- - -[NOTE] -==== -Shorthand representations, such as `~` are not supported, and relative paths starting by `.` are not supported. -For relative file or folder paths, use `$PWD` instead. -==== - -== Machine configuration - -== Benchmark configuration - -== Overview configuration - -== Plots configuration \ No newline at end of file +include::configurationfiles/plots.adoc[leveloffset=+1] \ No newline at end of file diff --git a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc new file mode 100644 index 00000000..7355b3e2 --- /dev/null +++ b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc @@ -0,0 +1 @@ += Benchmark configuration \ No newline at end of file diff --git a/docs/modules/tutorial/pages/configurationfiles/machine.adoc b/docs/modules/tutorial/pages/configurationfiles/machine.adoc new file mode 100644 index 00000000..d6f32a8f --- /dev/null +++ b/docs/modules/tutorial/pages/configurationfiles/machine.adoc @@ -0,0 +1,152 @@ += Machine configuration + +The machine configuration file contains all information related uniquely to the system where benchmarks will run on. It is used to tell the application HOW benchmarks will run on it. +The framework supports multiple containers and environments such as Apptainer and Spack. This information should be specified here. + +The following table describes all supported fields. + +[cols="2,1,1,3,1"] +|=== +| Field name | Optional | type | description | Default + +| machine +| No +| str +| The name of the machine. It needs to be the same as the name of the ReFrame configuration file. +| + +| execution_policy +| Yes +| str +| Either 'async' or 'serial'. The way in which ReFrame will run the tests. +| Serial + +| reframe_base_dir +| No +| str +| The base directory of ReFrame's _stage_ and _output_ directories. If it does not exist, it will be created. +| + +| reports_base_dir +| No +| str +| The base directory where ReFrame reports will be saved to. +| + +| input_dataset_base_dir +| Yes +| str +| The base directory where input data can be found (if applicable) +| None + +| output_app_dir +| No +| str +| The base directory where the benchmarked application should write its outputs to. +| + +| targets +| Yes +| list[str] or str +| Specifies in which partition, platform and prog_environment run benchmarks on. +The syntax is `[partition:platform:prog_environment]`. Default values are supported by only putting `:`. For example `partition::prog_environment`. Default values are "default" for partition and prog_environment, and "builtin" for platform. +Provide this field or all (partitions, platform, prog_environments) fields. +| None + +| platform +| Yes +| str +| Platform to run the benchmark on, possible values are "Apptainer" and "builtin". Docker will soon be supported. +| builtin + +| partitions +| Yes +| List[str] +| Partitions where the test can run on. Tests will run on the cartesian product of partitions and prog_environments, where environments are specified for the current partition on the ReFrame configuration. +| [] + +| prog_environments +| Yes +| List[str] +| Environments where the test can run on. Test will run with this programming environment if it is specified on the current partition on the ReFrame configuration. +| [] + +| containers +| Yes +| Dict[str,Container] +| Dictionary specifying container type "Apptainer" or "Docker" (not yet supported), and container related information. More details on the `Container` object below. +| {} + + +|=== + + +The containers object is defined as follow + +[cols="2,1,1,3,1"] +|=== +| Field name | Optional | type | description | Default value + +| cachedir +| Yes +| str +| Directory where the pulled images will be cached on. +| None + +| tmpdir +| Yes +| str +| Directory where temporary image files will be written. +| None + +| image_base_dir +| No +| str +| Base directory where images can be found in the system +| None + +| options +| Yes +| List[str] +| Options to add to the container execution command. +| None + +|=== + +Below, an example of a machine configuration file can be found, for a machine called "my_machine". + +[source,json] +---- +{ + "machine": "my_machine", + "targets":"production:builtin:hpcx", + "execution_policy": "async", + "reframe_base_dir":"$PWD/build/reframe", + "reports_base_dir":"$PWD/reports/", + "input_dataset_base_dir":"$PWD/input/", + "output_app_dir":"$PWD/output/", + "containers":{ + "apptainer":{ + "image_base_dir":"/data/images/", + "options":[ "--sharens", "--bind /opt/:/opt/" ] + } + } +} +---- + +Let's review step by step what the file defines. + +- `"machine":"my_machine"` indicates that the ReFrame config can be found as _my\_machine.py_ +- `"targets":"production:builtin:hpcx"` tells reframe to run tests uniquely on the production partition with the builtin platform and the hpcx programming environment. +- `"execution_policy":"async"` tells ReFrame to run tests asynchronously on available resources. +- `"reframe_base_dir":"$PWD/build/reframe"` Reframe will use the _build/stage/_ folder and _build/output/_ folder of the current working directory for staging tests and storing the benchmarked application's standard output and errors. +- `"reports_base_dir":"$PWD/reports/"` Means that the reframe reports will be found under the _reports/_ folder of the current working directory. +- `"input_dataset_base_dir":"$PWD/input/"` Means that the framework should look for input somewhere under the _input/_ folder of the current working directory. The rest of the path is specified on the benchmark configuration. +- `"output_app_dir":"$PWD/output/"` Means that the benchmarked application should write its output files under the _output/_ folder of the current working directory. The rest of the path is specified on the benchmark configuration. + +Concerning containers: + +- The `"apptainer"` key indicated that the application COULD be benchmarked using apptainer. Not necesserily that it will. If the `targets` field specifies the apptainer platform, then this field is mandatory. +- `"image_base_dir":"/data/images"` indicates that the built apptainer images can be found somewhere under the _/data/images/ directory. The rest of the path is specified on the benchmark configuration. +- `"options":"[ "--sharens", "--bind /opt/:/opt/" ]"` Tells ReFrame to add these options to the Apptainer execution command. For example, `mpiexec -n 4 apptainer exec --sharens --bind /opt/:/opt/`. Only machine related options should be specified here, more options can be defined in the benchmark configuration. + diff --git a/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc b/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc new file mode 100644 index 00000000..f024c4e0 --- /dev/null +++ b/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc @@ -0,0 +1,69 @@ += Magic strings + +Benchmarking configuration files support a special *placeholder* syntax, using double curly braces `{{placeholder}}`. +This syntax is specially useful for: + +- Refactoring configuration fields. +- Replacing with values from other configuration files, such as the machine config. +- Making use of code variables modified at runtime, by having reserved keywords. +- Fetching defined parameters values that change during runtime. + +To get a value of a field in the same file, the field path must be separated by dots. For example, +[source,json] +---- +"field_a":{ + "field_b":{ + "field_c": "my value" + } +} + +"example_placeholder": "{{field_a.field_b.field_c}}" +---- + +For replacing a value coming from the machine configuration, simply prepend any placeholder path with `machine.` + +== Reserved Keywords + +The framework is equiped with the following reserved keywords for placeholders: + +- `{{instance}}` : Returns the hashcode of the current ReFrame test. +- `{{.value}}`: The value keyword must be appended to a parameter name (e.g. `{{parameters.my_param.value}}`). It fetches the current value of a given runtime variable (such as a parameter). More information on [Parameters TODO link] + +== Nested placeholders + +Nested placeholders are supported. + +For example, lets say you have a _machine_ configuration containing +[source,json] +---- +"platform":"builtin" +---- + +And a benchmark configuration: + +[source,json] +---- +"platforms":{ + "builtin":"my_builtin_value", + "other":"my_other_value" +}, +"nested_placeholder":"My platform dependent value is {{ platforms.{{machine.platform}} }}" +---- + +The `nested_placeholder` field will then take the value of "My platform dependent value is my_buildin_value", because the machine config specifies that "platform" is "builtin". But this will change if "platform" is set to "other". + +== Using environment variables + +Environment variables can be specifed in any configuration file by prepending a `$`. +For example, + +[source,json] +---- +"my_home": "$HOME" +---- + +[NOTE] +==== +Shorthand representations such as `~` and relative paths starting by `.` are not supported. +For relative file or folder paths, use `$PWD` instead. +==== diff --git a/docs/modules/tutorial/pages/configurationfiles/overviews.adoc b/docs/modules/tutorial/pages/configurationfiles/overviews.adoc new file mode 100644 index 00000000..0fe52968 --- /dev/null +++ b/docs/modules/tutorial/pages/configurationfiles/overviews.adoc @@ -0,0 +1 @@ += Overview configuration diff --git a/docs/modules/tutorial/pages/configurationfiles/plots.adoc b/docs/modules/tutorial/pages/configurationfiles/plots.adoc new file mode 100644 index 00000000..97983328 --- /dev/null +++ b/docs/modules/tutorial/pages/configurationfiles/plots.adoc @@ -0,0 +1 @@ += Figures \ No newline at end of file diff --git a/docs/modules/tutorial/pages/configurationfiles/system.adoc b/docs/modules/tutorial/pages/configurationfiles/system.adoc new file mode 100644 index 00000000..c4bf386d --- /dev/null +++ b/docs/modules/tutorial/pages/configurationfiles/system.adoc @@ -0,0 +1,19 @@ += System configuration + +The system configuration files need to be placed under _src/feelpp/benchmarking/reframe/config/machineConfigs_, and are strictly ReFrame dependent. A single Python file should be provided per machine. Please follow https://reframe-hpc.readthedocs.io/en/stable/config_reference.html[ReFrame's configuration file reference] for precise settings. + +Example configurations are provided for the _Gaya_ machine and for a simple single node 8-core system. + +[NOTE] +==== +Processor bindings and other launcher options should be specified as a resource under the desired partition, with the `launcher_options` name field value for example. For example, +[source,json] +---- +"resources": [ + { + "name":"launcher_options", + "options":["-bind-to","core"] + } +] +---- +==== diff --git a/docs/modules/tutorial/pages/gettingstarted.adoc b/docs/modules/tutorial/pages/gettingstarted.adoc index 7f9cbb22..0b5e21e4 100644 --- a/docs/modules/tutorial/pages/gettingstarted.adoc +++ b/docs/modules/tutorial/pages/gettingstarted.adoc @@ -62,3 +62,6 @@ execute-benchmark --machine-config config/machines/local.json \ The `--website` option will start an http-server on localhost, so the website can be visualized, check the console for more information. +== Executing a benchmark + +== Rendering reports \ No newline at end of file diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index 22f6e7fb..ffe38323 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -4,8 +4,6 @@ The _Feel++ benchmarking_ project provides a framework for automating, centraliz This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. -[TODO] -Add ToC From a2497216f3e2407c00c40b78b7aaeccb0e0bca4c Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 17:04:57 +0100 Subject: [PATCH 18/52] input_dataset_base_dir is now optional --- src/feelpp/benchmarking/reframe/config/configMachines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feelpp/benchmarking/reframe/config/configMachines.py b/src/feelpp/benchmarking/reframe/config/configMachines.py index b291e364..19fca95e 100644 --- a/src/feelpp/benchmarking/reframe/config/configMachines.py +++ b/src/feelpp/benchmarking/reframe/config/configMachines.py @@ -24,7 +24,7 @@ class MachineConfig(BaseModel): execution_policy:Optional[Literal["serial","async"]] = "serial" reframe_base_dir:str reports_base_dir:str - input_dataset_base_dir:str + input_dataset_base_dir:Optional[str] = None output_app_dir:str containers:Optional[Dict[str,Container]] = {} From 23a35027789c7f85ea1165d38e978bc01481fe14 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Fri, 29 Nov 2024 17:10:10 +0100 Subject: [PATCH 19/52] add note and init bench config #90 --- .../modules/tutorial/pages/configuration.adoc | 5 +++ .../pages/configurationfiles/benchmark.adoc | 33 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/modules/tutorial/pages/configuration.adoc b/docs/modules/tutorial/pages/configuration.adoc index e560cf66..261e40e8 100644 --- a/docs/modules/tutorial/pages/configuration.adoc +++ b/docs/modules/tutorial/pages/configuration.adoc @@ -11,6 +11,11 @@ Users must provide the following configuration files: These files, with the exeption of ReFrame configuration, are equiped with a special placeholder syntax, allowing to dynamically update the files along the tests execution. Aditionally, multiple environments can be specified, including Apptainer containers. +[NOTE] +==== +Comments are supported on these JSON files. +==== + include::configurationfiles/system.adoc[leveloffset=+1] include::configurationfiles/magicstrings.adoc[leveloffset=+1] diff --git a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc index 7355b3e2..e9ecc121 100644 --- a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc @@ -1 +1,32 @@ -= Benchmark configuration \ No newline at end of file += Benchmark configuration + +Configuring a benchmark can be quite extensive, as this framework focuses on flexibility. For this, the documentation will be divided in main sections. + +The base of the configuration file is shown below. +[source,json] +---- +{ + "executable": "", + "output_directory": "", + "use_case_name": "", + "timeout":"", + "platforms":{}, + "options": [], + "outputs":{}, + "scalability":{}, + "sanity":{}, + "parameters":{}, +} +---- + +== Fields on JSON root + +== Platforms + +== Outputs + +== Scalability + +== Sanity + +== Parameters From cfc4aa7957ee168882da5fb80b375ce0c500611b Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Sun, 1 Dec 2024 08:32:50 +0100 Subject: [PATCH 20/52] up local and set env default --- config/machines/local.json | 3 +-- .../benchmarking/reframe/config/machineConfigs/local.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/config/machines/local.json b/config/machines/local.json index 29f5c144..f1f66fd0 100644 --- a/config/machines/local.json +++ b/config/machines/local.json @@ -1,8 +1,7 @@ { "machine": "local", + "targets":[":builtin:"], "execution_policy": "async", - "partitions":["default"], - "prog_environment":"builtin", "reframe_base_dir":"$HOME/Documents/Repos/benchmarking/build/reframe", "reports_base_dir":"$HOME/Documents/Repos/benchmarking/reports/", "input_dataset_base_dir":"$HOME/Documents", diff --git a/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py b/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py index 113e96db..fbea86be 100644 --- a/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py +++ b/src/feelpp/benchmarking/reframe/config/machineConfigs/local.py @@ -10,7 +10,7 @@ 'name': 'default', 'scheduler': 'local', 'launcher': 'mpiexec', - 'environs': ['builtin'], + 'environs': ['default'], 'processor': { 'num_cpus': 8 }, @@ -26,7 +26,7 @@ ], 'environments': [ { - 'name': 'builtin', + 'name': 'default', 'cc': 'clang', 'cxx': 'clang++', 'target_systems': ['local:default'] From d56d5e3d0e44db1524aa75a60d0bec1403530c7e Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Sun, 1 Dec 2024 08:33:03 +0100 Subject: [PATCH 21/52] lower tasks --- config/tests_parallelSum/parallelSum.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/config/tests_parallelSum/parallelSum.json b/config/tests_parallelSum/parallelSum.json index 987b611f..d31afacc 100644 --- a/config/tests_parallelSum/parallelSum.json +++ b/config/tests_parallelSum/parallelSum.json @@ -34,9 +34,7 @@ "sequence": [ {"tasks" : 1, "exclusive_access":true}, {"tasks" : 2, "exclusive_access":true}, - {"tasks" : 4, "exclusive_access":true}, - {"tasks" : 8, "exclusive_access":true}, - {"tasks" : 16, "exclusive_access":true} + {"tasks" : 4, "exclusive_access":true} ] }, { From 409be7f9bb06e7d8c8264469cc0b55108fee82a4 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Sun, 1 Dec 2024 08:33:18 +0100 Subject: [PATCH 22/52] fix python 3.8 --- src/feelpp/benchmarking/reframe/config/configMachines.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/feelpp/benchmarking/reframe/config/configMachines.py b/src/feelpp/benchmarking/reframe/config/configMachines.py index 19fca95e..33df2623 100644 --- a/src/feelpp/benchmarking/reframe/config/configMachines.py +++ b/src/feelpp/benchmarking/reframe/config/configMachines.py @@ -6,7 +6,7 @@ class Container(BaseModel): cachedir:Optional[str] = None tmpdir:Optional[str] = None image_base_dir:str - options:Optional[list[str]] = [] + options:Optional[List[str]] = [] @field_validator("cachedir","tmpdir","image_base_dir",mode="before") @classmethod @@ -19,7 +19,7 @@ def checkDirectories(cls,v): class MachineConfig(BaseModel): machine:str - targets:Optional[str | List[str]] = None + targets:Optional[Union[str,List[str]]] = None active: Optional[bool] = True execution_policy:Optional[Literal["serial","async"]] = "serial" reframe_base_dir:str From c1b08b42ce53c6c63ac770540ee468cb35a8abe4 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Sun, 1 Dec 2024 08:44:06 +0100 Subject: [PATCH 23/52] fix dirs --- config/machines/local.json | 2 +- config/tests_parallelSum/parallelSum.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/machines/local.json b/config/machines/local.json index f1f66fd0..54a70b56 100644 --- a/config/machines/local.json +++ b/config/machines/local.json @@ -4,7 +4,7 @@ "execution_policy": "async", "reframe_base_dir":"$HOME/Documents/Repos/benchmarking/build/reframe", "reports_base_dir":"$HOME/Documents/Repos/benchmarking/reports/", - "input_dataset_base_dir":"$HOME/Documents", + "input_dataset_base_dir":"$HOME/Documents/Repos/benchmarking/", "output_app_dir":"$HOME/Documents/Repos/benchmarking" // "containers":{ // "apptainer":{ diff --git a/config/tests_parallelSum/parallelSum.json b/config/tests_parallelSum/parallelSum.json index d31afacc..15622371 100644 --- a/config/tests_parallelSum/parallelSum.json +++ b/config/tests_parallelSum/parallelSum.json @@ -26,7 +26,7 @@ }, "sanity": { "success": ["[SUCCESS]"], - "error": ["OOPSIE","Error"] + "error": ["[OOPSIE]","Error"] }, "parameters": [ { From 106dc9db7b748dd67431e6ac8d6b00be1a3a2b44 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Sun, 1 Dec 2024 08:44:12 +0100 Subject: [PATCH 24/52] up exe local --- tests/data/parallelSum | Bin 106048 -> 83880 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/data/parallelSum b/tests/data/parallelSum index 8460bddfe95498297f0a6110a7f55d0b073e9999..54d9519d9dc11e3d4ea5353b9c50080d14d0964c 100755 GIT binary patch literal 83880 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 literal 106048 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 Date: Mon, 2 Dec 2024 10:44:29 +0100 Subject: [PATCH 25/52] add comments --- config/tests_parallelSum/parallelSum.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/tests_parallelSum/parallelSum.json b/config/tests_parallelSum/parallelSum.json index 15622371..7c248a8a 100644 --- a/config/tests_parallelSum/parallelSum.json +++ b/config/tests_parallelSum/parallelSum.json @@ -3,16 +3,19 @@ "output_directory": "{{machine.output_app_dir}}/tests/data/outputs/parallelSum", "use_case_name": "parallel_sum", "timeout":"0-0:5:0", + //Application options "options": [ "{{parameters.elements.value}}", "{{output_directory}}/{{instance}}" ], + // Files containing app outputs "outputs": [ { "filepath":"{{output_directory}}/{{instance}}/outputs.csv", "format":"csv" } ], + //Files containing execution times "scalability": { "directory": "{{output_directory}}/{{instance}}/", "stages": [ @@ -24,10 +27,12 @@ } ] }, + // Only stdout supported at the moment "sanity": { "success": ["[SUCCESS]"], "error": ["[OOPSIE]","Error"] }, + // Test parameters "parameters": [ { "name": "nb_tasks", From 6fe3b80446300c4b6d9ab1c60f04995cbe558ea5 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 10:47:36 +0100 Subject: [PATCH 26/52] typos --- docs/modules/tutorial/pages/configurationfiles/machine.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/tutorial/pages/configurationfiles/machine.adoc b/docs/modules/tutorial/pages/configurationfiles/machine.adoc index d6f32a8f..25e7251c 100644 --- a/docs/modules/tutorial/pages/configurationfiles/machine.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/machine.adoc @@ -136,7 +136,7 @@ Below, an example of a machine configuration file can be found, for a machine ca Let's review step by step what the file defines. -- `"machine":"my_machine"` indicates that the ReFrame config can be found as _my\_machine.py_ +- `"machine":"my_machine"` indicates that the ReFrame config can be found as _my_machine.py_ - `"targets":"production:builtin:hpcx"` tells reframe to run tests uniquely on the production partition with the builtin platform and the hpcx programming environment. - `"execution_policy":"async"` tells ReFrame to run tests asynchronously on available resources. - `"reframe_base_dir":"$PWD/build/reframe"` Reframe will use the _build/stage/_ folder and _build/output/_ folder of the current working directory for staging tests and storing the benchmarked application's standard output and errors. @@ -148,5 +148,5 @@ Concerning containers: - The `"apptainer"` key indicated that the application COULD be benchmarked using apptainer. Not necesserily that it will. If the `targets` field specifies the apptainer platform, then this field is mandatory. - `"image_base_dir":"/data/images"` indicates that the built apptainer images can be found somewhere under the _/data/images/ directory. The rest of the path is specified on the benchmark configuration. -- `"options":"[ "--sharens", "--bind /opt/:/opt/" ]"` Tells ReFrame to add these options to the Apptainer execution command. For example, `mpiexec -n 4 apptainer exec --sharens --bind /opt/:/opt/`. Only machine related options should be specified here, more options can be defined in the benchmark configuration. +- `"options":"[ "--sharens", "--bind /opt/:/opt/" ]"` Tells ReFrame to add these options to the Apptainer execution command. For example, `mpiexec -n 4 apptainer exec --sharens --bind /opt/:/opt/ ...`. Only machine related options should be specified here, more options can be defined in the benchmark configuration. From f5b6d207a66200af68c34346ab9b7af594f5f1ce Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 13:31:28 +0100 Subject: [PATCH 27/52] output_dir optional --- src/feelpp/benchmarking/reframe/config/configSchemas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feelpp/benchmarking/reframe/config/configSchemas.py b/src/feelpp/benchmarking/reframe/config/configSchemas.py index c5fa2977..2e2beb0c 100644 --- a/src/feelpp/benchmarking/reframe/config/configSchemas.py +++ b/src/feelpp/benchmarking/reframe/config/configSchemas.py @@ -71,7 +71,7 @@ class ConfigFile(BaseModel): executable: str timeout: str platforms:Optional[Dict[str,Platform]] = {"builtin":Platform()} - output_directory:str + output_directory:Optional[str] = "" use_case_name: str options: List[str] outputs: List[AppOutput] From 8190572d0b0449318416512f83db119dae0f1617 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 13:31:34 +0100 Subject: [PATCH 28/52] fix logspace bug --- src/feelpp/benchmarking/reframe/parameters.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/feelpp/benchmarking/reframe/parameters.py b/src/feelpp/benchmarking/reframe/parameters.py index c469910f..70d143ad 100644 --- a/src/feelpp/benchmarking/reframe/parameters.py +++ b/src/feelpp/benchmarking/reframe/parameters.py @@ -33,10 +33,10 @@ class LogspaceParameter(Parameter): """ Parameter that generates evenly spaced samples on a log scale using a min, max, a number of steps and the log base""" def __init__(self, param_config): super().__init__(param_config) - self.min = param_config.linspace.min - self.max = param_config.linspace.max - self.n_steps = param_config.linspace.n_steps - self.base = param_config.linspace.base + self.min = param_config.logspace.min + self.max = param_config.logspace.max + self.n_steps = param_config.logspace.n_steps + self.base = param_config.logspace.base def parametrize(self): yield from np.logspace(self.min,self.max,self.n_steps,endpoint=True,base=self.base,dtype=object) From 35b37590457499abff451712c3dde5a06fd29fba Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 13:51:27 +0100 Subject: [PATCH 29/52] typo --- docs/modules/tutorial/pages/configurationfiles/machine.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/tutorial/pages/configurationfiles/machine.adoc b/docs/modules/tutorial/pages/configurationfiles/machine.adoc index 25e7251c..da02a697 100644 --- a/docs/modules/tutorial/pages/configurationfiles/machine.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/machine.adoc @@ -19,7 +19,7 @@ The following table describes all supported fields. | Yes | str | Either 'async' or 'serial'. The way in which ReFrame will run the tests. -| Serial +| serial | reframe_base_dir | No From d42e9e6781bf4de29acf9181304aa479691b7e5a Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 13:51:38 +0100 Subject: [PATCH 30/52] add parameter doc #90 --- .../pages/configurationfiles/benchmark.adoc | 386 +++++++++++++++++- 1 file changed, 385 insertions(+), 1 deletion(-) diff --git a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc index e9ecc121..5116cbe2 100644 --- a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc @@ -7,7 +7,6 @@ The base of the configuration file is shown below. ---- { "executable": "", - "output_directory": "", "use_case_name": "", "timeout":"", "platforms":{}, @@ -21,12 +20,397 @@ The base of the configuration file is shown below. == Fields on JSON root +Users can add any field used for refactoring. For example, one can do the following. + +[source,json] +---- +"output_directory":"/data/outputs" // This is a custom field +"options":["--output {{output_directory}}"] +---- + +Mandatory and actionable fields are: + +[cols="2,1,1,3,1"] +|=== +| Field name | Optional | type | description | Default + +| executable +| No +| str +| Path or name of the application executable. +| + +| use_case_name +| No +| str +| Custom name given to the use case. Serves as an ID of the use case, must be unique across use cases. +| + +| timeout +| No +| str +| Job execution timeout. Format: days-hours:minutes:seconds +| + +|=== + == Platforms +The `platforms` object lists all options and directories related to the benchmark execution for each supported platform. A platform present on this object does not imply that it will be benchmarked, but it rather lists all possible options. + +The field is optional, if not provided, the builtin platform will be considered. + +The syntax for builtin platform is the following: + +[source,json] +---- +"platforms": { + "builtin":{ + "input_dir":"", + "append_app_option":[] + } +} +---- + +- `append_app_options` is in this case equivalent to the `options` field on the configuration root. +- `input_dir` indicates the path of the directory where input files can be found. + +The following example shows how to configure the Apptainer platform: + +[source,json] +---- +"platforms":{ + "apptainer":{ + "image":{ + "name":"{{machine.containers.apptainer.image_base_dir}}/my_image.sif" + }, + "input_dir":"/input_data/", + "options":["--home {{machine.output_app_dir}}"], + "append_app_options":["--my_custom_option_for_apptainer"] + } +} +---- + +For any container, the `image` field must be specified, specifically `image.name`, containing the path of the image. Pulling images is not yet supported. + +In this case, `input_dir` represents the directory where input files will be found INSIDE the container. + +The `options` field contains a list of all the options to include on the container execution. It is equivalent to the machine's `containers.apptainer.options` field. However, users should only include application dependent options in this list. + +The `append_app_options` lists all the options to add to the application execution. It does the same as the `options` field in the root of the file, but can be used for case handling. + == Outputs +The `outputs` field lists all the files where application outputs are exported. + + +[cols="2,1,1,3,1"] +|=== +| Field name | Optional | type | description | Default + +| filepath +| No +| str +| Path of the file containing the outputs +| + +| filepath +| No +| str (csv, json) +| Format of the output file +| + +|=== + +All columns or fields present on the output file will be considered. +Outputs are added to the ReFrame report as pervormance variables. + +[NOTE] +==== +Soon, the same syntax as scalability files will be used. +==== + == Scalability +Lists all the files where performance times can be found. + +[cols="2,1,1,3,1"] +|=== +| Field name | Optional | type | description | Default + +| directory +| No +| str +| Common directory where scalability files can be found. Used for refactoring fields. + +| stages +| No +| list[Stage] +| List of scalability file objects describing them. +| + +|=== + +Each stage object is described as follows + +[cols="2,1,1,3,1"] +|=== +| Field name | Optional | type | description | Default + +| name +| No +| str +| Prefix to add to the performance variables found in the file +| + +| filepath +| No +| str +| partial filepath, relative to the `directory` field, where values are found. +| + + +| format +| No +| str +| Format of the file. Supported values are (csv, json, tsv) +| + +| variables_path +| Yes +| str +| Only if format is json. Defines where, in the JSON hierrarchy, performance variables will be found. Supports the use of a single wildcard (`*`). +| + +|=== + +An example of the scalability field is found and explained below. + +[source,json] +---- +"scalability": { + "directory": "{{output_directory}}/{{instance}}/cem/", + "stages": [ + { + "name":"custom_execution_name", + "filepath": "instances/np_{{parameters.nb_tasks.tasks.value}}/logs/execution_timers.json", + "format": "json", + "variables_path":"execution.*" + }, + { + "name":"construction", + "filepath": "logs/timers.json", + "format": "json", + "variables_path":"*.constructor" + } + ] +} +---- + +- `directory` implies that scalability files can be found under `{{output_directory}}/{{instance}}/cem/`. Where `output_directory` is defined above, and `instance` is a reserved keyword containing the hashcode of the test. + +There are two scalability files in the example. Let's suppose files are built like follows: + +- _logs/execution_timers.json_ +[source,json] +---- +{ + "execution":{ + "step1":0.5, + "step2":0.7, + "step3":1.0, + }, + "postprocess":{...} +} +---- + +- _logs/timers.json_ +[source,json] +---- +{ + "function1":{ + "constructor":1.0, + "init":0.1, + }, + "function2":{ + "constructor":1.0, + "init":0.1, + } +} +---- + +Then, by specifying `"variables_path":"exection.*"`, performance variables will be `custom_execution_name.step1`, `custom_execution_name.step2` and `custom_execution_name.step3`. + +And by specifying `"variables_path":"*.constructor` for the other file, performance vairalbes will be `construction.function1`, and `construction.function2`. + +Note how variables are prefixed with the value under `name`, and that the wildcard (`*`) determines the variable names. + +[NOTE] +==== +Deeply nested and complex JSON scalability files are supported. +==== + == Sanity +The `sanity` field is used to validate the application execution. + +The syntax is the following: + +[source,json] +---- +"sanity":{ + "success":[], + "error":[] +} +---- + +- The `success` field contains a list of patterns to look for in the standard output. If any of the patterns are not found, the test will fail. +- The `error` field contains a list of patters that will make the test fail if found in the standard output. If any of these paterns are found, the test will fail. + +[NOTE] +==== +At the moment, only validating standard output is supported. It will soon be possible to specify custom log files. +==== + == Parameters + +The `parameters` field list all parameters to be used in the test. +The cartesian product of the elements in this list will determine the benchmarks. + +Parameters are accessible across the whole configuration file by using the syntax `{{parameters.my_parameter.value}}`. + +Each parameter is described by a name and a generator. + +Valid generators are : + + +- `linspace`: +[source,json] +---- +{ + "name": "my_linspace_generator", + "logspace":{ + "min":1, + "max":10, + "n_steps":5 + } +} +---- + +- `logspace`: +[source,json] +---- +{ + "name": "my_logspace_generator", + "logspace":{ + "min":1, + "max":10, + "n_steps":5, + "base":2 + } +} +---- + +- `range`: +[source,json] +---- +{ + "name": "my_range_generator", + "logspace":{ + "min":1, + "max":10, + "step":1 + } +} +---- + + +- `geometric`: +[source,json] +---- +{ + "name": "my_geometric_generator", + "logspace":{ + "start":1, + "ratio":2, + "n_steps":5 + } +} +---- + +- `repeat`: +[source,json] +---- +{ + "name": "my_repeat_generator", + "repeat":{ + "value":"a repeated value", + "count":5 + } +} +---- + +- `sequence`: + +[source,json] +---- +{ + "name": "my_sequence_generator", + "sequence":[ + {"val1":1,"val2":2}, + {"val1":3,"val2":4}, + {"val1":5,"val2":6} + ] +} +---- + + +- `zip` and subparameters: + +Parameters can contain subparameters, which can be accessed recursively via the `.` separator. Its objective is to have parameters that depend on eachother, without producing a cartesian product. +Aditionnaly, parameters can be zipped together via the `zip` generator. +The `zip` generator takes a list of parameters to produce a list of python dictionaries. Each param inside the list can then have any desired generator from above. + +[source,json] +---- +{ + "name": "my_zip_generator", + "zip":[ + { + "name":"param1", + "sequence":[ + {"val1":1,"val2":2}, + {"val1":3,"val2":4}, + {"val1":5,"val2":6} + ] + }, + { + "name":"param2", + "repeat":{ + "value":"a repeated value", + "count":3 + } + } + ] +} +---- + +[WARNING] +==== +Zipped parameters need to have the same lenght. +==== + +- Special parameters + +There is one special parameter: `nb_tasks`. If included, should follow some rules for its subparameters. + +- Accepts `exclusive_access` subparameter. Defaults to `true`. +- Either specify `tasks_per_node` and `tasks` subparameters, OR +- Specify `tasks_per_node` and `nodes` subparameters, OR +- Specify only the `tasks` parameter. +- Specifying `tasks` and `nodes` is NOT currently supported. + +The `nb_tasks` parameter and its subparameters are directly accesses by ReFrame. + +Other parameters have only an impact on the application execution, meaning that they should be passed as options to the executable. + From c2901ead748d70347905815648e2c897ae6c48ac Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 14:03:58 +0100 Subject: [PATCH 31/52] fix outputs #90 --- tests/data/parallelSum.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/data/parallelSum.cpp b/tests/data/parallelSum.cpp index b524497a..a6ab74e9 100644 --- a/tests/data/parallelSum.cpp +++ b/tests/data/parallelSum.cpp @@ -60,9 +60,6 @@ int main(int argc, char** argv) scal_outfile << "{\n"; scal_outfile << " \"computation_time\": " << computation_time << ",\n"; scal_outfile << " \"communication_time\": " << communication_time << ",\n"; - scal_outfile << " \"num_processes\": " << size << ",\n"; - scal_outfile << " \"N\": " << N << ",\n"; - scal_outfile << " \"sum\": " << global_sum << "\n"; scal_outfile << "}\n"; scal_outfile.close(); } @@ -73,8 +70,8 @@ int main(int argc, char** argv) std::ofstream out_outfile(output_dir/out_filename); if (out_outfile.is_open()) { - out_outfile << "N,sum\n"; - out_outfile << N << "," < Date: Mon, 2 Dec 2024 14:21:06 +0100 Subject: [PATCH 32/52] add parameter examples #90 --- .../pages/configurationfiles/benchmark.adoc | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc index 5116cbe2..fa2b3469 100644 --- a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc @@ -290,12 +290,13 @@ Valid generators are : { "name": "my_linspace_generator", "logspace":{ - "min":1, + "min":2, "max":10, "n_steps":5 } } ---- +The example will yield `[2,4,6,8,10]`. Min and max are inclusive. - `logspace`: [source,json] @@ -305,11 +306,12 @@ Valid generators are : "logspace":{ "min":1, "max":10, - "n_steps":5, + "n_steps":4, "base":2 } } ---- +The example will yield `[2,16,128,1024]`. Min and max are inclusive. - `range`: [source,json] @@ -318,11 +320,12 @@ Valid generators are : "name": "my_range_generator", "logspace":{ "min":1, - "max":10, + "max":5, "step":1 } } ---- +The example will yield `[1,2,3,4,5]`. Min and max are inclusive. - `geometric`: @@ -337,6 +340,7 @@ Valid generators are : } } ---- +The example will yield `[1,2,4,8,16]`. - `repeat`: [source,json] @@ -345,24 +349,25 @@ Valid generators are : "name": "my_repeat_generator", "repeat":{ "value":"a repeated value", - "count":5 + "count":3 } } ---- +The example will yield `["a repeated value", "a repeated value", "a repeated value"]`. - `sequence`: +Sequence accepts + [source,json] ---- { "name": "my_sequence_generator", - "sequence":[ - {"val1":1,"val2":2}, - {"val1":3,"val2":4}, - {"val1":5,"val2":6} - ] + "sequence":[ 1, 2, 3, 4] } ---- +Sequence is the simplest generator. It will yield exactly the given list. +It accepts dictionnaries as items, which can then be accessed via the `.` separator. - `zip` and subparameters: @@ -394,6 +399,7 @@ The `zip` generator takes a list of parameters to produce a list of python dicti ] } ---- +This example will yield `[{'param1': {'val1': 1, 'val2': 2}, 'param2': 'a repeated value'}, {'param1': {'val1': 3, 'val2': 4}, 'param2': 'a repeated value'}, {'param1': {'val1': 5, 'val2': 6}, 'param2': 'a repeated value'}]` [WARNING] ==== @@ -404,11 +410,10 @@ Zipped parameters need to have the same lenght. There is one special parameter: `nb_tasks`. If included, should follow some rules for its subparameters. -- Accepts `exclusive_access` subparameter. Defaults to `true`. -- Either specify `tasks_per_node` and `tasks` subparameters, OR -- Specify `tasks_per_node` and `nodes` subparameters, OR -- Specify only the `tasks` parameter. -- Specifying `tasks` and `nodes` is NOT currently supported. +Accepts `exclusive_access` subparameter. Defaults to `true`. +Either specify `tasks_per_node` and `tasks` subparameters, OR specify `tasks_per_node` and `nodes` subparameters, OR Specify only the `tasks` parameter. + +Specifying `tasks` and `nodes` is NOT currently supported. The `nb_tasks` parameter and its subparameters are directly accesses by ReFrame. From 84eccef033635deac428bfa107ae62b4c1dc8e54 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 14:46:24 +0100 Subject: [PATCH 33/52] fix wrong comma and optimize --- tests/data/parallelSum | Bin 83880 -> 40632 bytes tests/data/parallelSum.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/parallelSum b/tests/data/parallelSum index 54d9519d9dc11e3d4ea5353b9c50080d14d0964c..3b03303da890ce88e7965aa6d802422082fb1d57 100755 GIT binary patch literal 40632 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 diff --git a/tests/data/parallelSum.cpp b/tests/data/parallelSum.cpp index a6ab74e9..736275bb 100644 --- a/tests/data/parallelSum.cpp +++ b/tests/data/parallelSum.cpp @@ -59,7 +59,7 @@ int main(int argc, char** argv) { scal_outfile << "{\n"; scal_outfile << " \"computation_time\": " << computation_time << ",\n"; - scal_outfile << " \"communication_time\": " << communication_time << ",\n"; + scal_outfile << " \"communication_time\": " << communication_time << "\n"; scal_outfile << "}\n"; scal_outfile.close(); } From 3be94df8884d82809fd910b410ab2791fd1d2910 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Mon, 2 Dec 2024 16:31:42 +0100 Subject: [PATCH 34/52] rm and ignore test executable --- .gitignore | 5 ++++- tests/data/parallelSum | Bin 40632 -> 0 bytes 2 files changed, 4 insertions(+), 1 deletion(-) delete mode 100755 tests/data/parallelSum diff --git a/.gitignore b/.gitignore index a9ec23ce..e406e867 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,7 @@ docs/modules/ROOT/pages/ reports/ #Test Outputs -tests/data/outputs/ \ No newline at end of file +tests/data/outputs/ + +#Executables +tests/data/parallelSum \ No newline at end of file diff --git a/tests/data/parallelSum b/tests/data/parallelSum deleted file mode 100755 index 3b03303da890ce88e7965aa6d802422082fb1d57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40632 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 Date: Mon, 2 Dec 2024 17:21:41 +0100 Subject: [PATCH 35/52] add exaple report and plots doc #90 --- docs/modules/tutorial/data/plots.json | 1 + .../modules/tutorial/data/reframe_report.json | 1644 +++++++++++++++++ .../pages/configurationfiles/plots.adoc | 213 ++- 3 files changed, 1857 insertions(+), 1 deletion(-) create mode 100644 docs/modules/tutorial/data/plots.json create mode 100644 docs/modules/tutorial/data/reframe_report.json diff --git a/docs/modules/tutorial/data/plots.json b/docs/modules/tutorial/data/plots.json new file mode 100644 index 00000000..40664510 --- /dev/null +++ b/docs/modules/tutorial/data/plots.json @@ -0,0 +1 @@ +[{"title": "Absolute performance", "plot_types": ["stacked_bar", "grouped_bar"], "transformation": "performance", "aggregations": null, "variables": ["computation_time"], "names": ["Time"], "xaxis": {"parameter": "nb_tasks.tasks", "label": "Number of tasks"}, "secondary_axis": {"parameter": "elements", "label": "N"}, "yaxis": {"parameter": null, "label": "Execution time (s)"}, "color_axis": null}, {"title": "Absolute performance", "plot_types": ["stacked_bar", "table"], "transformation": "performance", "aggregations": null, "variables": ["computation_time"], "names": ["Time"], "xaxis": {"parameter": "elements", "label": "N"}, "secondary_axis": {"parameter": "nb_tasks.tasks", "label": "Number of tasks"}, "yaxis": {"parameter": null, "label": "Execution time (s)"}, "color_axis": null}, {"title": "Speedup", "plot_types": ["scatter"], "transformation": "speedup", "aggregations": null, "variables": ["computation_time"], "names": ["Time"], "xaxis": {"parameter": "nb_tasks.tasks", "label": "Number of tasks"}, "secondary_axis": {"parameter": "elements", "label": "N"}, "yaxis": {"parameter": null, "label": "Execution time (s)"}, "color_axis": null}] \ No newline at end of file diff --git a/docs/modules/tutorial/data/reframe_report.json b/docs/modules/tutorial/data/reframe_report.json new file mode 100644 index 00000000..74d1fad3 --- /dev/null +++ b/docs/modules/tutorial/data/reframe_report.json @@ -0,0 +1,1644 @@ +{ + "session_info": { + "cmdline": "/Users/cladellash/Documents/Repos/benchmarking/.venv/bin/reframe -C /Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/config/machineConfigs/local.py -c /Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py -S report_dir_path=/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28 --system=local --exec-policy=async --prefix=/Users/cladellash/Documents/Repos/benchmarking/build/reframe --report-file=/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28/reframe_report.json -J '#SBATCH --time=0-0:5:0' --perflogdir=/Users/cladellash/Documents/Repos/benchmarking/build/reframe/logs -v -r", + "config_files": [ + "", + "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/config/machineConfigs/local.py" + ], + "data_version": "3.1", + "hostname": "irma-dhcp-2.math.unistra.fr", + "log_files": [ + "/var/folders/pd/r8v9chs90wb1bj6pm0x147jr0000gp/T/rfm-qml5j4xz.log" + ], + "prefix_output": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output", + "prefix_stage": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage", + "user": "cladellash", + "version": "4.6.3", + "workdir": "/Users/cladellash/Documents/Repos/benchmarking", + "time_start": "2024-12-02T14:46:29+0100", + "time_end": "2024-12-02T14:46:40+0100", + "time_elapsed": 11.50057601928711, + "num_cases": 12, + "num_failures": 0 + }, + "runs": [ + { + "num_cases": 12, + "num_failures": 0, + "num_aborted": 0, + "num_skipped": 0, + "runid": 0, + "testcases": [ + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=1000000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "aa223ed0", + "jobid": "99178", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=1000000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_aa223ed0", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 5.32933 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.052584 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1000000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1000000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 4.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_aa223ed0", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.006192207336425781, + "time_performance": 0.008784055709838867, + "time_run": 9.518624067306519, + "time_sanity": 0.007528066635131836, + "time_setup": 0.00566411018371582, + "time_total": 9.696507215499878, + "unique_name": "RegressionTest_11", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "1000000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/aa223ed0" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 4, + "num_tasks_per_node": 4, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 4, + "exclusive_access": true + }, + "elements": 1000000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=700000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "6a58f265", + "jobid": "99179", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=700000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_6a58f265", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 4.56971 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.005627 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 700000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 700000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 4.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_6a58f265", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.007662057876586914, + "time_performance": 0.038092851638793945, + "time_run": 8.129333019256592, + "time_sanity": 0.03859901428222656, + "time_setup": 0.009199142456054688, + "time_total": 8.30247712135315, + "unique_name": "RegressionTest_10", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "700000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/6a58f265" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 4, + "num_tasks_per_node": 4, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 4, + "exclusive_access": true + }, + "elements": 700000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=400000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "e8955ef5", + "jobid": "99180", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=400000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_e8955ef5", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 3.85582 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.180105 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 400000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 400000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 4.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_e8955ef5", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.008015155792236328, + "time_performance": 0.03525996208190918, + "time_run": 7.037631988525391, + "time_sanity": 0.03978276252746582, + "time_setup": 0.01161503791809082, + "time_total": 7.199726104736328, + "unique_name": "RegressionTest_09", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "400000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/e8955ef5" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 4, + "num_tasks_per_node": 4, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 4, + "exclusive_access": true + }, + "elements": 400000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=100000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "9886e190", + "jobid": "99181", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 4, 'exclusive_access': True} %elements=100000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_9886e190", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.062597 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.0161 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 100000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 100000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 4.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_9886e190", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.006299018859863281, + "time_performance": 0.017982006072998047, + "time_run": 1.7802720069885254, + "time_sanity": 0.014677762985229492, + "time_setup": 0.005388975143432617, + "time_total": 1.927483081817627, + "unique_name": "RegressionTest_08", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "100000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/9886e190" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 4, + "num_tasks_per_node": 4, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 4, + "exclusive_access": true + }, + "elements": 100000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=1000000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "86092ceb", + "jobid": "99182", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=1000000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_86092ceb", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 5.13016 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.000502 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1000000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1000000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 2.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_86092ceb", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.00612187385559082, + "time_performance": 0.002651214599609375, + "time_run": 10.523810148239136, + "time_sanity": 0.0021507740020751953, + "time_setup": 0.005548954010009766, + "time_total": 10.664539098739624, + "unique_name": "RegressionTest_07", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "1000000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/86092ceb" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 2, + "num_tasks_per_node": 2, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 2, + "exclusive_access": true + }, + "elements": 1000000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=700000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "b22a7385", + "jobid": "99183", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=700000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_b22a7385", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 5.06941 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.03559 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 700000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 700000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 2.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_b22a7385", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.00615692138671875, + "time_performance": 0.015397310256958008, + "time_run": 9.810746192932129, + "time_sanity": 0.025763988494873047, + "time_setup": 0.006819963455200195, + "time_total": 9.945525169372559, + "unique_name": "RegressionTest_06", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "700000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/b22a7385" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 2, + "num_tasks_per_node": 2, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 2, + "exclusive_access": true + }, + "elements": 700000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=400000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "7dd0d8fb", + "jobid": "99184", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=400000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_7dd0d8fb", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 4.70458 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.129757 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 400000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 400000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 2.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_7dd0d8fb", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.006106138229370117, + "time_performance": 0.00861215591430664, + "time_run": 8.266666889190674, + "time_sanity": 0.006582021713256836, + "time_setup": 0.005933046340942383, + "time_total": 8.394183158874512, + "unique_name": "RegressionTest_05", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "400000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/7dd0d8fb" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 2, + "num_tasks_per_node": 2, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 2, + "exclusive_access": true + }, + "elements": 400000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=100000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "e75954a0", + "jobid": "99185", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 2, 'exclusive_access': True} %elements=100000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_e75954a0", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.183174 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.003264 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 100000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 100000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 2.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_e75954a0", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.00605320930480957, + "time_performance": 0.019010066986083984, + "time_run": 1.770622968673706, + "time_sanity": 0.0030341148376464844, + "time_setup": 0.00586390495300293, + "time_total": 1.8920440673828125, + "unique_name": "RegressionTest_04", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "100000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/e75954a0" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 2, + "num_tasks_per_node": 2, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 2, + "exclusive_access": true + }, + "elements": 100000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=1000000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "cbfe221b", + "jobid": "99225", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=1000000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_cbfe221b", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 4.8334 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 2.1e-05 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1000000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1000000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_cbfe221b", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.005920886993408203, + "time_performance": 0.0037949085235595703, + "time_run": 9.820374727249146, + "time_sanity": 0.003256082534790039, + "time_setup": 0.005385160446166992, + "time_total": 11.37114691734314, + "unique_name": "RegressionTest_03", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "1000000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/cbfe221b" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 1, + "num_tasks_per_node": 1, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 1, + "exclusive_access": true + }, + "elements": 1000000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=700000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "be4af6da", + "jobid": "99226", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=700000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_be4af6da", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 4.90371 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 2.7e-05 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 700000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 700000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_be4af6da", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.005860805511474609, + "time_performance": 0.0030002593994140625, + "time_run": 9.275190114974976, + "time_sanity": 0.002341032028198242, + "time_setup": 0.005341053009033203, + "time_total": 10.844825267791748, + "unique_name": "RegressionTest_02", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "700000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/be4af6da" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 1, + "num_tasks_per_node": 1, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 1, + "exclusive_access": true + }, + "elements": 700000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=400000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "e8e66601", + "jobid": "99278", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=400000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_e8e66601", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 2.24316 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 3.2e-05 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 400000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 400000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_e8e66601", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.0059511661529541016, + "time_performance": 0.002692699432373047, + "time_run": 4.065032005310059, + "time_sanity": 0.002173185348510742, + "time_setup": 0.005150794982910156, + "time_total": 10.587581872940063, + "unique_name": "RegressionTest_01", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "400000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/e8e66601" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 1, + "num_tasks_per_node": 1, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 1, + "exclusive_access": true + }, + "elements": 400000000.0 + } + }, + { + "build_stderr": null, + "build_stdout": null, + "dependencies_actual": [], + "dependencies_conceptual": [], + "description": "", + "display_name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=100000000.0", + "environment": "default", + "fail_phase": null, + "fail_reason": null, + "filename": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe/regression.py", + "fixture": false, + "hash": "da2298ca", + "jobid": "99283", + "job_stderr": "rfm_job.err", + "job_stdout": "rfm_job.out", + "maintainers": [], + "name": "RegressionTest %nb_tasks={'tasks': 1, 'exclusive_access': True} %elements=100000000.0", + "nodelist": [ + "irma-dhcp-2.math.unistra.fr" + ], + "outputdir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/output/local/default/default/RegressionTest_da2298ca", + "perfvars": [ + { + "name": "computation_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 0.622329 + }, + { + "name": "communication_time", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "s", + "value": 3.2e-05 + }, + { + "name": "N", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 100000000.0 + }, + { + "name": "sum", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 100000000.0 + }, + { + "name": "num_process", + "reference": 0, + "thres_lower": null, + "thres_upper": null, + "unit": "", + "value": 1.0 + } + ], + "prefix": "/Users/cladellash/Documents/Repos/benchmarking/.venv/lib/python3.8/site-packages/feelpp/benchmarking/reframe", + "result": "success", + "stagedir": "/Users/cladellash/Documents/Repos/benchmarking/build/reframe/stage/local/default/default/RegressionTest_da2298ca", + "scheduler": "local", + "system": "local:default", + "tags": [ + "async" + ], + "time_compile": 0.005639791488647461, + "time_performance": 0.008454084396362305, + "time_run": 1.732982873916626, + "time_sanity": 0.0396878719329834, + "time_setup": 0.005467891693115234, + "time_total": 9.557442903518677, + "unique_name": "RegressionTest_00", + "check_vars": { + "valid_prog_environs": [ + "default" + ], + "valid_systems": [ + "local:default" + ], + "descr": "", + "sourcepath": "", + "sourcesdir": null, + "prebuild_cmds": [], + "postbuild_cmds": [], + "executable": "/Users/cladellash/Documents/Repos/benchmarking//tests/data/parallelSum", + "executable_opts": [ + "100000000.0", + "/Users/cladellash/Documents/Repos/benchmarking/tests/data/outputs/parallelSum/da2298ca" + ], + "prerun_cmds": [], + "postrun_cmds": [], + "keep_files": [], + "readonly_files": [], + "tags": [ + "async" + ], + "maintainers": [], + "strict_check": true, + "num_tasks": 1, + "num_tasks_per_node": 1, + "num_gpus_per_node": null, + "num_cpus_per_task": 1, + "num_tasks_per_core": null, + "num_tasks_per_socket": null, + "use_multithreading": null, + "max_pending_time": null, + "exclusive_access": true, + "local": false, + "modules": [], + "env_vars": {}, + "variables": {}, + "time_limit": null, + "build_time_limit": null, + "extra_resources": {}, + "build_locally": true, + "report_dir_path": "/Users/cladellash/Documents/Repos/benchmarking/reports/parallelSum/parallel_sum/local/2024_12_02T14_46_28", + "use_case": "parallel_sum", + "platform": "builtin" + }, + "check_params": { + "nb_tasks": { + "tasks": 1, + "exclusive_access": true + }, + "elements": 100000000.0 + } + } + ] + } + ], + "restored_cases": [] +} diff --git a/docs/modules/tutorial/pages/configurationfiles/plots.adoc b/docs/modules/tutorial/pages/configurationfiles/plots.adoc index 97983328..67639304 100644 --- a/docs/modules/tutorial/pages/configurationfiles/plots.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/plots.adoc @@ -1 +1,212 @@ -= Figures \ No newline at end of file += Figures +:page-plotly: true +:page-jupyter: true + +In order to generate reports, the _Feel++ benchmarking_ framework requires a figure description to specify what the website report page should contain. + +These descriptions should be provided either with a specific JSON file with the structure containing uniquely + +[source,json] +---- +{ + "plots":[] +} +---- + +Or by specifying the `plots` field on the benchmark configuration JSON file. + +Each figure description should contain the following fields + +[source,json] +---- +{ + "title": "The figure title", + "plot_types": [], //List of figure types + "transformation": "", //Transformation type + "variables":[], // List of variables to consider + "names":[], //Respective labels for variables + "yaxis":{}, + "xaxis":{}, + "color_axis":{}, //Default: performance variables + "secondary_axis":{} +} +---- + +Figures will appear in the same order as they appear on the list. + +Users can provide multiple plot_types in the same description field. + +[NOTE] +==== +Only performance variables specified under the `variables` list will be considered. If the list is empty, ALL variables inside the ReFrame report will be taken into account. +==== + +== Axis +Each axis (with the exception of the `yaxis`) take a `parameter` and a `label` field. +The `yaxis` will always contain the performance values, therefore only the `label` key should be specified. + +The `parameter` field of each axis should correspond to either a single dimension parameter specified on the benchmark configuration. +In the case of subparameters, the syntax should be the following: `parameter.subparameter`. + +By default, the color axis will contain the performance variables, but this can be customized. + +== Transformations + +The ReFrame report will be used to create a _Master DataFrame_, which will contain all performance variables and their respective values, as well as all parameters and environments. + +To explain how transformation and plot types work, we can consider the following example. + +[%dynamic%open%hide_code,python] +---- +import json +from feelpp.benchmarking.report.atomicReports.model import AtomicReportModel +with open("./docs/modules/tutorial/data/reframe_report.json","r") as rfm_report: + report = json.load(rfm_report) + +model = AtomicReportModel(report["runs"]) +model.master_df = model.master_df[model.master_df["performance_variable"].isin(["computation_time","communication_time"])].loc[:,["performance_variable","value","unit", "testcase_time_run","environment","platform","nb_tasks.tasks","nb_tasks.exclusive_access","elements"]] +---- + + +[%dynamic%open%hide_code,python] +---- +model.master_df +---- + +We can see that this dataframe contains the parameters: +- environment +- platform +- nb_tasks.tasks +- nb_tasks.exclusive_access +- elements +- performance_variable + +By having this common structure, we can make use of transformation strategies to manipulate values depending on the desired output. + +Strategies will depend on the figure axis. All strategies will create a pivot dataframe that will contain the parameter specified as `color_axis` as columns, `xaxis` as first level index and `secondary_axis` as second level index. Values of the dataframe will always be the `values` of the master dataframe. + +As an example, we will consider the following axis: +[source,json] +---- +"xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" +}, +"yaxis":{ + "label":"Execution time (s)" +}, +"secondary_axis":{ + "parameter":"elements", + "label":"N" +}, +"color_axis":{ + "parameter":"performance_variable", + "label":"Performance variable" +} +---- + +Available strategies are: +- performance + +This strategy should be seen as the "base" strategy. No transformation, other that a pivot, is done. +For the given example, it produces the following dataframe + +[%dynamic%open%hide_code,python] +---- +from feelpp.benchmarking.report.strategies import StrategyFactory +from feelpp.benchmarking.reframe.config.configPlots import Plot +plot_config = Plot(**{ + "title": "Absolute performance", + "plot_types": [ "stacked_bar", "grouped_bar" ], + "transformation": "performance", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + } +}) +strategy = StrategyFactory.create(plot_config) +strategy.calculate(model.master_df) +---- + +- relative_performance + +The relative performance strategy computes the proportion of the time that a a `color_axis` variable takes with regards of the total. + +[%dynamic%open%hide_code,python] +---- +from feelpp.benchmarking.report.strategies import StrategyFactory +from feelpp.benchmarking.reframe.config.configPlots import Plot +plot_config = Plot(**{ + "title": "Absolute performance", + "plot_types": [ "stacked_bar", "grouped_bar" ], + "transformation": "relative_performance", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + } +}) +strategy = StrategyFactory.create(plot_config) +strategy.calculate(model.master_df) +---- + +The sum along the column axis will always be equal to 1. + +- speedup + +The speedup strategy computes the speedup of the `color_axis` variables. The minimum of the `xaxis` values is taken as the base of the speedup. +For the example, this strategy will produce the following. + +[%dynamic%open%hide_code,python] +---- +from feelpp.benchmarking.report.strategies import StrategyFactory +from feelpp.benchmarking.reframe.config.configPlots import Plot +plot_config = Plot(**{ + "title": "Absolute performance", + "plot_types": [ "stacked_bar", "grouped_bar" ], + "transformation": "speedup", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + } +}) +strategy = StrategyFactory.create(plot_config) +strategy.calculate(model.master_df) +---- + +== Plot types + +- `scatter` + +- `stacked_bar` + +- `grouped_bar` + +- `table` + + + +== Custom layouts + + + From df37c9cf5ee210ecbbc347fed18a061e946cbef3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 01:17:28 +0000 Subject: [PATCH 36/52] Bump @antora/collector-extension from 1.0.0 to 1.0.1 --- updated-dependencies: - dependency-name: "@antora/collector-extension" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 33 ++++++++++++++++++++++++--------- package.json | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 992c78d1..960e3066 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "AGPL-3.0", "dependencies": { "@antora/cli": "~3.1.9", - "@antora/collector-extension": "^1.0.0", + "@antora/collector-extension": "^1.0.1", "@antora/site-generator": "~3.1.9", "@antora/site-generator-default": "~3.1.9", "@asciidoctor/core": "~2.2.8", @@ -58,11 +58,11 @@ } }, "node_modules/@antora/collector-extension": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@antora/collector-extension/-/collector-extension-1.0.0.tgz", - "integrity": "sha512-Qjk7ydxkVlKhXSopTztpBBpFmNEvssj9wuxxKr1sHQswIPPgzqPtS1vP6ra6dbfY1UgU3/lOpqGCqpBHgTRXTQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@antora/collector-extension/-/collector-extension-1.0.1.tgz", + "integrity": "sha512-Bq6s2ZN5VESJ3/skEeytfCeBRD4Z/K06dWQFPTMFUn3+nzaA/NDeQ1x16YPk491DeOSg4dXcW0CerwVqdL3zPQ==", "dependencies": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "@antora/run-command-helper": "~1.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -72,6 +72,14 @@ "node": ">=16.0.0" } }, + "node_modules/@antora/collector-extension/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/content-aggregator": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.9.tgz", @@ -3331,15 +3339,22 @@ } }, "@antora/collector-extension": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@antora/collector-extension/-/collector-extension-1.0.0.tgz", - "integrity": "sha512-Qjk7ydxkVlKhXSopTztpBBpFmNEvssj9wuxxKr1sHQswIPPgzqPtS1vP6ra6dbfY1UgU3/lOpqGCqpBHgTRXTQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@antora/collector-extension/-/collector-extension-1.0.1.tgz", + "integrity": "sha512-Bq6s2ZN5VESJ3/skEeytfCeBRD4Z/K06dWQFPTMFUn3+nzaA/NDeQ1x16YPk491DeOSg4dXcW0CerwVqdL3zPQ==", "requires": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "@antora/run-command-helper": "~1.0", "cache-directory": "~2.0", "fast-glob": "~3.3", "js-yaml": "~4.1" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + } } }, "@antora/content-aggregator": { diff --git a/package.json b/package.json index bc683217..ad849a83 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "dependencies": { "@antora/cli": "~3.1.9", - "@antora/collector-extension": "^1.0.0", + "@antora/collector-extension": "^1.0.1", "@antora/site-generator": "~3.1.9", "@antora/site-generator-default": "~3.1.9", "@asciidoctor/core": "~2.2.8", From 27116ae7ac43e7da87c276a0bd2a021907f75c80 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 09:50:09 +0100 Subject: [PATCH 37/52] rm TODO --- src/feelpp/benchmarking/report/applications/repository.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feelpp/benchmarking/report/applications/repository.py b/src/feelpp/benchmarking/report/applications/repository.py index d97366f4..514e5b01 100644 --- a/src/feelpp/benchmarking/report/applications/repository.py +++ b/src/feelpp/benchmarking/report/applications/repository.py @@ -20,7 +20,7 @@ def __init__(self, applications_json): ] self.id = "applications" self.display_name = "Applications" - self.description = "Applications [description TODO]" + self.description = "Applications" def link(self, machines, use_cases, execution_mapping): """ Create the links between the applications and the machines and test cases depending on the execution mapping From c005e186cc25ebd5a3b1d789181189e9f63bb949 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 10:07:52 +0100 Subject: [PATCH 38/52] change accumulate for loop --- tests/data/parallelSum.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/data/parallelSum.cpp b/tests/data/parallelSum.cpp index 736275bb..983d838c 100644 --- a/tests/data/parallelSum.cpp +++ b/tests/data/parallelSum.cpp @@ -34,7 +34,9 @@ int main(int argc, char** argv) std::vector local_array(local_end - local_start, 1.0); double start_time = MPI_Wtime(); - double local_sum = std::accumulate(local_array.begin(), local_array.end(), 0.0); + double local_sum = 0; + for (int i = 0; i < local_array.size(); ++i) + local_sum += local_array[i]; double end_time = MPI_Wtime(); double start_comm_time = MPI_Wtime(); From 9f2be97ae83c502f7f7e8373c0192fb2f8ff2342 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 10:50:35 +0100 Subject: [PATCH 39/52] fix table --- docs/modules/tutorial/pages/configurationfiles/benchmark.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc index fa2b3469..a8d901a3 100644 --- a/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/benchmark.adoc @@ -1,4 +1,6 @@ = Benchmark configuration +:page-plotly: true +:page-jupyter: true Configuring a benchmark can be quite extensive, as this framework focuses on flexibility. For this, the documentation will be divided in main sections. @@ -142,6 +144,7 @@ Lists all the files where performance times can be found. | No | str | Common directory where scalability files can be found. Used for refactoring fields. +| | stages | No From bb2b96f15b7478029e28bbee879ee5adae6ac3e6 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 10:50:45 +0100 Subject: [PATCH 40/52] Add figures (not showing ? ) --- .../pages/configurationfiles/plots.adoc | 109 +++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/docs/modules/tutorial/pages/configurationfiles/plots.adoc b/docs/modules/tutorial/pages/configurationfiles/plots.adoc index 67639304..f582f6d3 100644 --- a/docs/modules/tutorial/pages/configurationfiles/plots.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/plots.adoc @@ -196,17 +196,124 @@ strategy.calculate(model.master_df) == Plot types +Considering the same example axis as above, the software can generate the following figures: + - `scatter` +[%dynamic%open%hide_code,python] +---- +from feelpp.benchmarking.report.figureFactory import FigureFactory +figures = FigureFactory.create(Plot(**{ + "title": "Absolute performance", + "plot_types": [ "scatter" ], + "transformation": "performance", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "color_axis":{ + "parameter":"performance_variable", + "label":"Performance variable" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + }, + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + } +})) +fig = figures[0].createFigure(model.master_df) +fig.show() +---- + - `stacked_bar` +[%dynamic%open%hide_code,python] +---- +figures = FigureFactory.create(Plot(**{ + "title": "Absolute performance", + "plot_types": [ "stacked_bar" ], + "transformation": "performance", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "color_axis":{ + "parameter":"performance_variable", + "label":"Performance variable" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + }, + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + } +})) +fig = figures[0].createFigure(model.master_df) +fig.show() +---- + + - `grouped_bar` +[%dynamic%open%hide_code,python] +---- +figures = FigureFactory.create(Plot(**{ + "title": "Absolute performance", + "plot_types": [ "grouped_bar" ], + "transformation": "performance", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "color_axis":{ + "parameter":"performance_variable", + "label":"Performance variable" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + }, + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + } +})) +fig = figures[0].createFigure(model.master_df) +fig.show() +---- + - `table` +[%dynamic%open%hide_code,python] +---- +figures = FigureFactory.create(Plot(**{ + "title": "Absolute performance", + "plot_types": [ "table" ], + "transformation": "performance", + "variables": [ "computation_time","communication_time" ], + "names": ["Time"], + "color_axis":{ + "parameter":"performance_variable", + "label":"Performance variable" + }, + "yaxis":{"label":"Execution time (s)"}, + "secondary_axis":{ + "parameter":"elements", + "label":"N" + }, + "xaxis":{ + "parameter":"nb_tasks.tasks", + "label":"Number of tasks" + } +})) +fig = figures[0].createFigure(model.master_df) +fig.show() +---- -== Custom layouts +== Custom layouts From 298bba972aa6c7b16d4f49c8e71e5271a29c630e Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:16:49 +0100 Subject: [PATCH 41/52] add conf to nav #90 --- docs/modules/tutorial/nav.adoc | 6 +++++- docs/modules/tutorial/pages/plots.adoc | 0 2 files changed, 5 insertions(+), 1 deletion(-) delete mode 100644 docs/modules/tutorial/pages/plots.adoc diff --git a/docs/modules/tutorial/nav.adoc b/docs/modules/tutorial/nav.adoc index e56a7158..29981b18 100644 --- a/docs/modules/tutorial/nav.adoc +++ b/docs/modules/tutorial/nav.adoc @@ -2,4 +2,8 @@ * xref:tutorial:index.adoc[Documentation] ** xref:tutorial:gettingstarted.adoc[Getting Started] ** xref:tutorial:configuration.adoc[Configuration Guide] -** xref:tutorial:plots.adoc[Figures Guide] \ No newline at end of file +*** xref:tutorial:configurationfiles/system.adoc[System Configuration] +*** xref:tutorial:configurationfiles/magicstrings.adoc[Magic Strings] +*** xref:tutorial:configurationfiles/machine.adoc[Machine Configuration] +*** xref:tutorial:configurationfiles/benchmark.adoc[Benchmark Configuration] +*** xref:tutorial:configurationfiles/plots.adoc[Plots Configuration] \ No newline at end of file diff --git a/docs/modules/tutorial/pages/plots.adoc b/docs/modules/tutorial/pages/plots.adoc deleted file mode 100644 index e69de29b..00000000 From 4319149be1e1f3ff584b5622230b9c06f160c291 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:16:59 +0100 Subject: [PATCH 42/52] add layout and aggregations doc #90 --- .../pages/configurationfiles/plots.adoc | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/modules/tutorial/pages/configurationfiles/plots.adoc b/docs/modules/tutorial/pages/configurationfiles/plots.adoc index f582f6d3..c1473c45 100644 --- a/docs/modules/tutorial/pages/configurationfiles/plots.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/plots.adoc @@ -312,8 +312,67 @@ fig = figures[0].createFigure(model.master_df) fig.show() ---- +== Aggregations + +Depending on the dashboard level that we are located at, it might be necessary to aggregate the data on the master dataframe. +For example, if we have all use cases, applications and machines on the dataframe, and we want to see how a certain use case performs on different machines, we can make use of the `aggregations` field to group the data accordingly. + +[source,json] +---- +"aggregations":[ + {"column":"date","agg":"max"}, + {"column":"applications","agg":"filter:my_app"}, + {"column":"use_cases","agg":"filter:my_use_case"}, + {"column":"performance_variable","agg":"sum"} +] +---- + +The previous example will first get only the latest benchmarks (by getting the maximum date), then it will filter the application and the use case to find applications and use cases that correspond to "my_app" and "my_use_case". And finally it will compute the sum of all performance variables for the remaining rows. + +Users must provide a column and an aggregation function as a string. + +Available aggregations are: +- `mean` : Computes the mean of the column +- `mean` : Computes the sum of the column +- `max` : Computes the maximum of the column +- `min` : Computes the minimum of the column +- `filter:value`: : Filters the column by `value`. + + +[NOTE] +==== +The order of the aggregations list is important. +==== == Custom layouts +By providing the `layout_modifiers` field, users can pass custom layout options for rendering the figures. +These options correspond to the accepted layout reference for Plotly: https://plotly.com/python/reference/layout/[Plotly layout reference] +It accepts a nested dictionnary just as Plotly does. +For example, we could customize a figure to have have its x-axis on a logscale. +[source,json] +---- +"layout_modifiers":{ + "xaxis":{ + "type":"log" + } +} +---- + + +++++ + +++++ \ No newline at end of file From b887b34199b242a52881def69d6afcd0dbfb4b5d Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:28:16 +0100 Subject: [PATCH 43/52] add link to params #90 --- .../modules/tutorial/pages/configurationfiles/magicstrings.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc b/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc index f024c4e0..c7fba6ed 100644 --- a/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc +++ b/docs/modules/tutorial/pages/configurationfiles/magicstrings.adoc @@ -27,7 +27,7 @@ For replacing a value coming from the machine configuration, simply prepend any The framework is equiped with the following reserved keywords for placeholders: - `{{instance}}` : Returns the hashcode of the current ReFrame test. -- `{{.value}}`: The value keyword must be appended to a parameter name (e.g. `{{parameters.my_param.value}}`). It fetches the current value of a given runtime variable (such as a parameter). More information on [Parameters TODO link] +- `{{.value}}`: The value keyword must be appended to a parameter name (e.g. `{{parameters.my_param.value}}`). It fetches the current value of a given runtime variable (such as a parameter). More information on the xref:tutorial:configurationfiles/benchmark.adoc#_parameters[Parameters] section. == Nested placeholders From 8041dda845b879305f078f67bb93336a09ac0417 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:48:25 +0100 Subject: [PATCH 44/52] rm some sections #90 --- docs/modules/tutorial/pages/index.adoc | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index ffe38323..6fb910c0 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -2,24 +2,4 @@ The _Feel++ benchmarking_ project provides a framework for automating, centralizing and organizing performance evaluation of scientific simulations on HPC systems. This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. -It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. - - - - -== How it works - - - - -== Benchmarking Workflow - -== Interpreting Benchmarks - -== CI/CD and Automation - -== Versioning - -== Advanced usage - -== Examples \ No newline at end of file +It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. \ No newline at end of file From 7a961c2ba38a49af875946612a43ee53b04fc10f Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:48:31 +0100 Subject: [PATCH 45/52] add script doc #90 --- .../tutorial/pages/gettingstarted.adoc | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/modules/tutorial/pages/gettingstarted.adoc b/docs/modules/tutorial/pages/gettingstarted.adoc index 0b5e21e4..61e1b763 100644 --- a/docs/modules/tutorial/pages/gettingstarted.adoc +++ b/docs/modules/tutorial/pages/gettingstarted.adoc @@ -64,4 +64,31 @@ The `--website` option will start an http-server on localhost, so the website ca == Executing a benchmark -== Rendering reports \ No newline at end of file +In order to execute a benchmark, you can make use of the `execute-benchmark` command after all configuration files have been set ( xref:tutorial:configuration.adoc[Configuration Reference]). + +The script accepts the following options : +- `--machine-config` (`-mc`) : The path to the machine configuration JSON file +- `--benchmark-config` (`-bc`) : The path to the benchmark configuration JSON file +- `--plots-config` (`-pc`) : The path to the plots configuration JSON file. If not provided, it will be assumed that the plots section is included in the benchmark config. Otherwise, no plots will be considered. +- `--dir` (`-d`) : [Optional] Directory path where benchmark configuration files can be found. If provided, the application will consider all benchmark configuration files inside the provided directory. +- `--exclude` (`-e`) : [Optional] To use in combination with `--dir`, mentioned files will not be launched. Only provide basenames to exclude. +- `--move-results` (`-mv`) : [Optional] Directory to move the resulting files to. If not provided, result files will be located under the directory specified by the machine configuration. +- `--list-files` (`-lf`) : [Optional] List all benchmarking configuration file found. If this option is provided, the application will not run. Use it for validation. +- `--verbose` (`-v`) : [Optional] Select Reframe\'s verbose level by specifying multiple v\'s. +- `--website` (`-w`) : [Optional] Render reports, compile them, create the website and start an http server. +- `--help` (`-h`) : Display help and quit program + +When a benchmark is done, a `website_config.json` file will be created (or updated) with the current filepaths of the reports and plots generated by the framework. If the `--website` flag is active, the `render-benchmarks` command will be launched with this file as argument. + +== Rendering reports + +To render reports, a webiste configuration file is needed. An example is provided under _src/benchmarking/reports/config/config.json_. This file indicates how the website views should be structured, and it indicates the hierarchy of the benchmarks. + +A file of the same type is generated after a benchmark is launched, called _website_config.json_, and it is found at the root of the _reports_ directory specified under the `reports_base_dir` field of machine configuration file ( xref:tutorial:configfiles/machine.adoc). + +Once this file is located, users can run the `render-benchmarks` command to render existing reports. + +The script takes the following arguments: +- `config_file` : The path of the website configuration file. +- `json_output_path`: [Optional] Path of the directory to download the reports to. Only relevant if the configuration file contains remote locations (only Girder is supported at the moment). +- `modules_path`: [Optional] Path to the Antora module to render the reports to. It defaults to _docs/modules/ROOT/pages_. Multiple directories will be recursively created under the provided path. \ No newline at end of file From e71f24906b1d38ec5be2b61052023603b9d95025 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:53:39 +0100 Subject: [PATCH 46/52] fix lists #90 --- docs/modules/tutorial/pages/gettingstarted.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/modules/tutorial/pages/gettingstarted.adoc b/docs/modules/tutorial/pages/gettingstarted.adoc index 61e1b763..e5230d72 100644 --- a/docs/modules/tutorial/pages/gettingstarted.adoc +++ b/docs/modules/tutorial/pages/gettingstarted.adoc @@ -67,6 +67,7 @@ The `--website` option will start an http-server on localhost, so the website ca In order to execute a benchmark, you can make use of the `execute-benchmark` command after all configuration files have been set ( xref:tutorial:configuration.adoc[Configuration Reference]). The script accepts the following options : + - `--machine-config` (`-mc`) : The path to the machine configuration JSON file - `--benchmark-config` (`-bc`) : The path to the benchmark configuration JSON file - `--plots-config` (`-pc`) : The path to the plots configuration JSON file. If not provided, it will be assumed that the plots section is included in the benchmark config. Otherwise, no plots will be considered. @@ -89,6 +90,7 @@ A file of the same type is generated after a benchmark is launched, called _webs Once this file is located, users can run the `render-benchmarks` command to render existing reports. The script takes the following arguments: + - `config_file` : The path of the website configuration file. - `json_output_path`: [Optional] Path of the directory to download the reports to. Only relevant if the configuration file contains remote locations (only Girder is supported at the moment). - `modules_path`: [Optional] Path to the Antora module to render the reports to. It defaults to _docs/modules/ROOT/pages_. Multiple directories will be recursively created under the provided path. \ No newline at end of file From 64c7aaef0028fccc15e74be099f48953188144e2 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 11:55:53 +0100 Subject: [PATCH 47/52] fix figures display #90 --- docs/modules/tutorial/pages/configuration.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/modules/tutorial/pages/configuration.adoc b/docs/modules/tutorial/pages/configuration.adoc index 261e40e8..367d87c9 100644 --- a/docs/modules/tutorial/pages/configuration.adoc +++ b/docs/modules/tutorial/pages/configuration.adoc @@ -1,4 +1,6 @@ = Configuration guide +:page-plotly: true +:page-jupyter: true The core of the _Feel++ benchmarking_ framework are its configuration files. Users must provide the following configuration files: From e57df2a1f3c727e8591a5133e627e28cf52988a5 Mon Sep 17 00:00:00 2001 From: Christophe Prud'homme Date: Tue, 3 Dec 2024 12:43:46 +0100 Subject: [PATCH 48/52] Update index.adoc --- docs/modules/tutorial/pages/index.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/modules/tutorial/pages/index.adoc b/docs/modules/tutorial/pages/index.adoc index 6fb910c0..534ec5c0 100644 --- a/docs/modules/tutorial/pages/index.adoc +++ b/docs/modules/tutorial/pages/index.adoc @@ -1,5 +1,5 @@ -= feelpp.benchmarkign project += feelpp.benchmarking project -The _Feel++ benchmarking_ project provides a framework for automating, centralizing and organizing performance evaluation of scientific simulations on HPC systems. +The {feelpp} benchmarking_ project provides a framework for automating, centralizing and organizing performance evaluation of scientific simulations on HPC systems. This project, based on the https://reframe-hpc.readthedocs.io/en/stable/index.html[ReFrame-hpc framework], enables highly customized benchmarking using robust and comprehensive JSON configuration files that parametrize tests, validate executions and generate figures. -It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. \ No newline at end of file +It also provides concrete CI/CD/CB pipelines to fully automate the benchmarking step of any application. From c7d7ee4660d40c6109416ebb1ebc42549ca1d670 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 13:54:04 +0100 Subject: [PATCH 49/52] int -> size_t --- tests/data/parallelSum.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/parallelSum.cpp b/tests/data/parallelSum.cpp index 983d838c..e4895a6e 100644 --- a/tests/data/parallelSum.cpp +++ b/tests/data/parallelSum.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) double start_time = MPI_Wtime(); double local_sum = 0; - for (int i = 0; i < local_array.size(); ++i) + for (size_t i = 0; i < local_array.size(); ++i) local_sum += local_array[i]; double end_time = MPI_Wtime(); From 0492b8d283ea9fc037a4485c1080b6e918586a49 Mon Sep 17 00:00:00 2001 From: Javier Cladellas Date: Tue, 3 Dec 2024 16:17:53 +0100 Subject: [PATCH 50/52] readibility --- config/machines/local.json | 9 +-------- config/tests_parallelSum/parallelSum.json | 18 +++++++++--------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/config/machines/local.json b/config/machines/local.json index 54a70b56..80b60fde 100644 --- a/config/machines/local.json +++ b/config/machines/local.json @@ -1,16 +1,9 @@ { "machine": "local", - "targets":[":builtin:"], + "targets":["default:builtin:default"], "execution_policy": "async", "reframe_base_dir":"$HOME/Documents/Repos/benchmarking/build/reframe", "reports_base_dir":"$HOME/Documents/Repos/benchmarking/reports/", "input_dataset_base_dir":"$HOME/Documents/Repos/benchmarking/", "output_app_dir":"$HOME/Documents/Repos/benchmarking" - // "containers":{ - // "apptainer":{ - // "cachedir": "/home/u2/cladellash/.apptainer/cache", - // "tmpdir": "/data/scratch/cladellash/images/tmp", - // "image_base_dir":"/data/scratch/cladellash/images" - // } - // } } \ No newline at end of file diff --git a/config/tests_parallelSum/parallelSum.json b/config/tests_parallelSum/parallelSum.json index 7c248a8a..57c0dcbb 100644 --- a/config/tests_parallelSum/parallelSum.json +++ b/config/tests_parallelSum/parallelSum.json @@ -1,20 +1,13 @@ { "executable": "{{machine.input_dataset_base_dir}}/tests/data/parallelSum", - "output_directory": "{{machine.output_app_dir}}/tests/data/outputs/parallelSum", "use_case_name": "parallel_sum", "timeout":"0-0:5:0", + "output_directory": "{{machine.output_app_dir}}/tests/data/outputs/parallelSum", //Application options "options": [ "{{parameters.elements.value}}", "{{output_directory}}/{{instance}}" ], - // Files containing app outputs - "outputs": [ - { - "filepath":"{{output_directory}}/{{instance}}/outputs.csv", - "format":"csv" - } - ], //Files containing execution times "scalability": { "directory": "{{output_directory}}/{{instance}}/", @@ -27,7 +20,14 @@ } ] }, - // Only stdout supported at the moment + // Files containing app outputs + "outputs": [ + { + "filepath":"{{output_directory}}/{{instance}}/outputs.csv", + "format":"csv" + } + ], + // Test validation (Only stdout supported at the moment) "sanity": { "success": ["[SUCCESS]"], "error": ["[OOPSIE]","Error"] From dd841d48add5731440a2b8bfb669d1b7e60994eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 00:38:36 +0000 Subject: [PATCH 51/52] Bump @antora/site-generator-default from 3.1.9 to 3.1.10 Bumps [@antora/site-generator-default](https://gitlab.com/antora/antora) from 3.1.9 to 3.1.10. - [Changelog](https://gitlab.com/antora/antora/blob/main/CHANGELOG.adoc) - [Commits](https://gitlab.com/antora/antora/compare/v3.1.9...v3.1.10) --- updated-dependencies: - dependency-name: "@antora/site-generator-default" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 1058 ++++++++++++++++++++++++++++++--------------- package.json | 2 +- 2 files changed, 700 insertions(+), 360 deletions(-) diff --git a/package-lock.json b/package-lock.json index 992c78d1..b33521c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@antora/cli": "~3.1.9", "@antora/collector-extension": "^1.0.0", "@antora/site-generator": "~3.1.9", - "@antora/site-generator-default": "~3.1.9", + "@antora/site-generator-default": "~3.1.10", "@asciidoctor/core": "~2.2.8", "@feelpp/asciidoctor-extensions": "1.0.0-rc.11", "asciidoctor": "~2.2.8", @@ -28,18 +28,51 @@ } }, "node_modules/@antora/asciidoc-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", - "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.10.tgz", + "integrity": "sha512-np0JkOV37CK7V4eDZUZXf4fQuCKYW3Alxl8FlyzBevXi2Ujv29O82JLbHbv1cyTsvGkGNNB+gzJIx9XBsQ7+Nw==", "dependencies": { - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "@asciidoctor/core": "~2.2" }, "engines": { "node": ">=16.0.0" } }, + "node_modules/@antora/asciidoc-loader/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/asciidoc-loader/node_modules/@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/asciidoc-loader/node_modules/@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "dependencies": { + "@antora/expand-path-helper": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/cli": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", @@ -73,13 +106,13 @@ } }, "node_modules/@antora/content-aggregator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.9.tgz", - "integrity": "sha512-g+UzevPSm5c4R0j1U9uysJfdIUfp++QOHIEBmqjhfx/aIEnOL70zA+WF55Mm+syAfzU3877puI27sOp8qtPglw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.10.tgz", + "integrity": "sha512-OT6ZcCA7LrtNfrAZUr3hFh+Z/1isKpsfnqFjCDC66NEMqIyzJO99jq0CM66rYlYhyX7mb5BwEua8lHcwpOXNow==", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -97,6 +130,39 @@ "node": ">=16.0.0" } }, + "node_modules/@antora/content-aggregator/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-aggregator/node_modules/@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-aggregator/node_modules/@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "dependencies": { + "@antora/expand-path-helper": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/content-aggregator/node_modules/picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", @@ -109,12 +175,12 @@ } }, "node_modules/@antora/content-classifier": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", - "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.10.tgz", + "integrity": "sha512-3JJl4IIiTX00v/MirK603NoqIcHjGYAaRWt3Q4U03tI1Fv2Aho/ypO3FE45069jFf0Dx2uDJfp5kapb9gaIjdQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/logger": "3.1.9", + "@antora/asciidoc-loader": "3.1.10", + "@antora/logger": "3.1.10", "mime-types": "~2.1", "vinyl": "~3.0" }, @@ -122,12 +188,34 @@ "node": ">=16.0.0" } }, + "node_modules/@antora/content-classifier/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-classifier/node_modules/@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/document-converter": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", - "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.10.tgz", + "integrity": "sha512-qi9ctgcKal8tZtWflVo66w+4zCJoBmUKRV+eA9aRRR09KDdU9r514vu1adWNgniPppISr90zD13V5l2JUy/2CQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" }, "engines": { "node": ">=16.0.0" @@ -142,12 +230,12 @@ } }, "node_modules/@antora/file-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", - "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.10.tgz", + "integrity": "sha512-DPR/0d1P+kr3qV4T0Gh81POEO/aCmNWIp/oLUYAhr0HHOcFzgpTUUoLStgcYynZPFRIB7EYKSab+oYSCK17DGA==", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/user-require-helper": "~3.0", "vinyl": "~3.0", "yazl": "~2.5" }, @@ -155,6 +243,25 @@ "node": ">=16.0.0" } }, + "node_modules/@antora/file-publisher/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/file-publisher/node_modules/@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "dependencies": { + "@antora/expand-path-helper": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/logger": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.9.tgz", @@ -169,125 +276,47 @@ "node": ">=16.0.0" } }, - "node_modules/@antora/logger/node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" - }, - "node_modules/@antora/logger/node_modules/pino": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", - "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/@antora/logger/node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/@antora/logger/node_modules/pino-pretty": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", - "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "node_modules/@antora/navigation-builder": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.10.tgz", + "integrity": "sha512-aLMK49nYsSB3mEZbLkmUXDAUYmscv2AFWu+5c3eqVGkQ6Wgyd79WQ6Bz3/TN9YqkzGL+PqGs0G39F0VQzD23Hw==", "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" + "@antora/asciidoc-loader": "3.1.10" }, - "bin": { - "pino-pretty": "bin.js" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@antora/logger/node_modules/pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" - }, - "node_modules/@antora/logger/node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" - }, - "node_modules/@antora/logger/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "node_modules/@antora/page-composer": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.10.tgz", + "integrity": "sha512-JoEg8J8HVsnPmAgUrYSGzf0C8rQefXyCi/18ucy0utyfUvlJNsZvUbGUPx62Het9p0JP0FkAz2MTLyDlNdArVg==", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "@antora/logger": "3.1.10", + "handlebars": "~4.7", + "require-from-string": "~2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@antora/logger/node_modules/sonic-boom": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", - "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/@antora/logger/node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "dependencies": { - "real-require": "^0.2.0" + "node": ">=16.0.0" } }, - "node_modules/@antora/navigation-builder": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", - "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", - "dependencies": { - "@antora/asciidoc-loader": "3.1.9" - }, + "node_modules/@antora/page-composer/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", "engines": { "node": ">=16.0.0" } }, - "node_modules/@antora/page-composer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.9.tgz", - "integrity": "sha512-X6Qj+J5dfFAGXoCAOaA+R6xRp8UoNMDHsRsB1dUTT2QNzk1Lrq6YkYyljdD2cxkWjLVqQ/pQSP+BJVNFGbqDAQ==", + "node_modules/@antora/page-composer/node_modules/@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", "dependencies": { - "@antora/logger": "3.1.9", - "handlebars": "~4.7", - "require-from-string": "~2.0" + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" }, "engines": { "node": ">=16.0.0" @@ -308,9 +337,9 @@ } }, "node_modules/@antora/redirect-producer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", - "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.10.tgz", + "integrity": "sha512-IbWJGh6LmsxJQ821h0B9JfooofFZBgFLZxsbp/IoTLkBFGLFAY5tDRvB6rvubfNLRoSjM8VjEUXGqVLlwZOb+g==", "dependencies": { "vinyl": "~3.0" }, @@ -327,46 +356,93 @@ } }, "node_modules/@antora/site-generator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", - "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", - "dependencies": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/content-aggregator": "3.1.9", - "@antora/content-classifier": "3.1.9", - "@antora/document-converter": "3.1.9", - "@antora/file-publisher": "3.1.9", - "@antora/logger": "3.1.9", - "@antora/navigation-builder": "3.1.9", - "@antora/page-composer": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/redirect-producer": "3.1.9", - "@antora/site-mapper": "3.1.9", - "@antora/site-publisher": "3.1.9", - "@antora/ui-loader": "3.1.9", - "@antora/user-require-helper": "~2.0" + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.10.tgz", + "integrity": "sha512-NCULYtwUjIyr5FGCymhfG/zDVUmZ6pfmCPorka8mAzo4/GDx1T7bgaRL9rEIyf2AMqcm7apQiAz03mpU4kucsw==", + "dependencies": { + "@antora/asciidoc-loader": "3.1.10", + "@antora/content-aggregator": "3.1.10", + "@antora/content-classifier": "3.1.10", + "@antora/document-converter": "3.1.10", + "@antora/file-publisher": "3.1.10", + "@antora/logger": "3.1.10", + "@antora/navigation-builder": "3.1.10", + "@antora/page-composer": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/redirect-producer": "3.1.10", + "@antora/site-mapper": "3.1.10", + "@antora/site-publisher": "3.1.10", + "@antora/ui-loader": "3.1.10", + "@antora/user-require-helper": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-generator-default": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.9.tgz", - "integrity": "sha512-m/QCv2o/24VmWZaeqtc6nNEky///GTLLx/pyyihP7uWKvZ0AhGPp6Agv1yaShjKIthBzHJ3JozaMPev2leor+A==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.10.tgz", + "integrity": "sha512-dMhjbklthysj3espwYNkTkADm2Z3EbWThq9gJv/ZuSXGZSXVSwt8b3mBpCTwxOeAKIldnj3fc1pzQxei/7PC2w==", + "dependencies": { + "@antora/site-generator": "3.1.10" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator/node_modules/@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator/node_modules/@antora/playbook-builder": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.10.tgz", + "integrity": "sha512-UB8UmRYfkKgActTUlotdVS4FKGjaZgTnSXE7Fns1xb3/3HRanWvI+Yze1OmCkGC33cTpoQFnSYp7ySEH8LaiBw==", + "dependencies": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator/node_modules/@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", "dependencies": { - "@antora/site-generator": "3.1.9" + "@antora/expand-path-helper": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-mapper": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", - "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.10.tgz", + "integrity": "sha512-KY1j/y0uxC2Y7RAo4r4yKv9cgFm8aZoRylZXEODJnwj3tffbZ2ZdRzSWHp6fN0QX/Algrr9JNd9CWrjcj2f3Zw==", "dependencies": { - "@antora/content-classifier": "3.1.9", + "@antora/content-classifier": "3.1.10", "vinyl": "~3.0" }, "engines": { @@ -374,22 +450,22 @@ } }, "node_modules/@antora/site-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", - "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.10.tgz", + "integrity": "sha512-G4xcUWvgth8oeEQwiu9U1cE0miQtYHwKHOobUbDBt2Y6LlC5H31zQQmAyvMwTsGRlvYRgLVtG6j9d6JBwQ6w9Q==", "dependencies": { - "@antora/file-publisher": "3.1.9" + "@antora/file-publisher": "3.1.10" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/ui-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", - "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.10.tgz", + "integrity": "sha512-H1f5wI5a5HjLuE/Wexvc8NZy8w83Bhqjka7t1DbwOOqP+LyxFGLx/QbBVKdTtgFNDHVMtNBlplQq0ixeoTSh0A==", "dependencies": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -405,6 +481,14 @@ "node": ">=16.0.0" } }, + "node_modules/@antora/ui-loader/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/ui-loader/node_modules/picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", @@ -663,11 +747,6 @@ "node": ">=8.0.0" } }, - "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1516,6 +1595,11 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "node_modules/hpagent": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", @@ -2282,14 +2366,103 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pino": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "node_modules/portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -2333,6 +2506,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -2671,6 +2849,14 @@ "simple-concat": "^1.0.0" } }, + "node_modules/sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2725,9 +2911,9 @@ } }, "node_modules/streamx": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", - "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.0.tgz", + "integrity": "sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==", "dependencies": { "fast-fifo": "^1.3.2", "queue-tick": "^1.0.1", @@ -2818,11 +3004,16 @@ } }, "node_modules/text-decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", - "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz", + "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==" + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", "dependencies": { - "b4a": "^1.6.4" + "real-require": "^0.2.0" } }, "node_modules/through": { @@ -3310,13 +3501,39 @@ }, "dependencies": { "@antora/asciidoc-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", - "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.10.tgz", + "integrity": "sha512-np0JkOV37CK7V4eDZUZXf4fQuCKYW3Alxl8FlyzBevXi2Ujv29O82JLbHbv1cyTsvGkGNNB+gzJIx9XBsQ7+Nw==", "requires": { - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "@asciidoctor/core": "~2.2" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "requires": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + } + }, + "@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "requires": { + "@antora/expand-path-helper": "~3.0" + } + } } }, "@antora/cli": { @@ -3343,13 +3560,13 @@ } }, "@antora/content-aggregator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.9.tgz", - "integrity": "sha512-g+UzevPSm5c4R0j1U9uysJfdIUfp++QOHIEBmqjhfx/aIEnOL70zA+WF55Mm+syAfzU3877puI27sOp8qtPglw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.10.tgz", + "integrity": "sha512-OT6ZcCA7LrtNfrAZUr3hFh+Z/1isKpsfnqFjCDC66NEMqIyzJO99jq0CM66rYlYhyX7mb5BwEua8lHcwpOXNow==", "requires": { - "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -3364,6 +3581,30 @@ "vinyl": "~3.0" }, "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "requires": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + } + }, + "@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "requires": { + "@antora/expand-path-helper": "~3.0" + } + }, "picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", @@ -3372,22 +3613,40 @@ } }, "@antora/content-classifier": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", - "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.10.tgz", + "integrity": "sha512-3JJl4IIiTX00v/MirK603NoqIcHjGYAaRWt3Q4U03tI1Fv2Aho/ypO3FE45069jFf0Dx2uDJfp5kapb9gaIjdQ==", "requires": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/logger": "3.1.9", + "@antora/asciidoc-loader": "3.1.10", + "@antora/logger": "3.1.10", "mime-types": "~2.1", "vinyl": "~3.0" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "requires": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + } + } } }, "@antora/document-converter": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", - "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.10.tgz", + "integrity": "sha512-qi9ctgcKal8tZtWflVo66w+4zCJoBmUKRV+eA9aRRR09KDdU9r514vu1adWNgniPppISr90zD13V5l2JUy/2CQ==", "requires": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" } }, "@antora/expand-path-helper": { @@ -3396,14 +3655,29 @@ "integrity": "sha512-CSMBGC+tI21VS2kGW3PV7T2kQTM5eT3f2GTPVLttwaNYbNxDve08en/huzszHJfxo11CcEs26Ostr0F2c1QqeA==" }, "@antora/file-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", - "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.10.tgz", + "integrity": "sha512-DPR/0d1P+kr3qV4T0Gh81POEO/aCmNWIp/oLUYAhr0HHOcFzgpTUUoLStgcYynZPFRIB7EYKSab+oYSCK17DGA==", "requires": { - "@antora/expand-path-helper": "~2.0", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/user-require-helper": "~3.0", "vinyl": "~3.0", "yazl": "~2.5" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "requires": { + "@antora/expand-path-helper": "~3.0" + } + } } }, "@antora/logger": { @@ -3415,117 +3689,42 @@ "pino": "~9.2", "pino-pretty": "~11.2", "sonic-boom": "~4.0" - }, - "dependencies": { - "help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" - }, - "pino": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", - "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", - "requires": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - } - }, - "pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "requires": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "pino-pretty": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", - "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", - "requires": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" - } - }, - "pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" - }, - "process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - }, - "sonic-boom": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", - "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", - "requires": { - "atomic-sleep": "^1.0.0" - } - }, - "thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "requires": { - "real-require": "^0.2.0" - } - } } }, "@antora/navigation-builder": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", - "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.10.tgz", + "integrity": "sha512-aLMK49nYsSB3mEZbLkmUXDAUYmscv2AFWu+5c3eqVGkQ6Wgyd79WQ6Bz3/TN9YqkzGL+PqGs0G39F0VQzD23Hw==", "requires": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" } }, "@antora/page-composer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.9.tgz", - "integrity": "sha512-X6Qj+J5dfFAGXoCAOaA+R6xRp8UoNMDHsRsB1dUTT2QNzk1Lrq6YkYyljdD2cxkWjLVqQ/pQSP+BJVNFGbqDAQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.10.tgz", + "integrity": "sha512-JoEg8J8HVsnPmAgUrYSGzf0C8rQefXyCi/18ucy0utyfUvlJNsZvUbGUPx62Het9p0JP0FkAz2MTLyDlNdArVg==", "requires": { - "@antora/logger": "3.1.9", + "@antora/logger": "3.1.10", "handlebars": "~4.7", "require-from-string": "~2.0" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "requires": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + } + } } }, "@antora/playbook-builder": { @@ -3540,9 +3739,9 @@ } }, "@antora/redirect-producer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", - "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.10.tgz", + "integrity": "sha512-IbWJGh6LmsxJQ821h0B9JfooofFZBgFLZxsbp/IoTLkBFGLFAY5tDRvB6rvubfNLRoSjM8VjEUXGqVLlwZOb+g==", "requires": { "vinyl": "~3.0" } @@ -3553,57 +3752,94 @@ "integrity": "sha512-zMSrr28jbuAabcjM5YKZgQshv16TceAhe+F4xY0b+hsF+Nh4JgtJf7dPHfT6EDxwIyO3UAP0yjCv61JM1yohIw==" }, "@antora/site-generator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", - "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.10.tgz", + "integrity": "sha512-NCULYtwUjIyr5FGCymhfG/zDVUmZ6pfmCPorka8mAzo4/GDx1T7bgaRL9rEIyf2AMqcm7apQiAz03mpU4kucsw==", "requires": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/content-aggregator": "3.1.9", - "@antora/content-classifier": "3.1.9", - "@antora/document-converter": "3.1.9", - "@antora/file-publisher": "3.1.9", - "@antora/logger": "3.1.9", - "@antora/navigation-builder": "3.1.9", - "@antora/page-composer": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/redirect-producer": "3.1.9", - "@antora/site-mapper": "3.1.9", - "@antora/site-publisher": "3.1.9", - "@antora/ui-loader": "3.1.9", - "@antora/user-require-helper": "~2.0" + "@antora/asciidoc-loader": "3.1.10", + "@antora/content-aggregator": "3.1.10", + "@antora/content-classifier": "3.1.10", + "@antora/document-converter": "3.1.10", + "@antora/file-publisher": "3.1.10", + "@antora/logger": "3.1.10", + "@antora/navigation-builder": "3.1.10", + "@antora/page-composer": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/redirect-producer": "3.1.10", + "@antora/site-mapper": "3.1.10", + "@antora/site-publisher": "3.1.10", + "@antora/ui-loader": "3.1.10", + "@antora/user-require-helper": "~3.0" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "requires": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + } + }, + "@antora/playbook-builder": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.10.tgz", + "integrity": "sha512-UB8UmRYfkKgActTUlotdVS4FKGjaZgTnSXE7Fns1xb3/3HRanWvI+Yze1OmCkGC33cTpoQFnSYp7ySEH8LaiBw==", + "requires": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + } + }, + "@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "requires": { + "@antora/expand-path-helper": "~3.0" + } + } } }, "@antora/site-generator-default": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.9.tgz", - "integrity": "sha512-m/QCv2o/24VmWZaeqtc6nNEky///GTLLx/pyyihP7uWKvZ0AhGPp6Agv1yaShjKIthBzHJ3JozaMPev2leor+A==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.10.tgz", + "integrity": "sha512-dMhjbklthysj3espwYNkTkADm2Z3EbWThq9gJv/ZuSXGZSXVSwt8b3mBpCTwxOeAKIldnj3fc1pzQxei/7PC2w==", "requires": { - "@antora/site-generator": "3.1.9" + "@antora/site-generator": "3.1.10" } }, "@antora/site-mapper": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", - "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.10.tgz", + "integrity": "sha512-KY1j/y0uxC2Y7RAo4r4yKv9cgFm8aZoRylZXEODJnwj3tffbZ2ZdRzSWHp6fN0QX/Algrr9JNd9CWrjcj2f3Zw==", "requires": { - "@antora/content-classifier": "3.1.9", + "@antora/content-classifier": "3.1.10", "vinyl": "~3.0" } }, "@antora/site-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", - "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.10.tgz", + "integrity": "sha512-G4xcUWvgth8oeEQwiu9U1cE0miQtYHwKHOobUbDBt2Y6LlC5H31zQQmAyvMwTsGRlvYRgLVtG6j9d6JBwQ6w9Q==", "requires": { - "@antora/file-publisher": "3.1.9" + "@antora/file-publisher": "3.1.10" } }, "@antora/ui-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", - "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.10.tgz", + "integrity": "sha512-H1f5wI5a5HjLuE/Wexvc8NZy8w83Bhqjka7t1DbwOOqP+LyxFGLx/QbBVKdTtgFNDHVMtNBlplQq0ixeoTSh0A==", "requires": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -3616,6 +3852,11 @@ "yauzl": "~3.1" }, "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, "picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", @@ -3795,11 +4036,6 @@ "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" }, - "b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4467,6 +4703,11 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "hpagent": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", @@ -5023,6 +5264,87 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, + "pino": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", + "requires": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + } + }, + "pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "requires": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } + } + }, + "pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "requires": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } + } + }, + "pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -5062,6 +5384,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5284,6 +5611,14 @@ "simple-concat": "^1.0.0" } }, + "sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "requires": { + "atomic-sleep": "^1.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5329,9 +5664,9 @@ } }, "streamx": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", - "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.0.tgz", + "integrity": "sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==", "requires": { "bare-events": "^2.2.0", "fast-fifo": "^1.3.2", @@ -5401,11 +5736,16 @@ } }, "text-decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", - "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz", + "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==" + }, + "thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", "requires": { - "b4a": "^1.6.4" + "real-require": "^0.2.0" } }, "through": { diff --git a/package.json b/package.json index bc683217..5e3e66a4 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@antora/cli": "~3.1.9", "@antora/collector-extension": "^1.0.0", "@antora/site-generator": "~3.1.9", - "@antora/site-generator-default": "~3.1.9", + "@antora/site-generator-default": "~3.1.10", "@asciidoctor/core": "~2.2.8", "asciidoctor": "~2.2.8", "asciidoctor-jupyter": "^0.7.0", From 12d78a5fb625dd7bef3d16f47c6b13c745e69f15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:38:00 +0000 Subject: [PATCH 52/52] Bump @antora/cli from 3.1.9 to 3.1.10 Bumps [@antora/cli](https://gitlab.com/antora/antora) from 3.1.9 to 3.1.10. - [Changelog](https://gitlab.com/antora/antora/blob/main/CHANGELOG.adoc) - [Commits](https://gitlab.com/antora/antora/compare/v3.1.9...v3.1.10) --- updated-dependencies: - dependency-name: "@antora/cli" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 525 ++++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 320 insertions(+), 207 deletions(-) diff --git a/package-lock.json b/package-lock.json index 960e3066..195d47e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.1.0", "license": "AGPL-3.0", "dependencies": { - "@antora/cli": "~3.1.9", + "@antora/cli": "~3.1.10", "@antora/collector-extension": "^1.0.1", "@antora/site-generator": "~3.1.9", "@antora/site-generator-default": "~3.1.9", @@ -41,13 +41,13 @@ } }, "node_modules/@antora/cli": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", - "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.10.tgz", + "integrity": "sha512-gp8u9aVM0w1DtWSsB5PwvEfFYKrooPENLhN58RAfdgTrcsTsWw+CDysFZPgEaHB0Y1ZbanR82ZH/f6JVKGcZfQ==", "dependencies": { - "@antora/logger": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/user-require-helper": "~3.0", "commander": "~11.1" }, "bin": { @@ -57,6 +57,53 @@ "node": ">=16.0.0" } }, + "node_modules/@antora/cli/node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/cli/node_modules/@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/cli/node_modules/@antora/playbook-builder": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.10.tgz", + "integrity": "sha512-UB8UmRYfkKgActTUlotdVS4FKGjaZgTnSXE7Fns1xb3/3HRanWvI+Yze1OmCkGC33cTpoQFnSYp7ySEH8LaiBw==", + "dependencies": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/cli/node_modules/@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "dependencies": { + "@antora/expand-path-helper": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/collector-extension": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@antora/collector-extension/-/collector-extension-1.0.1.tgz", @@ -177,106 +224,6 @@ "node": ">=16.0.0" } }, - "node_modules/@antora/logger/node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" - }, - "node_modules/@antora/logger/node_modules/pino": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", - "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/@antora/logger/node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/@antora/logger/node_modules/pino-pretty": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", - "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/@antora/logger/node_modules/pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" - }, - "node_modules/@antora/logger/node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" - }, - "node_modules/@antora/logger/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@antora/logger/node_modules/sonic-boom": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", - "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/@antora/logger/node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "dependencies": { - "real-require": "^0.2.0" - } - }, "node_modules/@antora/navigation-builder": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", @@ -1524,6 +1471,11 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "node_modules/hpagent": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", @@ -2298,6 +2250,95 @@ "node": ">=6" } }, + "node_modules/pino": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "node_modules/portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -2341,6 +2382,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -2679,6 +2725,14 @@ "simple-concat": "^1.0.0" } }, + "node_modules/sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2833,6 +2887,14 @@ "b4a": "^1.6.4" } }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -3328,14 +3390,51 @@ } }, "@antora/cli": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", - "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.10.tgz", + "integrity": "sha512-gp8u9aVM0w1DtWSsB5PwvEfFYKrooPENLhN58RAfdgTrcsTsWw+CDysFZPgEaHB0Y1ZbanR82ZH/f6JVKGcZfQ==", "requires": { - "@antora/logger": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/user-require-helper": "~3.0", "commander": "~11.1" + }, + "dependencies": { + "@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" + }, + "@antora/logger": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", + "requires": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + } + }, + "@antora/playbook-builder": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.10.tgz", + "integrity": "sha512-UB8UmRYfkKgActTUlotdVS4FKGjaZgTnSXE7Fns1xb3/3HRanWvI+Yze1OmCkGC33cTpoQFnSYp7ySEH8LaiBw==", + "requires": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + } + }, + "@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "requires": { + "@antora/expand-path-helper": "~3.0" + } + } } }, "@antora/collector-extension": { @@ -3430,99 +3529,6 @@ "pino": "~9.2", "pino-pretty": "~11.2", "sonic-boom": "~4.0" - }, - "dependencies": { - "help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" - }, - "pino": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", - "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", - "requires": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - } - }, - "pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "requires": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "pino-pretty": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", - "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", - "requires": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" - } - }, - "pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" - }, - "process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" - }, - "readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - }, - "sonic-boom": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", - "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", - "requires": { - "atomic-sleep": "^1.0.0" - } - }, - "thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "requires": { - "real-require": "^0.2.0" - } - } } }, "@antora/navigation-builder": { @@ -4482,6 +4488,11 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "hpagent": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", @@ -5038,6 +5049,87 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, + "pino": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", + "requires": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + } + }, + "pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "requires": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } + } + }, + "pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "requires": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } + } + }, + "pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -5077,6 +5169,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5299,6 +5396,14 @@ "simple-concat": "^1.0.0" } }, + "sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "requires": { + "atomic-sleep": "^1.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5423,6 +5528,14 @@ "b4a": "^1.6.4" } }, + "thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "requires": { + "real-require": "^0.2.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/package.json b/package.json index ad849a83..59ee458b 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "linkcheck": "broken-link-checker --filter-level 3 --recursive --verbose" }, "dependencies": { - "@antora/cli": "~3.1.9", + "@antora/cli": "~3.1.10", "@antora/collector-extension": "^1.0.1", "@antora/site-generator": "~3.1.9", "@antora/site-generator-default": "~3.1.9",