From 796076bb04bf351b16b5c37fea18bbafe183cd24 Mon Sep 17 00:00:00 2001 From: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:51:22 -0500 Subject: [PATCH] Add new Bechmark IA (#5022) * Rework Benchmark IA Signed-off-by: Naarcha-AWS * Add new Benchmark IA. Signed-off-by: Naarcha-AWS * Add Quickstart steps and Sigv4 guide. Signed-off-by: Naarcha-AWS * Add tutorial text Signed-off-by: Naarcha-AWS * Fix links Signed-off-by: Naarcha-AWS * Add technical feedback Signed-off-by: Naarcha-AWS * Apply suggestions from code review Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Apply suggestions from code review Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Chris Moore <107723039+cwillum@users.noreply.github.com> Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Chris Moore <107723039+cwillum@users.noreply.github.com> Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Remove section Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Update quickstart.md Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Nathan Bower Co-authored-by: Chris Moore <107723039+cwillum@users.noreply.github.com> Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> * Update concepts.md Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> --------- Signed-off-by: Naarcha-AWS Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Co-authored-by: Chris Moore <107723039+cwillum@users.noreply.github.com> Co-authored-by: Nathan Bower --- _benchmark/index.md | 17 +- _benchmark/quickstart.md | 401 ++++++++++++++++++ _benchmark/tutorials/index.md | 10 + _benchmark/tutorials/sigv4.md | 32 ++ _benchmark/user-guide/concepts.md | 171 ++++++++ .../{ => user-guide}/configuring-benchmark.md | 3 +- .../creating-custom-workloads.md | 3 +- _benchmark/user-guide/index.md | 10 + .../{ => user-guide}/installing-benchmark.md | 56 ++- _benchmark/workloads/index.md | 147 +------ images/benchmark/OSB-workflow.png | Bin 0 -> 54708 bytes 11 files changed, 695 insertions(+), 155 deletions(-) create mode 100644 _benchmark/quickstart.md create mode 100644 _benchmark/tutorials/index.md create mode 100644 _benchmark/tutorials/sigv4.md create mode 100644 _benchmark/user-guide/concepts.md rename _benchmark/{ => user-guide}/configuring-benchmark.md (99%) rename _benchmark/{ => user-guide}/creating-custom-workloads.md (99%) create mode 100644 _benchmark/user-guide/index.md rename _benchmark/{ => user-guide}/installing-benchmark.md (73%) create mode 100644 images/benchmark/OSB-workflow.png diff --git a/_benchmark/index.md b/_benchmark/index.md index dcfa629c5d..a0b518b77f 100644 --- a/_benchmark/index.md +++ b/_benchmark/index.md @@ -17,17 +17,18 @@ OpenSearch Benchmark is a macrobenchmark utility provided by the [OpenSearch Pro OpenSearch Benchmark can be installed directly on a compatible host running Linux and macOS. You can also run OpenSearch Benchmark in a Docker container. See [Installing OpenSearch Benchmark]({{site.url}}{{site.baseurl}}/benchmark/installing-benchmark/) for more information. -## Concepts +The following diagram visualizes how OpenSearch Benchmark works when run against a local host: -Before using OpenSearch Benchmark, familiarize yourself with the following concepts: +![Benchmark workflow]({{site.url}}{{site.baseurl}}/images/benchmark/OSB-workflow.png). -- **Workload**: The description of one or more benchmarking scenarios that use a specific document corpus from which to perform a benchmark against your cluster. The document corpus contains any indexes, data files, and operations invoked when the workflow runs. You can list the available workloads by using `opensearch-benchmark list workloads` or view any included workloads inside the [OpenSearch Benchmark Workloads repository](https://github.com/opensearch-project/opensearch-benchmark-workloads/). For information about building a custom workload, see [Creating custom workloads]({{site.url}}{{site.baseurl}}/benchmark/creating-custom-workloads/). +The OpenSearch Benchmark documentation is split into five sections: + +- [Quickstart]({{site.url}}{{site.baseurl}}/benchmark/quickstart/): Learn how to quickly run and install OpenSearch Benchmark. +- [User guide]({{site.url}}{{site.baseurl}}/benchmark/user-guide/index/): Dive deep into how OpenSearch Benchmark can help you track the performance of your cluster. +- [Tutorials]({{site.url}}{{site.baseurl}}/benchmark/tutorials/index/): Use step-by-step guides for more advanced benchmarking configurations and functionality. +- [Commands]({{site.url}}{{site.baseurl}}/benchmark/commands/index/): A detailed reference of commands and command options supported by OpenSearch. +- [Workloads]({{site.url}}{{site.baseurl}}/benchmark/workloads/index/): A detailed reference of options available for both default and custom workloads. -- **Pipeline**: A series of steps before and after a workload is run that determines benchmark results. OpenSearch Benchmark supports three pipelines: - - `from-sources`: Builds and provisions OpenSearch, runs a benchmark, and then publishes the results. - - `from-distribution`: Downloads an OpenSearch distribution, provisions it, runs a benchmark, and then publishes the results. - - `benchmark-only`: The default pipeline. Assumes an already running OpenSearch instance, runs a benchmark on that instance, and then publishes the results. -- **Test**: A single invocation of the OpenSearch Benchmark binary. diff --git a/_benchmark/quickstart.md b/_benchmark/quickstart.md new file mode 100644 index 0000000000..19b89bd07d --- /dev/null +++ b/_benchmark/quickstart.md @@ -0,0 +1,401 @@ +--- +layout: default +title: Quickstart +nav_order: 2 +--- + +# OpenSearch Benchmark quickstart + +This tutorial outlines how to quickly install OpenSearch Benchmark and run your first OpenSearch Benchmark workload. + +## Prerequisites + +To perform the Quickstart steps, you'll need to fulfill the following prerequisites: + +- A currently active OpenSearch cluster. For instructions on how to create an OpenSearch cluster, see [Creating a cluster]({{site.url}}{{site.baseurl}}//tuning-your-cluster/index/). +- Git 2.3 or greater. + +Additional prerequisites are required, depending on your installation method: + +- If you plan to install OpenSearch Benchmark with [PyPi](https://pypi.org/), install Python 3.8 or later. +- If you plan to install OpenSearch Benchmark using Docker, install Docker. + +## Installing OpenSearch Benchmark + +You can install OpenSearch Benchmark using either PyPi or Docker. + +If you plan to run OpenSearch Benchmark with a cluster using AWS Signature Version 4, see [Sigv4 support]({{site.url}}{{site.baseurl}}/benchmark/tutorials/sigv4/). + +### PyPi + +To install OpenSearch Benchmark with PyPi, enter the following `pip` command: + +```bash +pip3 install opensearch-benchmark +``` +{% include copy.html %} + +After the installation completes, verify that OpenSearch Benchmark is running by entering the following command: + +```bash +opensearch-benchmark --help +``` +{% include copy.html %} + +If successful, OpenSearch returns the following response: + +```bash +$ opensearch-benchmark --help +usage: opensearch-benchmark [-h] [--version] {execute-test,list,info,create-workload,generate,compare,download,install,start,stop} ... + + ____ _____ __ ____ __ __ + / __ \____ ___ ____ / ___/___ ____ ___________/ /_ / __ )___ ____ _____/ /_ ____ ___ ____ ______/ /__ + / / / / __ \/ _ \/ __ \\__ \/ _ \/ __ `/ ___/ ___/ __ \ / __ / _ \/ __ \/ ___/ __ \/ __ `__ \/ __ `/ ___/ //_/ +/ /_/ / /_/ / __/ / / /__/ / __/ /_/ / / / /__/ / / / / /_/ / __/ / / / /__/ / / / / / / / / /_/ / / / ,< +\____/ .___/\___/_/ /_/____/\___/\__,_/_/ \___/_/ /_/ /_____/\___/_/ /_/\___/_/ /_/_/ /_/ /_/\__,_/_/ /_/|_| + /_/ + + A benchmarking tool for OpenSearch + +optional arguments: + -h, --help show this help message and exit + --version show program's version number and exit + +subcommands: + {execute-test,list,info,create-workload,generate,compare,download,install,start,stop} + execute-test Run a benchmark + list List configuration options + info Show info about a workload + create-workload Create a Benchmark workload from existing data + generate Generate artifacts + compare Compare two test_executions + download Downloads an artifact + install Installs an OpenSearch node locally + start Starts an OpenSearch node locally + stop Stops an OpenSearch node locally + +Find out more about Benchmark at https://opensearch.org/docs +``` + +### Docker + +To pull the image from Docker Hub, run the following command: + +```bash +docker pull opensearchproject/opensearch-benchmark:latest +``` +{% include copy.html %} + +Then run the Docker image: + +```bash +docker run opensearchproject/opensearch-benchmark -h +``` +{% include copy.html %} + + +## Running your first benchmark + +You can now run your first benchmark. For your first benchmark, you'll use the [geonames](https://github.com/opensearch-project/opensearch-benchmark-workloads/tree/main/geonames) workload. + + +### Understanding workload command flags + +Benchmarks are run using the [`execute-test`]({{site.url}}{{site.baseurl}}/benchmark/commands/execute-test/) command with the following command flags: + +For additional `execute_test` command flags, see the [execute-test]({{site.url}}{{site.baseurl}}/benchmark/commands/execute-test/) reference. Some commonly used options are `--workload-params`, `--exclude-tasks`, and `--include-tasks`. +{: .tip} + +* `--pipeline=benchmark-only` : Informs OSB that users wants to provide their own OpenSearch cluster. +- `workload=geonames`: The name of workload used by OpenSearch Benchmark. +* `--target-host=""`: Indicates the target cluster or host that will be benchmarked. Enter the endpoint of your OpenSearch cluster here. +* `--client-options="basic_auth_user:'',basic_auth_password:''"`: The username and password for your OpenSearch cluster. +* `--test-mode`: Allows a user to run the workload without running it for the entire duration. When this flag is present, Benchmark runs the first thousand operations of each task in the workload. This is only meant for sanity checks---the metrics produced are meaningless. + +The `--distribution-version`, which indicates which OpenSearch version Benchmark will use when provisioning. When run, the `execute-test` command will parse the correct distribution version when it connects to the OpenSearch cluster. + +### Running the workload + +If you installed Benchmark with PyPi, customize and use the following command: + +```bash +opensearch-benchmark execute-test --pipeline=benchmark-only --workload=geonames --target-host="" --client-options="basic_auth_user:'',basic_auth_password:''" --test-mode +``` +{% include copy.html %} + +If you installed Benchmark with Docker, customize and use the following command: + +```bash +docker run opensearchproject/opensearch-benchmark execute-test --pipeline=benchmark-only --workload=geonames --target-host="" --client-options="basic_auth_user:'',basic_auth_password:''" --test-mode +``` +{% include copy.html %} + +When the `execute_test` command runs, all tasks and operations in the `geonames` workload run sequentially. + +### Understanding the results + +Benchmark returns the following response once the benchmark completes: + +```bash +----------------------------------------------------- + _______ __ _____ + / ____(_)___ ____ _/ / / ___/_________ ________ + / /_ / / __ \/ __ `/ / \__ \/ ___/ __ \/ ___/ _ \ + / __/ / / / / / /_/ / / ___/ / /__/ /_/ / / / __/ +/_/ /_/_/ /_/\__,_/_/ /____/\___/\____/_/ \___/ +------------------------------------------------------ + +| Metric | Task | Value | Unit | +|---------------------------------------------------------------:|-------------------------------:|------------:|--------:| +| Cumulative indexing time of primary shards | | 0.0359333 | min | +| Min cumulative indexing time across primary shards | | 0.00453333 | min | +| Median cumulative indexing time across primary shards | | 0.00726667 | min | +| Max cumulative indexing time across primary shards | | 0.00878333 | min | +| Cumulative indexing throttle time of primary shards | | 0 | min | +| Min cumulative indexing throttle time across primary shards | | 0 | min | +| Median cumulative indexing throttle time across primary shards | | 0 | min | +| Max cumulative indexing throttle time across primary shards | | 0 | min | +| Cumulative merge time of primary shards | | 0 | min | +| Cumulative merge count of primary shards | | 0 | | +| Min cumulative merge time across primary shards | | 0 | min | +| Median cumulative merge time across primary shards | | 0 | min | +| Max cumulative merge time across primary shards | | 0 | min | +| Cumulative merge throttle time of primary shards | | 0 | min | +| Min cumulative merge throttle time across primary shards | | 0 | min | +| Median cumulative merge throttle time across primary shards | | 0 | min | +| Max cumulative merge throttle time across primary shards | | 0 | min | +| Cumulative refresh time of primary shards | | 0.00728333 | min | +| Cumulative refresh count of primary shards | | 35 | | +| Min cumulative refresh time across primary shards | | 0.000966667 | min | +| Median cumulative refresh time across primary shards | | 0.00136667 | min | +| Max cumulative refresh time across primary shards | | 0.00236667 | min | +| Cumulative flush time of primary shards | | 0 | min | +| Cumulative flush count of primary shards | | 0 | | +| Min cumulative flush time across primary shards | | 0 | min | +| Median cumulative flush time across primary shards | | 0 | min | +| Max cumulative flush time across primary shards | | 0 | min | +| Total Young Gen GC time | | 0.01 | s | +| Total Young Gen GC count | | 1 | | +| Total Old Gen GC time | | 0 | s | +| Total Old Gen GC count | | 0 | | +| Store size | | 0.00046468 | GB | +| Translog size | | 2.56114e-07 | GB | +| Heap used for segments | | 0.113216 | MB | +| Heap used for doc values | | 0.0171394 | MB | +| Heap used for terms | | 0.0777283 | MB | +| Heap used for norms | | 0.010437 | MB | +| Heap used for points | | 0 | MB | +| Heap used for stored fields | | 0.00791168 | MB | +| Segment count | | 17 | | +| Min Throughput | index-append | 1879.5 | docs/s | +| Mean Throughput | index-append | 1879.5 | docs/s | +| Median Throughput | index-append | 1879.5 | docs/s | +| Max Throughput | index-append | 1879.5 | docs/s | +| 50th percentile latency | index-append | 505.028 | ms | +| 100th percentile latency | index-append | 597.718 | ms | +| 50th percentile service time | index-append | 505.028 | ms | +| 100th percentile service time | index-append | 597.718 | ms | +| error rate | index-append | 0 | % | +| Min Throughput | wait-until-merges-finish | 43.82 | ops/s | +| Mean Throughput | wait-until-merges-finish | 43.82 | ops/s | +| Median Throughput | wait-until-merges-finish | 43.82 | ops/s | +| Max Throughput | wait-until-merges-finish | 43.82 | ops/s | +| 100th percentile latency | wait-until-merges-finish | 22.2577 | ms | +| 100th percentile service time | wait-until-merges-finish | 22.2577 | ms | +| error rate | wait-until-merges-finish | 0 | % | +| Min Throughput | index-stats | 58.04 | ops/s | +| Mean Throughput | index-stats | 58.04 | ops/s | +| Median Throughput | index-stats | 58.04 | ops/s | +| Max Throughput | index-stats | 58.04 | ops/s | +| 100th percentile latency | index-stats | 24.891 | ms | +| 100th percentile service time | index-stats | 7.02568 | ms | +| error rate | index-stats | 0 | % | +| Min Throughput | node-stats | 51.21 | ops/s | +| Mean Throughput | node-stats | 51.21 | ops/s | +| Median Throughput | node-stats | 51.21 | ops/s | +| Max Throughput | node-stats | 51.21 | ops/s | +| 100th percentile latency | node-stats | 26.4279 | ms | +| 100th percentile service time | node-stats | 6.38569 | ms | +| error rate | node-stats | 0 | % | +| Min Throughput | default | 14.03 | ops/s | +| Mean Throughput | default | 14.03 | ops/s | +| Median Throughput | default | 14.03 | ops/s | +| Max Throughput | default | 14.03 | ops/s | +| 100th percentile latency | default | 78.9157 | ms | +| 100th percentile service time | default | 7.30501 | ms | +| error rate | default | 0 | % | +| Min Throughput | term | 59.96 | ops/s | +| Mean Throughput | term | 59.96 | ops/s | +| Median Throughput | term | 59.96 | ops/s | +| Max Throughput | term | 59.96 | ops/s | +| 100th percentile latency | term | 22.4626 | ms | +| 100th percentile service time | term | 5.38508 | ms | +| error rate | term | 0 | % | +| Min Throughput | phrase | 44.66 | ops/s | +| Mean Throughput | phrase | 44.66 | ops/s | +| Median Throughput | phrase | 44.66 | ops/s | +| Max Throughput | phrase | 44.66 | ops/s | +| 100th percentile latency | phrase | 27.4984 | ms | +| 100th percentile service time | phrase | 4.81552 | ms | +| error rate | phrase | 0 | % | +| Min Throughput | country_agg_uncached | 16.16 | ops/s | +| Mean Throughput | country_agg_uncached | 16.16 | ops/s | +| Median Throughput | country_agg_uncached | 16.16 | ops/s | +| Max Throughput | country_agg_uncached | 16.16 | ops/s | +| 100th percentile latency | country_agg_uncached | 67.5527 | ms | +| 100th percentile service time | country_agg_uncached | 5.40069 | ms | +| error rate | country_agg_uncached | 0 | % | +| Min Throughput | country_agg_cached | 49.31 | ops/s | +| Mean Throughput | country_agg_cached | 49.31 | ops/s | +| Median Throughput | country_agg_cached | 49.31 | ops/s | +| Max Throughput | country_agg_cached | 49.31 | ops/s | +| 100th percentile latency | country_agg_cached | 38.2485 | ms | +| 100th percentile service time | country_agg_cached | 17.6579 | ms | +| error rate | country_agg_cached | 0 | % | +| Min Throughput | scroll | 29.76 | pages/s | +| Mean Throughput | scroll | 29.76 | pages/s | +| Median Throughput | scroll | 29.76 | pages/s | +| Max Throughput | scroll | 29.76 | pages/s | +| 100th percentile latency | scroll | 93.1197 | ms | +| 100th percentile service time | scroll | 25.3068 | ms | +| error rate | scroll | 0 | % | +| Min Throughput | expression | 8.32 | ops/s | +| Mean Throughput | expression | 8.32 | ops/s | +| Median Throughput | expression | 8.32 | ops/s | +| Max Throughput | expression | 8.32 | ops/s | +| 100th percentile latency | expression | 127.701 | ms | +| 100th percentile service time | expression | 7.30691 | ms | +| error rate | expression | 0 | % | +| Min Throughput | painless_static | 6.2 | ops/s | +| Mean Throughput | painless_static | 6.2 | ops/s | +| Median Throughput | painless_static | 6.2 | ops/s | +| Max Throughput | painless_static | 6.2 | ops/s | +| 100th percentile latency | painless_static | 167.239 | ms | +| 100th percentile service time | painless_static | 5.76951 | ms | +| error rate | painless_static | 0 | % | +| Min Throughput | painless_dynamic | 19.56 | ops/s | +| Mean Throughput | painless_dynamic | 19.56 | ops/s | +| Median Throughput | painless_dynamic | 19.56 | ops/s | +| Max Throughput | painless_dynamic | 19.56 | ops/s | +| 100th percentile latency | painless_dynamic | 56.9046 | ms | +| 100th percentile service time | painless_dynamic | 5.50498 | ms | +| error rate | painless_dynamic | 0 | % | +| Min Throughput | decay_geo_gauss_function_score | 50.28 | ops/s | +| Mean Throughput | decay_geo_gauss_function_score | 50.28 | ops/s | +| Median Throughput | decay_geo_gauss_function_score | 50.28 | ops/s | +| Max Throughput | decay_geo_gauss_function_score | 50.28 | ops/s | +| 100th percentile latency | decay_geo_gauss_function_score | 25.9491 | ms | +| 100th percentile service time | decay_geo_gauss_function_score | 5.7773 | ms | +| error rate | decay_geo_gauss_function_score | 0 | % | +| Min Throughput | decay_geo_gauss_script_score | 28.96 | ops/s | +| Mean Throughput | decay_geo_gauss_script_score | 28.96 | ops/s | +| Median Throughput | decay_geo_gauss_script_score | 28.96 | ops/s | +| Max Throughput | decay_geo_gauss_script_score | 28.96 | ops/s | +| 100th percentile latency | decay_geo_gauss_script_score | 41.179 | ms | +| 100th percentile service time | decay_geo_gauss_script_score | 6.20007 | ms | +| error rate | decay_geo_gauss_script_score | 0 | % | +| Min Throughput | field_value_function_score | 52.97 | ops/s | +| Mean Throughput | field_value_function_score | 52.97 | ops/s | +| Median Throughput | field_value_function_score | 52.97 | ops/s | +| Max Throughput | field_value_function_score | 52.97 | ops/s | +| 100th percentile latency | field_value_function_score | 25.9004 | ms | +| 100th percentile service time | field_value_function_score | 6.68765 | ms | +| error rate | field_value_function_score | 0 | % | +| Min Throughput | field_value_script_score | 35.24 | ops/s | +| Mean Throughput | field_value_script_score | 35.24 | ops/s | +| Median Throughput | field_value_script_score | 35.24 | ops/s | +| Max Throughput | field_value_script_score | 35.24 | ops/s | +| 100th percentile latency | field_value_script_score | 34.2866 | ms | +| 100th percentile service time | field_value_script_score | 5.63202 | ms | +| error rate | field_value_script_score | 0 | % | +| Min Throughput | large_terms | 1.05 | ops/s | +| Mean Throughput | large_terms | 1.05 | ops/s | +| Median Throughput | large_terms | 1.05 | ops/s | +| Max Throughput | large_terms | 1.05 | ops/s | +| 100th percentile latency | large_terms | 1220.12 | ms | +| 100th percentile service time | large_terms | 256.856 | ms | +| error rate | large_terms | 0 | % | +| Min Throughput | large_filtered_terms | 4.11 | ops/s | +| Mean Throughput | large_filtered_terms | 4.11 | ops/s | +| Median Throughput | large_filtered_terms | 4.11 | ops/s | +| Max Throughput | large_filtered_terms | 4.11 | ops/s | +| 100th percentile latency | large_filtered_terms | 389.415 | ms | +| 100th percentile service time | large_filtered_terms | 137.216 | ms | +| error rate | large_filtered_terms | 0 | % | +| Min Throughput | large_prohibited_terms | 5.68 | ops/s | +| Mean Throughput | large_prohibited_terms | 5.68 | ops/s | +| Median Throughput | large_prohibited_terms | 5.68 | ops/s | +| Max Throughput | large_prohibited_terms | 5.68 | ops/s | +| 100th percentile latency | large_prohibited_terms | 352.926 | ms | +| 100th percentile service time | large_prohibited_terms | 169.633 | ms | +| error rate | large_prohibited_terms | 0 | % | +| Min Throughput | desc_sort_population | 42.48 | ops/s | +| Mean Throughput | desc_sort_population | 42.48 | ops/s | +| Median Throughput | desc_sort_population | 42.48 | ops/s | +| Max Throughput | desc_sort_population | 42.48 | ops/s | +| 100th percentile latency | desc_sort_population | 28.6485 | ms | +| 100th percentile service time | desc_sort_population | 4.82649 | ms | +| error rate | desc_sort_population | 0 | % | +| Min Throughput | :_sort_population | 49.06 | ops/s | +| Mean Throughput | asc_sort_population | 49.06 | ops/s | +| Median Throughput | asc_sort_population | 49.06 | ops/s | +| Max Throughput | asc_sort_population | 49.06 | ops/s | +| 100th percentile latency | asc_sort_population | 30.7929 | ms | +| 100th percentile service time | asc_sort_population | 10.0023 | ms | +| error rate | asc_sort_population | 0 | % | +| Min Throughput | asc_sort_with_after_population | 55.9 | ops/s | +| Mean Throughput | asc_sort_with_after_population | 55.9 | ops/s | +| Median Throughput | asc_sort_with_after_population | 55.9 | ops/s | +| Max Throughput | asc_sort_with_after_population | 55.9 | ops/s | +| 100th percentile latency | asc_sort_with_after_population | 25.413 | ms | +| 100th percentile service time | asc_sort_with_after_population | 7.00911 | ms | +| error rate | asc_sort_with_after_population | 0 | % | +| Min Throughput | desc_sort_geonameid | 63.86 | ops/s | +| Mean Throughput | desc_sort_geonameid | 63.86 | ops/s | +| Median Throughput | desc_sort_geonameid | 63.86 | ops/s | +| Max Throughput | desc_sort_geonameid | 63.86 | ops/s | +| 100th percentile latency | desc_sort_geonameid | 21.3566 | ms | +| 100th percentile service time | desc_sort_geonameid | 5.41555 | ms | +| error rate | desc_sort_geonameid | 0 | % | +| Min Throughput | desc_sort_with_after_geonameid | 58.36 | ops/s | +| Mean Throughput | desc_sort_with_after_geonameid | 58.36 | ops/s | +| Median Throughput | desc_sort_with_after_geonameid | 58.36 | ops/s | +| Max Throughput | desc_sort_with_after_geonameid | 58.36 | ops/s | +| 100th percentile latency | desc_sort_with_after_geonameid | 24.3476 | ms | +| 100th percentile service time | desc_sort_with_after_geonameid | 6.81395 | ms | +| error rate | desc_sort_with_after_geonameid | 0 | % | +| Min Throughput | asc_sort_geonameid | 69.44 | ops/s | +| Mean Throughput | asc_sort_geonameid | 69.44 | ops/s | +| Median Throughput | asc_sort_geonameid | 69.44 | ops/s | +| Max Throughput | asc_sort_geonameid | 69.44 | ops/s | +| 100th percentile latency | asc_sort_geonameid | 19.4046 | ms | +| 100th percentile service time | asc_sort_geonameid | 4.72967 | ms | +| error rate | asc_sort_geonameid | 0 | % | +| Min Throughput | asc_sort_with_after_geonameid | 70.35 | ops/s | +| Mean Throughput | asc_sort_with_after_geonameid | 70.35 | ops/s | +| Median Throughput | asc_sort_with_after_geonameid | 70.35 | ops/s | +| Max Throughput | asc_sort_with_after_geonameid | 70.35 | ops/s | +| 100th percentile latency | asc_sort_with_after_geonameid | 18.664 | ms | +| 100th percentile service time | asc_sort_with_after_geonameid | 4.16119 | ms | +| error rate | asc_sort_with_after_geonameid | 0 | % | + + +-------------------------------- +[INFO] SUCCESS (took 98 seconds) +-------------------------------- +``` + +Each task run by the `geonames` workload represents a specific OpenSearch API operation---such as Bulk or Search---that was performed when the test was run. Each task in the output summary contains the following information: + +* **Throughput:** The number of successful OpenSearch operations per second. +* **Latency:** The amount of time, including wait time, taken for the request and the response to be sent and received by Benchmark. +* **Service Time:** The amount of time, excluding wait time, taken for the request and the response to be sent and received by Benchmark. +* **Error Rate:** The percentage of operations run during the task that were not successful or returned a 200 error code. + + +## Next steps + +See the following resources to learn more about OpenSearch Benchmark: + +- [User guide]({{site.url}}{{site.baseurl}}/benchmark/user-guide/index/): Dive deep into how OpenSearch Benchmark can you help you track the performance of your cluster. +- [Tutorials]({{site.url}}{{site.baseurl}}/benchmark/tutorials/index/): Use step-by-step guides for more advanced Benchmarking configurations and functionality. diff --git a/_benchmark/tutorials/index.md b/_benchmark/tutorials/index.md new file mode 100644 index 0000000000..3e53db2eae --- /dev/null +++ b/_benchmark/tutorials/index.md @@ -0,0 +1,10 @@ +--- +layout: default +title: Tutorials +nav_order: 10 +has_children: true +--- + +# Tutorial + +This section of the OpenSearch Benchmark documentation provides a set of tutorials for those who want to learn more advanced OpenSearch Benchmark concepts. \ No newline at end of file diff --git a/_benchmark/tutorials/sigv4.md b/_benchmark/tutorials/sigv4.md new file mode 100644 index 0000000000..8e25362f7b --- /dev/null +++ b/_benchmark/tutorials/sigv4.md @@ -0,0 +1,32 @@ +--- +layout: default +title: AWS Signature Version 4 support +nav_order: 70 +parent: Tutorials +--- + +# Running OpenSearch Benchmark with AWS Signature Version 4 + +OpenSearch Benchmark supports AWS Signature Version 4 authentication. To run Benchmark with Signature Version 4, use the following steps: + +1. Set up an [IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html) and provide it access to the OpenSearch cluster using Signature Version 4 authentication. + +2. Set up the following environment variables for your IAM user: + + ```bash + OSB_AWS_ACCESS_KEY_ID=< + OSB_AWS_SECRET_ACCESS_KEY= + OSB_REGION= + OSB_SERVICE=aos + ``` + {% include copy.html %} + +3. Customize and run the following `execute-test` command with the ` --client-options=amazon_aws_log_in:environment` flag. This flag tells OpenSearch Benchmark the location of your exported credentials. + + ```bash + opensearch-benchmark execute-test \ + --target-hosts= \ + --pipeline=benchmark-only \ + --workload=geonames \ + --client-options=timeout:120,amazon_aws_log_in:environment \ + ``` \ No newline at end of file diff --git a/_benchmark/user-guide/concepts.md b/_benchmark/user-guide/concepts.md new file mode 100644 index 0000000000..265f698b56 --- /dev/null +++ b/_benchmark/user-guide/concepts.md @@ -0,0 +1,171 @@ +--- +layout: default +title: Concepts +nav_order: 3 +parent: User guide +--- + +# Concepts + +Before using OpenSearch Benchmark, familiarize yourself with the following concepts. + +## Core concepts and definitions + +- **Workload**: The description of one or more benchmarking scenarios that use a specific document corpus to perform a benchmark against your cluster. The document corpus contains any indexes, data files, and operations invoked when the workflow runs. You can list the available workloads by using `opensearch-benchmark list workloads` or view any included workloads in the [OpenSearch Benchmark Workloads repository](https://github.com/opensearch-project/opensearch-benchmark-workloads/). For more information about the elements of a workload, see [Anatomy of a workload](#anatomy-of-a-workload). For information about building a custom workload, see [Creating custom workloads]({{site.url}}{{site.baseurl}}/benchmark/creating-custom-workloads/). + +- **Pipeline**: A series of steps occurring before and after a workload is run that determines benchmark results. OpenSearch Benchmark supports three pipelines: + - `from-sources`: Builds and provisions OpenSearch, runs a benchmark, and then publishes the results. + - `from-distribution`: Downloads an OpenSearch distribution, provisions it, runs a benchmark, and then publishes the results. + - `benchmark-only`: The default pipeline. Assumes an already running OpenSearch instance, runs a benchmark on that instance, and then publishes the results. + +- **Test**: A single invocation of the OpenSearch Benchmark binary. + +A workload is a specification of one or more benchmarking scenarios. A workload typically includes the following: + +- One or more data streams that are ingested into indexes. +- A set of queries and operations that are invoked as part of the benchmark. + +## Anatomy of a workload + +The following example workload shows all of the essential elements needed to create a `workload.json` file. You can run this workload in your own benchmark configuration to understand how all of the elements work together: + +```json +{ + "description": "Tutorial benchmark for OpenSearch Benchmark", + "indices": [ + { + "name": "movies", + "body": "index.json" + } + ], + "corpora": [ + { + "name": "movies", + "documents": [ + { + "source-file": "movies-documents.json", + "document-count": 11658903, # Fetch document count from command line + "uncompressed-bytes": 1544799789 # Fetch uncompressed bytes from command line + } + ] + } + ], + "schedule": [ + { + "operation": { + "operation-type": "create-index" + } + }, + { + "operation": { + "operation-type": "cluster-health", + "request-params": { + "wait_for_status": "green" + }, + "retry-until-success": true + } + }, + { + "operation": { + "operation-type": "bulk", + "bulk-size": 5000 + }, + "warmup-time-period": 120, + "clients": 8 + }, + { + "operation": { + "name": "query-match-all", + "operation-type": "search", + "body": { + "query": { + "match_all": {} + } + } + }, + "iterations": 1000, + "target-throughput": 100 + } + ] +} +``` + +A workload usually includes the following elements: + +- [indices]({{site.url}}{{site.baseurl}}/benchmark/workloads/indices/): Defines the relevant indexes and index templates used for the workload. +- [corpora]({{site.url}}{{site.baseurl}}/benchmark/workloads/corpora/): Defines all document corpora used for the workload. +- `schedule`: Defines operations and the order in which the operations run inline. Alternatively, you can use `operations` to group operations and the `test_procedures` parameter to specify the order of operations. +- `operations`: **Optional**. Describes which operations are available for the workload and how they are parameterized. + +### Indices + +To create an index, specify its `name`. To add definitions to your index, use the `body` option and point it to the JSON file containing the index definitions. For more information, see [indices]({{site.url}}{{site.baseurl}}/benchmark/workloads/indices/). + +### Corpora + +The `corpora` element requires the name of the index containing the document corpus, for example, `movies`, and a list of parameters that define the document corpora. This list includes the following parameters: + +- `source-file`: The file name that contains the workload's corresponding documents. When using OpenSearch Benchmark locally, documents are contained in a JSON file. When providing a `base_url`, use a compressed file format: `.zip`, `.bz2`, `.gz`, `.tar`, `.tar.gz`, `.tgz`, or `.tar.bz2`. The compressed file must have one JSON file containing the name. +- `document-count`: The number of documents in the `source-file`, which determines which client indexes correlate to which parts of the document corpus. Each N client receives an Nth of the document corpus. When using a source that contains a document with a parent-child relationship, specify the number of parent documents. +- `uncompressed-bytes`: The size, in bytes, of the source file after decompression, indicating how much disk space the decompressed source file needs. +- `compressed-bytes`: The size, in bytes, of the source file before decompression. This can help you assess the amount of time needed for the cluster to ingest documents. + +### Operations + +The `operations` element lists the OpenSearch API operations performed by the workload. For example, you can set an operation to `create-index`, an index in the test cluster to which OpenSearch Benchmark can write documents. Operations are usually listed inside of `schedule`. + +### Schedule + +The `schedule` element contains a list of actions and operations that are run by the workload. Operations run according to the order in which they appear in the `schedule`. The following example illustrates a `schedule` with multiple operations, each defined by its `operation-type`: + +```json + "schedule": [ + { + "operation": { + "operation-type": "create-index" + } + }, + { + "operation": { + "operation-type": "cluster-health", + "request-params": { + "wait_for_status": "green" + }, + "retry-until-success": true + } + }, + { + "operation": { + "operation-type": "bulk", + "bulk-size": 5000 + }, + "warmup-time-period": 120, + "clients": 8 + }, + { + "operation": { + "name": "query-match-all", + "operation-type": "search", + "body": { + "query": { + "match_all": {} + } + } + }, + "iterations": 1000, + "target-throughput": 100 + } + ] +} +``` + +According to this schedule, the actions will run in the following order: + +1. The `create-index` operation creates an index. The index remains empty until the `bulk` operation adds documents with benchmarked data. +2. The `cluster-health` operation assesses the health of the cluster before running the workload. In this example, the workload waits until the status of the cluster's health is `green`. + - The `bulk` operation runs the `bulk` API to index `5000` documents simultaneously. + - Before benchmarking, the workload waits until the specified `warmup-time-period` passes. In this example, the warmup period is `120` seconds. +5. The `clients` field defines the number of clients that will run the remaining actions in the schedule concurrently. +6. The `search` runs a `match_all` query to match all documents after they have been indexed by the `bulk` API using the 8 clients specified. + - The `iterations` field indicates the number of times each client runs the `search` operation. The report generated by the benchmark automatically adjusts the percentile numbers based on this number. To generate a precise percentile, the benchmark needs to run at least 1,000 iterations. + - Lastly, the `target-throughput` field defines the number of requests per second each client performs, which, when set, can help reduce the latency of the benchmark. For example, a `target-throughput` of 100 requests divided by 8 clients means that each client will issue 12 requests per second. diff --git a/_benchmark/configuring-benchmark.md b/_benchmark/user-guide/configuring-benchmark.md similarity index 99% rename from _benchmark/configuring-benchmark.md rename to _benchmark/user-guide/configuring-benchmark.md index aa097f55ae..14d796a0d0 100644 --- a/_benchmark/configuring-benchmark.md +++ b/_benchmark/user-guide/configuring-benchmark.md @@ -2,7 +2,8 @@ layout: default title: Configuring OpenSearch Benchmark nav_order: 7 -has_children: false +parent: User guide +redirect_from: /benchmark/configuring-benchmark/ --- # Configuring OpenSearch Benchmark diff --git a/_benchmark/creating-custom-workloads.md b/_benchmark/user-guide/creating-custom-workloads.md similarity index 99% rename from _benchmark/creating-custom-workloads.md rename to _benchmark/user-guide/creating-custom-workloads.md index b5474fafe6..6ad284c2d1 100644 --- a/_benchmark/creating-custom-workloads.md +++ b/_benchmark/user-guide/creating-custom-workloads.md @@ -2,7 +2,8 @@ layout: default title: Creating custom workloads nav_order: 10 -has_children: false +parent: User guide +redirect_from: /benchmark/creating-custom-workloads/ --- # Creating custom workloads diff --git a/_benchmark/user-guide/index.md b/_benchmark/user-guide/index.md new file mode 100644 index 0000000000..358285521d --- /dev/null +++ b/_benchmark/user-guide/index.md @@ -0,0 +1,10 @@ +--- +layout: default +title: User guide +nav_order: 5 +has_children: true +--- + +# OpenSearch Benchmark User Guide + +The OpenSearch Benchmark User Guide includes core [concepts]({{site.url}}{{site.baseurl}}/benchmark/user-guide/concepts/), [installation]({{site.url}}{{site.baseurl}}/benchmark/installing-benchmark/) instructions, and [configuration options]({{site.url}}{{site.baseurl}}/benchmark/configuring-benchmark/) to help you get the most out of OpenSearch Benchmark. \ No newline at end of file diff --git a/_benchmark/installing-benchmark.md b/_benchmark/user-guide/installing-benchmark.md similarity index 73% rename from _benchmark/installing-benchmark.md rename to _benchmark/user-guide/installing-benchmark.md index 4749160796..b3c35b550c 100644 --- a/_benchmark/installing-benchmark.md +++ b/_benchmark/user-guide/installing-benchmark.md @@ -2,7 +2,8 @@ layout: default title: Installing OpenSearch Benchmark nav_order: 5 -has_children: false +parent: User guide +redirect_from: /benchmark/installing-benchmark/ --- # Installing OpenSearch Benchmark @@ -150,6 +151,59 @@ run -v $HOME/benchmarks:/opensearch-benchmark/.benchmark opensearchproject/opens See [Configuring OpenSearch Benchmark]({{site.url}}{{site.baseurl}}/benchmark/configuring-benchmark/) to learn more about the files and subdirectories located in `/opensearch-benchmark/.benchmark`. +## Provisioning an OpenSearch cluster with a test + +OpenSearch Benchmark is compatible with JDK versions 17, 16, 15, 14, 13, 12, 11, and 8. +{: .note} + +If you installed OpenSearch with PyPi, you can also provision a new OpenSearch cluster by specifying a `distribution-version` in the `execute-test` command. + +If you plan on having Benchmark provision a cluster, you'll need to inform Benchmark of the location of the `JAVA_HOME` path for the Benchmark cluster. To set the `JAVA_HOME` path and provision a cluster: + +1. Find the `JAVA_HOME` path you're currently using. Open a terminal and enter `/usr/libexec/java_home`. + +2. Set your corresponding JDK version environment variable by entering the path from the previous step. Enter `export JAVA17_HOME=`. + +3. Run the `execute-test` command and indicate the distribution version of OpenSearch you want to use: + + ```bash + opensearch-benchmark execute-test --distribution-version=2.3.0 --workload=geonames --test-mode + ``` + +## Directory structure + +After running OpenSearch Benchmark for the first time, you can search through all related files, including configuration files, in the `~/.benchmark` directory. The directory includes the following file tree: + +``` +# ~/.benchmark Tree +. +├── benchmark.ini +├── benchmarks +│ ├── data +│ │ └── geonames +│ ├── distributions +│ │ ├── opensearch-1.0.0-linux-x64.tar.gz +│ │ └── opensearch-2.3.0-linux-x64.tar.gz +│ ├── test_executions +│ │ ├── 0279b13b-1e54-49c7-b1a7-cde0b303a797 +│ │ └── 0279c542-a856-4e88-9cc8-04306378cd38 +│ └── workloads +│ └── default +│ └── geonames +├── logging.json +├── logs +│ └── benchmark.log +``` + +* `benchmark.ini`: Contains any adjustable configurations for tests. For information about how to configure OpenSearch Benchmark, see [Configuring OpenSearch Benchmark]({{site.url}}{{site.baseurl}}/benchmark/configuring-benchmark/). +* `data`: Contains all the data corpora and documents related to OpenSearch Benchmark's [official workloads](https://github.com/opensearch-project/opensearch-benchmark-workloads/tree/main/geonames). +* `distributions`: Contains all the OpenSearch distributions downloaded from [OpenSearch.org](http://opensearch.org/) and used to provision clusters. +* `test_executions`: Contains all the test `execution_id`s from previous runs of OpenSearch Benchmark. +* `workloads`: Contains all files related to workloads, except for the data corpora. +* `logging.json`: Contains all of the configuration options related to how logging is performed within OpenSearch Benchmark. +* `logs`: Contains all the logs from OpenSearch Benchmark runs. This can be helpful when you've encountered errors during runs. + + ## Next steps - [Configuring OpenSearch Benchmark]({{site.url}}{{site.baseurl}}/benchmark/configuring-benchmark/) diff --git a/_benchmark/workloads/index.md b/_benchmark/workloads/index.md index 771e98309f..d92ad2c1fa 100644 --- a/_benchmark/workloads/index.md +++ b/_benchmark/workloads/index.md @@ -12,153 +12,12 @@ A workload is a specification of one or more benchmarking scenarios. A workload - One or more data streams that are ingested into indices - A set of queries and operations that are invoked as part of the benchmark -## Anatomy of a workload +This section provides a list of options and examples you can use when customizing or using a workload. -The following example workload shows all of the essential elements needed to create a workload.json file. You can run this workload in your own benchmark configuration in order to understand how all of the elements work together: - -```json -{ - "description": "Tutorial benchmark for OpenSearch Benchmark", - "indices": [ - { - "name": "movies", - "body": "index.json" - } - ], - "corpora": [ - { - "name": "movies", - "documents": [ - { - "source-file": "movies-documents.json", - "document-count": 11658903, # Fetch document count from command line - "uncompressed-bytes": 1544799789 # Fetch uncompressed bytes from command line - } - ] - } - ], - "schedule": [ - { - "operation": { - "operation-type": "create-index" - } - }, - { - "operation": { - "operation-type": "cluster-health", - "request-params": { - "wait_for_status": "green" - }, - "retry-until-success": true - } - }, - { - "operation": { - "operation-type": "bulk", - "bulk-size": 5000 - }, - "warmup-time-period": 120, - "clients": 8 - }, - { - "operation": { - "name": "query-match-all", - "operation-type": "search", - "body": { - "query": { - "match_all": {} - } - } - }, - "iterations": 1000, - "target-throughput": 100 - } - ] -} -``` - -A workload usually consists of the following elements: - -- [indices]({{site.url}}{{site.baseurl}}/benchmark/workloads/indices/): Defines the relevant indices and index templates used for the workload. -- [corpora]({{site.url}}{{site.baseurl}}/benchmark/workloads/corpora/): Defines all document corpora used for the workload. -- `schedule`: Defines operations and in what order the operations run in-line. Alternatively, you can use `operations` to group operations and the `test_procedures` parameter to specify the order of operations. -- `operations`: **Optional**. Describes which operations are available for the workload and how they are parameterized. - -### Indices - -To create an index, specify its `name`. To add definitions to your index, use the `body` option and point it to the JSON file containing the index definitions. For more information, see [indices]({{site.url}}{{site.baseurl}}/benchmark/workloads/indices/). For more information, see [indices]({{site.url}}{{site.baseurl}}/benchmark/workloads/indices/). - -### Corpora - -The `corpora` element requires the name of the index containing the document corpus, for example, `movies`, and a list of parameters that define the document corpora. This list includes the following parameters: - -- `source-file`: The file name that contains the workload's corresponding documents. When using OpenSearch Benchmark locally, documents are contained in a JSON file. When providing a `base_url`, use a compressed file format: `.zip`, `.bz2`, `.gz`, `.tar`, `.tar.gz`, `.tgz`, or `.tar.bz2`. The compressed file must have one JSON file containing the name. -- `document-count`: The number of documents in the `source-file`, which determines which client indices correlate to which parts of the document corpus. Each N client receives an Nth of the document corpus. When using a source that contains a document with a parent-child relationship, specify the number of parent documents. -- `uncompressed-bytes`: The size, in bytes, of the source file after decompression, indicating how much disk space the decompressed source file needs. -- `compressed-bytes`: The size, in bytes, of the source file before decompression. This can help you assess the amount of time needed for the cluster to ingest documents. - -### Operations - -The `operations` element lists the OpenSearch API operations performed by the workload. For example, you can set an operation to `create-index`, which creates an index in the test cluster that OpenSearch Benchmark can write documents into. Operations are usually listed inside of `schedule`. - -### Schedule - -The `schedule` element contains a list of actions and operations that are run by the workload. Operations run according to the order in which they appear in the `schedule`. The following example illustrates a `schedule` with multiple operations, each defined by its `operation-type`: - -```json - "schedule": [ - { - "operation": { - "operation-type": "create-index" - } - }, - { - "operation": { - "operation-type": "cluster-health", - "request-params": { - "wait_for_status": "green" - }, - "retry-until-success": true - } - }, - { - "operation": { - "operation-type": "bulk", - "bulk-size": 5000 - }, - "warmup-time-period": 120, - "clients": 8 - }, - { - "operation": { - "name": "query-match-all", - "operation-type": "search", - "body": { - "query": { - "match_all": {} - } - } - }, - "iterations": 1000, - "target-throughput": 100 - } - ] -} -``` - -According to this schedule, the actions will run in the following order: - -1. The `create-index` operation creates an index. The index remains empty until the `bulk` operation adds documents with benchmarked data. -2. The `cluster-health` operation assesses the health of the cluster before running the workload. In this example, the workload waits until the status of the cluster's health is `green`. - - The `bulk` operation runs the `bulk` API to index `5000` documents simultaneously. - - Before benchmarking, the workload waits until the specified `warmup-time-period` passes. In this example, the warmup period is `120` seconds. -5. The `clients` field defines the number of clients that will run the remaining actions in the schedule concurrently. -6. The `search` runs a `match_all` query to match all documents after they have been indexed by the `bulk` API using the 8 clients specified. - - The `iterations` field indicates the number of times each client runs the `search` operation. The report generated by the benchmark automatically adjusts the percentile numbers based on this number. To generate a precise percentile, the benchmark needs to run at least 1,000 iterations. - - Lastly, the `target-throughput` field defines the number of requests per second each client performs, which, when set, can help reduce the latency of the benchmark. For example, a `target-throughput` of 100 requests divided by 8 clients means that each client will issue 12 requests per second. +For more information about what comprises a workload, see [Anatomy of a workload]({{site.url}}{{site.baseurl}}/benchmark/user-guide/concepts#anatomy-of-a-workload). -## More workload examples +## Workload examples If you want to try certain workloads before creating your own, use the following examples. diff --git a/images/benchmark/OSB-workflow.png b/images/benchmark/OSB-workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..cedbf577a1d33378ebcd926152fc2ab26b815f85 GIT binary patch literal 54708 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

}Pu*u)n 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%0D{Gt*Rnj`K-`Bm+7aNbV#Mepi&CS~ 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 NMgF?nD;dLk{|~pp=@S3| literal 0 HcmV?d00001