blob: e77b7215e03b00de039d9fed6d665c99c394d0ce [file] [view]
---
title: BE Storage Layer Benchmark Tool
language: en
description: Apache Doris BE storage layer benchmark tool for segment read/write and performance testing.
keywords:
- Apache Doris
- BE storage layer
- Benchmark
- Segment
- Page
- Dictionary encoding
- google benchmark
- CustomBenchmark
---
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# BE Storage Layer Benchmark Tool
<!-- Knowledge type: Tool usage -->
<!-- Applicable scenarios: Performance tuning / Storage layer benchmarking -->
## Purpose
`benchmark_tool` tests the performance of the Apache Doris BE storage layer (such as `segment` and `page`). It constructs the specified objects from input data and runs performance tests through [google benchmark](https://github.com/google/benchmark).
## Compilation
1. Make sure you have an environment that can compile Doris itself. See [Compilation and Deployment](/community/source-install/compilation-with-docker) for reference.
2. Run `run-be-ut.sh` in the Doris repository.
3. The compiled executable is located at `./be/ut_build_ASAN/test/tools/benchmark_tool`.
## Usage
### Common Parameters
| Parameter | Meaning | Default |
|------|------|--------|
| `--operation` | Test type. See the scenarios below for details. | None (required) |
| `--column_type` | Column types of the segment table schema. Supports `int`, `char`, `varchar`, `string`. | `int,varchar` |
| `--rows_number` | Number of data rows. | `10000` |
| `--iterations` | Number of test iterations. `0` lets benchmark choose automatically. | `10` |
| `--input_file` | Path of the data file when importing data from a file. | None |
Type length conventions:
| Type | Length |
|------|------|
| `char` | `8` |
| `varchar` | Maximum value |
| `string` | Maximum value |
Random dataset generation rules:
| Type | Rule |
|------|------|
| `int` | Random within `[1, 1000000]` |
| `char` | Random length within `[1, 8]`, character set is uppercase and lowercase English letters |
| `varchar` | Random length within `[1, 128]`, character set is uppercase and lowercase English letters |
| `string` | Random length within `[1, 100000]`, character set is uppercase and lowercase English letters |
### Test Scenarios at a Glance
| Scenario | Command |
|------|------|
| Segment read test with a random dataset | `./benchmark_tool --operation=SegmentScan --column_type=int,varchar --rows_number=10000 --iterations=0` |
| Segment write test with a random dataset | `./benchmark_tool --operation=SegmentWrite` |
| Segment read test with a dataset imported from a file | `./benchmark_tool --operation=SegmentScanByFile --input_file=./sample.dat` |
| Segment write test with a dataset imported from a file | `./benchmark_tool --operation=SegmentWriteByFile --input_file=./sample.dat` |
| Page dictionary encoding test with a random dataset | `./benchmark_tool --operation=BinaryDictPageEncode --rows_number=10000 --iterations=0` |
| Page dictionary decoding test with a random dataset | `./benchmark_tool --operation=BinaryDictPageDecode` |
### Segment Read Test with a Randomly Generated Dataset
First writes a `segment` file using the dataset, then measures the time to scan the entire `segment`.
```bash
./benchmark_tool --operation=SegmentScan --column_type=int,varchar --rows_number=10000 --iterations=0
```
### Segment Write Test with a Randomly Generated Dataset
Measures the time of the process that adds the dataset to a `segment` and writes it to disk.
```bash
./benchmark_tool --operation=SegmentWrite
```
### Segment Read Test with a Dataset Imported from a File
```bash
./benchmark_tool --operation=SegmentScanByFile --input_file=./sample.dat
```
`input_file` is the imported dataset file. The first line of the file defines the table schema, and each subsequent line corresponds to one row of data with columns separated by `,`:
```text
int,char,varchar
123,hello,world
321,good,bye
```
The supported types are also `int`, `char`, `varchar`, and `string`. Note that data of the `char` type cannot exceed a length of `8`.
### Segment Write Test with a Dataset Imported from a File
```bash
./benchmark_tool --operation=SegmentWriteByFile --input_file=./sample.dat
```
### Page Dictionary Encoding Test with a Randomly Generated Dataset
```bash
./benchmark_tool --operation=BinaryDictPageEncode --rows_number=10000 --iterations=0
```
Randomly generates `varchar` values with lengths in `[1, 8]` and measures the encoding time.
### Page Dictionary Decoding Test with a Randomly Generated Dataset
```bash
./benchmark_tool --operation=BinaryDictPageDecode
```
Randomly generates `varchar` values with lengths in `[1, 8]`, encodes them, and measures the decoding time.
## Custom Tests
You can run performance tests with your own functions. The implementation is in `/be/test/tools/benchmark_tool.cpp`.
### 1. Write the Test Function
```cpp
void custom_run_plus() {
int p = 100000;
int q = 0;
while (p--) {
q++;
if (UNLIKELY(q == 1024)) q = 0;
}
}
void custom_run_mod() {
int p = 100000;
int q = 0;
while (p--) {
q++;
if (q %= 1024) q = 0;
}
}
```
### 2. Register CustomBenchmark
```cpp
benchmarks.emplace_back(
new doris::CustomBenchmark("custom_run_plus", 0,
custom_init, custom_run_plus));
benchmarks.emplace_back(
new doris::CustomBenchmark("custom_run_mod", 0,
custom_init, custom_run_mod));
```
Here, `init` is the initialization step for each round of testing (not counted in the elapsed time). If you need to initialize objects, implement it through a derived class of `CustomBenchmark`.
### 3. Example Run Output
```text
2021-08-30T10:29:35+08:00
Running ./benchmark_tool
Run on (96 X 3100.75 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x48)
L1 Instruction 32 KiB (x48)
L2 Unified 1024 KiB (x48)
L3 Unified 33792 KiB (x2)
Load Average: 0.55, 0.53, 0.39
----------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------
custom_run_plus 0.812 ms 0.812 ms 861
custom_run_mod 1.30 ms 1.30 ms 539
```
## FAQ
**Q: Cannot find the `benchmark_tool` executable?**
Run `run-be-ut.sh` first to fully build the BE unit tests. The executable is output to `./be/ut_build_ASAN/test/tools/benchmark_tool`.
**Q: The custom test result does not match expectations?**
Make sure `custom_init` does not contain the logic of the function under test, and that the body of each `custom_run_*` function is large enough to avoid being eliminated by the optimizer.