Add analyze script
This commit is contained in:
parent
36a7abb170
commit
500691318a
@ -103,7 +103,7 @@ static void BM_BenchmarkContainsBppTree(::benchmark::State &state) {
|
|||||||
tlx::btree_map<storage::v3::PrimaryKey, storage::v3::LexicographicallyOrderedVertex> bpp_tree;
|
tlx::btree_map<storage::v3::PrimaryKey, storage::v3::LexicographicallyOrderedVertex> bpp_tree;
|
||||||
PrepareData(bpp_tree, state.range(0));
|
PrepareData(bpp_tree, state.range(0));
|
||||||
|
|
||||||
// So we can also have elements that does don't exist
|
// So we can also have elements that does don't exists
|
||||||
std::mt19937 i_generator(std::random_device{}());
|
std::mt19937 i_generator(std::random_device{}());
|
||||||
std::uniform_int_distribution<int64_t> i_distribution(0, state.range(0) * 2);
|
std::uniform_int_distribution<int64_t> i_distribution(0, state.range(0) * 2);
|
||||||
int64_t found_elems{0};
|
int64_t found_elems{0};
|
||||||
@ -118,13 +118,13 @@ static void BM_BenchmarkContainsBppTree(::benchmark::State &state) {
|
|||||||
state.SetItemsProcessed(found_elems);
|
state.SetItemsProcessed(found_elems);
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkContainsSkipList)->Arg(1000);
|
BENCHMARK(BM_BenchmarkContainsSkipList)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkContainsStdMap)->Arg(1000);
|
BENCHMARK(BM_BenchmarkContainsStdMap)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkContainsStdSet)->Arg(1000);
|
BENCHMARK(BM_BenchmarkContainsStdSet)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkContainsBppTree)->Arg(1000);
|
BENCHMARK(BM_BenchmarkContainsBppTree)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
} // namespace memgraph::benchmark
|
} // namespace memgraph::benchmark
|
||||||
|
|
||||||
|
@ -117,13 +117,13 @@ static void BM_BenchmarkFindBppTree(::benchmark::State &state) {
|
|||||||
state.SetItemsProcessed(found_elems);
|
state.SetItemsProcessed(found_elems);
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkFindSkipList)->Arg(1000);
|
BENCHMARK(BM_BenchmarkFindSkipList)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkFindStdMap)->Arg(1000);
|
BENCHMARK(BM_BenchmarkFindStdMap)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkFindStdSet)->Arg(1000);
|
BENCHMARK(BM_BenchmarkFindStdSet)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkFindBppTree)->Arg(1000);
|
BENCHMARK(BM_BenchmarkFindBppTree)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
} // namespace memgraph::benchmark
|
} // namespace memgraph::benchmark
|
||||||
|
|
||||||
|
@ -99,13 +99,13 @@ static void BM_BenchmarkInsertBppTree(::benchmark::State &state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkInsertSkipList)->Arg(1000);
|
BENCHMARK(BM_BenchmarkInsertSkipList)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkInsertStdMap)->Arg(1000);
|
BENCHMARK(BM_BenchmarkInsertStdMap)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkInsertStdSet)->Arg(1000);
|
BENCHMARK(BM_BenchmarkInsertStdSet)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkInsertBppTree)->Arg(1000);
|
BENCHMARK(BM_BenchmarkInsertBppTree)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
} // namespace memgraph::benchmark
|
} // namespace memgraph::benchmark
|
||||||
|
|
||||||
|
@ -125,13 +125,13 @@ static void BM_BenchmarkRemoveBppTree(::benchmark::State &state) {
|
|||||||
state.SetItemsProcessed(removed_elems);
|
state.SetItemsProcessed(removed_elems);
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkRemoveSkipList)->Arg(1000);
|
BENCHMARK(BM_BenchmarkRemoveSkipList)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkRemoveStdMap)->Arg(1000);
|
BENCHMARK(BM_BenchmarkRemoveStdMap)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkRemoveStdSet)->Arg(1000);
|
BENCHMARK(BM_BenchmarkRemoveStdSet)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
BENCHMARK(BM_BenchmarkRemoveBppTree)->Arg(1000);
|
BENCHMARK(BM_BenchmarkRemoveBppTree)->RangeMultiplier(10)->Range(1000, 1000000)->Unit(::benchmark::kMillisecond);
|
||||||
|
|
||||||
} // namespace memgraph::benchmark
|
} // namespace memgraph::benchmark
|
||||||
|
|
||||||
|
172
tools/plot/benchmark_datastructures.py
Normal file
172
tools/plot/benchmark_datastructures.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
# Copyright 2022 Memgraph Ltd.
|
||||||
|
#
|
||||||
|
# Use of this software is governed by the Business Source License
|
||||||
|
# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
|
# License, and you may not use this file except in compliance with the Business Source License.
|
||||||
|
#
|
||||||
|
# As of the Change Date specified in that file, in accordance with
|
||||||
|
# the Business Source License, use of this software will be governed
|
||||||
|
# by the Apache License, Version 2.0, included in the file
|
||||||
|
# licenses/APL.txt.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
class Operation(Enum):
|
||||||
|
CONTAINS = "contains"
|
||||||
|
FIND = "find"
|
||||||
|
INSERT = "insert"
|
||||||
|
RANDOM = "random"
|
||||||
|
REMOVE = "remove"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_list(cls) -> List[str]:
|
||||||
|
return list(map(lambda c: c.value, cls))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get(s: str) -> Optional["Operation"]:
|
||||||
|
try:
|
||||||
|
return Operation[s.upper()]
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.value)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class BenchmarkRow:
|
||||||
|
name: str
|
||||||
|
datastructure: str
|
||||||
|
operation: Operation
|
||||||
|
real_time: int
|
||||||
|
cpu_time: int
|
||||||
|
iterations: int
|
||||||
|
time_unit: str
|
||||||
|
run_arg: Optional[Any]
|
||||||
|
|
||||||
|
|
||||||
|
class GoogleBenchmarkResult:
|
||||||
|
def __init__(self):
|
||||||
|
self._operation = None
|
||||||
|
self._datastructures: Dict[str, List[BenchmarkRow]] = dict()
|
||||||
|
|
||||||
|
def add_result(self, row: BenchmarkRow) -> None:
|
||||||
|
if self._operation is None:
|
||||||
|
self._operation = row.operation
|
||||||
|
assert self._operation is row.operation
|
||||||
|
if row.datastructure not in self._datastructures:
|
||||||
|
self._datastructures[row.datastructure] = [row]
|
||||||
|
else:
|
||||||
|
self._datastructures[row.datastructure].append(row)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def operation(self) -> Optional[Operation]:
|
||||||
|
return self._operation
|
||||||
|
|
||||||
|
@property
|
||||||
|
def datastructures(self) -> Dict[str, List[BenchmarkRow]]:
|
||||||
|
return self._datastructures
|
||||||
|
|
||||||
|
|
||||||
|
def get_operation(s: str) -> Operation:
|
||||||
|
for op in Operation.to_list():
|
||||||
|
if op.lower() in s.lower():
|
||||||
|
operation_enum = Operation.get(op)
|
||||||
|
if operation_enum is not None:
|
||||||
|
return operation_enum
|
||||||
|
else:
|
||||||
|
print("Operation not found!")
|
||||||
|
sys.exit(1)
|
||||||
|
print("Operation not found!")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_row_data(line: Dict[str, Any]) -> BenchmarkRow:
|
||||||
|
"""
|
||||||
|
Naming is very important, first must come an Operation name, and then a data
|
||||||
|
structure to test.
|
||||||
|
"""
|
||||||
|
full_name = line["name"].split("BM_Benchmark")[1]
|
||||||
|
name_with_run_arg = full_name.split("/")
|
||||||
|
operation = get_operation(name_with_run_arg[0])
|
||||||
|
datastructure = name_with_run_arg[0].split(operation.value.capitalize())[1]
|
||||||
|
|
||||||
|
run_arg = None
|
||||||
|
if len(name_with_run_arg) > 1:
|
||||||
|
run_arg = name_with_run_arg[1]
|
||||||
|
|
||||||
|
return BenchmarkRow(
|
||||||
|
name_with_run_arg[0],
|
||||||
|
datastructure,
|
||||||
|
operation,
|
||||||
|
line["real_time"],
|
||||||
|
line["cpu_time"],
|
||||||
|
line["iterations"],
|
||||||
|
line["time_unit"],
|
||||||
|
run_arg,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_benchmark_res(args) -> Optional[GoogleBenchmarkResult]:
|
||||||
|
file_path = Path(args.log_file)
|
||||||
|
if not file_path.exists():
|
||||||
|
print("Error file {file_path} not found!")
|
||||||
|
return None
|
||||||
|
with file_path.open("r") as file:
|
||||||
|
data = json.load(file)
|
||||||
|
res = GoogleBenchmarkResult()
|
||||||
|
assert "benchmarks" in data, "There must be a benchmark list inside"
|
||||||
|
for benchmark in data["benchmarks"]:
|
||||||
|
res.add_result(get_row_data(benchmark))
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def plot_operation(results: GoogleBenchmarkResult, save: bool) -> None:
|
||||||
|
colors = ["red", "green", "blue", "yellow", "purple", "brown"]
|
||||||
|
assert results.operation is not None
|
||||||
|
fig = plt.figure()
|
||||||
|
for ds, benchmarks in results.datastructures.items():
|
||||||
|
if benchmarks:
|
||||||
|
# Print line chart
|
||||||
|
x_axis = [elem.real_time for elem in benchmarks]
|
||||||
|
y_axis = [elem.run_arg for elem in benchmarks]
|
||||||
|
plt.plot(x_axis, y_axis, marker="", color=colors.pop(0), linewidth="2", label=f"{ds}")
|
||||||
|
plt.title(f"Benchmark results for operation {results.operation.value}")
|
||||||
|
plt.xlabel(f"Time [{benchmarks[0].time_unit}]")
|
||||||
|
plt.legend()
|
||||||
|
else:
|
||||||
|
print(f"Nothing to do for {ds}...")
|
||||||
|
if save:
|
||||||
|
plt.savefig(f"{results.operation.value}.png")
|
||||||
|
plt.close(fig)
|
||||||
|
else:
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser(description="Process benchmark results.")
|
||||||
|
parser.add_argument("--log_file", type=str)
|
||||||
|
parser.add_argument("--save", type=bool, default=True)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
res = get_benchmark_res(args)
|
||||||
|
if res is None:
|
||||||
|
print("Failed to get results from log file!")
|
||||||
|
sys.exit(1)
|
||||||
|
plot_operation(res, args.save)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
16
tools/plot/benchmark_datastructures.sh
Executable file
16
tools/plot/benchmark_datastructures.sh
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euox pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
WORKSPACE_DIR=${SCRIPT_DIR}/../../
|
||||||
|
|
||||||
|
BENCHMARK_FILES=$(find ${WORKSPACE_DIR}/tests/benchmark -type f -iname data_structures_*)
|
||||||
|
echo $BENCHMARK_FILES
|
||||||
|
for bench_file in ${BENCHMARK_FILES}; do
|
||||||
|
echo "Running $name"
|
||||||
|
base_name=$(basename $bench_file)
|
||||||
|
name=${base_name%%.*}
|
||||||
|
${WORKSPACE_DIR}/build/tests/benchmark/${name} --benchmark_format=json --benchmark_out=${name}_output.json
|
||||||
|
python3 ${WORKSPACE_DIR}/tools/plot/benchmark_datastructures.py --log-file=${name}_output.json
|
||||||
|
done
|
Loading…
Reference in New Issue
Block a user