From 825f672333d5e85c722abc5cea612d50212e49b0 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Mon, 9 Nov 2026 12:40:48 +0100 Subject: [PATCH] common: PMDK-656: remove benchmarks All benchmarks are deemed obsolete and a burden to maintain due to the use of C++ instead of C as the rest of this repository. Signed-off-by: Oksana Salyk --- .codecov.yml | 1 - .github/actions/pmem_benchmark_run/action.yml | 45 - .github/workflows/main.yml | 1 - .github/workflows/pmem_benchmark.yml | 112 -- .gitignore | 1 - CODING_STYLE.md | 2 +- CONTRIBUTING.md | 18 +- Makefile | 7 +- src/Makefile | 22 +- src/benchmarks/.gitignore | 3 - src/benchmarks/Makefile | 194 -- src/benchmarks/README | 19 - src/benchmarks/benchdiff | 156 -- src/benchmarks/benchmark.hpp | 325 ---- src/benchmarks/benchmark_empty.cpp | 91 - src/benchmarks/benchmark_time.cpp | 111 -- src/benchmarks/benchmark_time.hpp | 18 - src/benchmarks/benchmark_worker.cpp | 195 -- src/benchmarks/benchmark_worker.hpp | 67 - src/benchmarks/clo.cpp | 1024 ----------- src/benchmarks/clo.hpp | 18 - src/benchmarks/clo_vec.cpp | 250 --- src/benchmarks/clo_vec.hpp | 46 - src/benchmarks/config_reader.cpp | 280 --- src/benchmarks/config_reader.hpp | 12 - src/benchmarks/map_bench.cpp | 846 --------- src/benchmarks/obj_lanes.cpp | 132 -- src/benchmarks/obj_locks.cpp | 849 --------- src/benchmarks/obj_pmalloc.cpp | 504 ----- src/benchmarks/perf.cfg | 102 -- src/benchmarks/pmem_flush.cpp | 540 ------ src/benchmarks/pmem_memcpy.cpp | 613 ------- src/benchmarks/pmem_memset.cpp | 452 ----- src/benchmarks/pmembench.cpp | 1623 ----------------- src/benchmarks/pmembench_atomic_lists.cfg | 256 --- src/benchmarks/pmembench_flush.cfg | 63 - src/benchmarks/pmembench_map.cfg | 15 - src/benchmarks/pmembench_memcpy.cfg | 73 - src/benchmarks/pmembench_memset.cfg | 96 - src/benchmarks/pmembench_obj_gen.cfg | 58 - src/benchmarks/pmembench_obj_lanes.cfg | 9 - src/benchmarks/pmembench_obj_locks.cfg | 239 --- src/benchmarks/pmembench_obj_persist.cfg | 25 - src/benchmarks/pmembench_obj_pmalloc.cfg | 33 - src/benchmarks/pmembench_tx.cfg | 379 ---- src/benchmarks/pmembench_tx_add_range.cfg | 26 - src/benchmarks/pmemobj_atomic_lists.cpp | 1094 ----------- src/benchmarks/pmemobj_gen.cpp | 671 ------- src/benchmarks/pmemobj_persist.cpp | 271 --- src/benchmarks/pmemobj_tx.cpp | 1230 ------------- src/benchmarks/pmemobj_tx_add_range.cpp | 278 --- src/benchmarks/poolset_util.cpp | 93 - src/benchmarks/poolset_util.hpp | 17 - src/benchmarks/scenario.cpp | 197 -- src/benchmarks/scenario.hpp | 46 - src/common.inc | 17 +- src/examples/Makefile.inc | 5 +- src/test/Makefile | 5 +- src/test/tools/Makefile | 6 +- src/test/unittest/Makefile | 3 +- src/tools/Makefile | 6 +- utils/ansible/opensuse-setup.yml | 9 +- utils/ansible/rockylinux-setup.yml | 12 - utils/benchmarks/run_and_combine.py | 176 -- utils/check-area.sh | 2 +- utils/check-commit.sh | 3 +- .../docker/images/Dockerfile.opensuse-leap-15 | 6 +- utils/docker/images/Dockerfile.rockylinux-8 | 6 +- utils/docker/images/Dockerfile.rockylinux-9 | 6 +- utils/docker/images/Dockerfile.ubuntu-22.04 | 6 +- utils/style_check.sh | 92 +- 71 files changed, 38 insertions(+), 14170 deletions(-) delete mode 100644 .github/actions/pmem_benchmark_run/action.yml delete mode 100644 .github/workflows/pmem_benchmark.yml delete mode 100644 src/benchmarks/.gitignore delete mode 100644 src/benchmarks/Makefile delete mode 100644 src/benchmarks/README delete mode 100755 src/benchmarks/benchdiff delete mode 100644 src/benchmarks/benchmark.hpp delete mode 100644 src/benchmarks/benchmark_empty.cpp delete mode 100644 src/benchmarks/benchmark_time.cpp delete mode 100644 src/benchmarks/benchmark_time.hpp delete mode 100644 src/benchmarks/benchmark_worker.cpp delete mode 100644 src/benchmarks/benchmark_worker.hpp delete mode 100644 src/benchmarks/clo.cpp delete mode 100644 src/benchmarks/clo.hpp delete mode 100644 src/benchmarks/clo_vec.cpp delete mode 100644 src/benchmarks/clo_vec.hpp delete mode 100644 src/benchmarks/config_reader.cpp delete mode 100644 src/benchmarks/config_reader.hpp delete mode 100644 src/benchmarks/map_bench.cpp delete mode 100644 src/benchmarks/obj_lanes.cpp delete mode 100644 src/benchmarks/obj_locks.cpp delete mode 100644 src/benchmarks/obj_pmalloc.cpp delete mode 100644 src/benchmarks/perf.cfg delete mode 100644 src/benchmarks/pmem_flush.cpp delete mode 100644 src/benchmarks/pmem_memcpy.cpp delete mode 100644 src/benchmarks/pmem_memset.cpp delete mode 100644 src/benchmarks/pmembench.cpp delete mode 100644 src/benchmarks/pmembench_atomic_lists.cfg delete mode 100644 src/benchmarks/pmembench_flush.cfg delete mode 100644 src/benchmarks/pmembench_map.cfg delete mode 100644 src/benchmarks/pmembench_memcpy.cfg delete mode 100644 src/benchmarks/pmembench_memset.cfg delete mode 100644 src/benchmarks/pmembench_obj_gen.cfg delete mode 100644 src/benchmarks/pmembench_obj_lanes.cfg delete mode 100644 src/benchmarks/pmembench_obj_locks.cfg delete mode 100644 src/benchmarks/pmembench_obj_persist.cfg delete mode 100644 src/benchmarks/pmembench_obj_pmalloc.cfg delete mode 100644 src/benchmarks/pmembench_tx.cfg delete mode 100644 src/benchmarks/pmembench_tx_add_range.cfg delete mode 100644 src/benchmarks/pmemobj_atomic_lists.cpp delete mode 100644 src/benchmarks/pmemobj_gen.cpp delete mode 100644 src/benchmarks/pmemobj_persist.cpp delete mode 100644 src/benchmarks/pmemobj_tx.cpp delete mode 100644 src/benchmarks/pmemobj_tx_add_range.cpp delete mode 100644 src/benchmarks/poolset_util.cpp delete mode 100644 src/benchmarks/poolset_util.hpp delete mode 100644 src/benchmarks/scenario.cpp delete mode 100644 src/benchmarks/scenario.hpp delete mode 100755 utils/benchmarks/run_and_combine.py diff --git a/.codecov.yml b/.codecov.yml index 2a40b97fe5..c694255660 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,7 +1,6 @@ ignore: - '.*test.*' - '.*valgrind.*' - - '.*benchmarks.*' comment: layout: "diff" diff --git a/.github/actions/pmem_benchmark_run/action.yml b/.github/actions/pmem_benchmark_run/action.yml deleted file mode 100644 index 24e4e40d38..0000000000 --- a/.github/actions/pmem_benchmark_run/action.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: PMEM benchmark procedure -description: PMDK benchmarking procedure for self-hosted runners equipped with PMEM -inputs: - runtime_dir: - description: The root directory of the repository designated as runtime - required: true - reference_LIB_PATH: - description: LD_LIBRARY_PATH where the first version of PMDK is built - required: true - rival_LIB_PATH: - description: LD_LIBRARY_PATH where the second version of PMDK is built - required: true - config: - description: Name of the .cfg file to use - required: true - scenario: - description: Name of the scenario to run - required: true - pmem_path: - description: A PMEM-mounted directory to use - default: /mnt/pmem0 -runs: - using: composite - steps: - - name: Run the benchmark - working-directory: ${{ inputs.runtime_dir }} - shell: bash - run: >- - ./utils/benchmarks/run_and_combine.py - --reference ${{ inputs.reference_LIB_PATH }} --rival ${{ inputs.rival_LIB_PATH }} - --config ${{ inputs.config }} --scenario ${{ inputs.scenario }} - --pmem_path ${{ inputs.pmem_path }} - - - name: Archive logs - if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - with: - name: ${{ inputs.config }}__${{ inputs.scenario }} - path: '${{ inputs.runtime_dir }}/*.csv' - - - name: Remove logs - if: always() - working-directory: ${{ inputs.runtime_dir }} - shell: bash - run: rm -f *.csv diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8346e92f70..dc180a6ca4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,6 @@ jobs: - name: Install dependencies run: | sudo pip install flake8 - sudo apt-get install clang-format-14 - name: Check license id: check_license diff --git a/.github/workflows/pmem_benchmark.yml b/.github/workflows/pmem_benchmark.yml deleted file mode 100644 index 60ef37598d..0000000000 --- a/.github/workflows/pmem_benchmark.yml +++ /dev/null @@ -1,112 +0,0 @@ -name: PMEM Benchmark - -on: - workflow_dispatch: - inputs: - reference_ref: - type: string - default: stable-2.0 - rival_ref: - type: string - default: master - -permissions: {} - -jobs: - prep_runtime: - name: Prepare runtime - runs-on: [self-hosted, benchmark] - steps: - - name: Clone the git repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - fetch-depth: 1 - - - name: Build - run: make -j - - - prep_contesters: - name: Prepare ${{ matrix.ROLE }} (${{ matrix.GITHUB_REF }}) - runs-on: [self-hosted, benchmark] - needs: prep_runtime - strategy: - matrix: - include: - - ROLE: reference - GITHUB_REF: ${{ inputs.reference_ref }} - - ROLE: rival - GITHUB_REF: ${{ inputs.rival_ref }} - env: - MANIFEST: ${{ matrix.ROLE }}/manifest.txt - steps: - - name: Clone the git repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - ref: ${{ matrix.GITHUB_REF }} - fetch-depth: 1 - path: ${{ matrix.ROLE }} - - - name: Build - working-directory: ${{ matrix.ROLE }} - run: make -j - - - name: Write the manifest - run: | - echo "${{ matrix.GITHUB_REF }}" >> $MANIFEST - git -C ${{ matrix.ROLE }} rev-parse HEAD >> $MANIFEST - - - name: Archive the manifest - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - with: - name: manifest_${{ matrix.ROLE }} - path: ${{ env.MANIFEST }} - - - run: - name: Run perf.cfg ${{ matrix.SCENARIO }} - runs-on: [self-hosted, benchmark] - needs: prep_contesters - strategy: - matrix: - SCENARIO: - - obj_tx_alloc_small_v_thread - - obj_pmalloc_small_v_threads - - obj_rbtree_map_insert - - obj_hashmap_tx_map_insert - steps: - - name: Benchmark - uses: ./.github/actions/pmem_benchmark_run - with: - runtime_dir: ./ - reference_LIB_PATH: reference/src/nondebug - rival_LIB_PATH: rival/src/nondebug - config: perf - scenario: ${{ matrix.SCENARIO }} - - - repack: - name: Repack - runs-on: ubuntu-latest - needs: run - steps: - - name: Download all artifacts - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - path: csvs - - - name: Combine the manifests - env: - OUTPUT: csvs/manifest.txt - run: | - for competitor in reference rival; do - echo "$competitor:" >> $OUTPUT - cat csvs/manifest_$competitor/manifest.txt >> $OUTPUT - echo >> $OUTPUT - done - - - name: Upload all as a single artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - with: - name: perf__all__${{ github.run_id }} - path: csvs/**/* diff --git a/.gitignore b/.gitignore index ddf2b3e64b..1de8834230 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ !.github !.gitignore !.gitattributes -!.clang-format !.mailmap !.codecov.yml !.pre-commit-config.yml diff --git a/CODING_STYLE.md b/CODING_STYLE.md index fb7e6f19b7..849cb9a576 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -94,7 +94,7 @@ conventions for git commit messages: the short summary. - Valid area names are: **pmem**, **pmem2**, **obj**, **set**, **test**, **doc**, **daxio**, **pmreorder**, **pool** (for *libpmempool* and *pmempool*), - **benchmark**, **examples**, **core** and **common** (for everything else). + **examples**, **core** and **common** (for everything else). - It is acceptable for the short summary to be the only thing in the commit message if it is a trivial change. Otherwise, the second line must be a blank line. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e3dc753a0a..a0e50cce48 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,21 +61,9 @@ Before contributing please remember to run: $ make cstyle ``` -This will check all C/C++ files in the tree for style issues. To check C++ -files you have to have clang-format version 14.0, otherwise they will be -skipped. If you want to run this target automatically at build time, you can -pass CSTYLEON=1 to make. If you want cstyle to be run, but not fail the build, -pass CSTYLEON=2 to make. -There is also a target for automatic C++ code formatting, to do this run: -``` - $ make format -``` - -There are cases, when you might have several clang-format-X.Y binaries and either -no clang-format or it pointing to an older version. In such case run: -``` - $ make CLANG_FORMAT=/path/to/clang-format cstyle|format -``` +This will check all C and Python files in the tree for style issues. If you want to +run this target automatically at build time, you can pass CSTYLEON=1 to make. +If you want cstyle to be run, but not fail the build, pass CSTYLEON=2 to make. ### Bug Reports diff --git a/Makefile b/Makefile index abe5927b9e..40b728272d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2014-2023, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Makefile -- top-level Makefile for PMDK @@ -80,10 +81,6 @@ cstyle: check-commits check-whitespace check-license $(MAKE) -C src $@ $(MAKE) -C utils $@ -format: - $(MAKE) -C src $@ - @echo Done. - check-whitespace: @echo Checking files for whitespace issues... @utils/check_whitespace -g @@ -129,5 +126,5 @@ ifeq ($(DOC),y) endif .PHONY: all clean clobber test check cstyle check-license install uninstall\ - source rpm dpkg pkg-clean pcheck format doc\ + source rpm dpkg pkg-clean pcheck doc\ $(SUBDIRS) diff --git a/src/Makefile b/src/Makefile index 154ebe2468..5ef1907b66 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2014-2023, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # src/Makefile -- Makefile for PMDK @@ -14,7 +15,7 @@ TARGETS = libpmem libpmemobj libpmempool tools libpmem2 ALL_TARGETS = $(TARGETS) common core # all available targets POSSIBLE_TARGETS = $(TARGETS) common core test\ - examples benchmarks + examples SCOPE_DIRS = $(TARGETS) common core @@ -26,11 +27,6 @@ ifneq ($(BUILD_EXAMPLES),n) RELEASE_TARGETS += examples endif -ifneq ($(BUILD_BENCHMARKS),n) - ALL_TARGETS += benchmarks - RELEASE_TARGETS += benchmarks -endif - CLEAN_TARGETS = $(POSSIBLE_TARGETS) CLOBBER_TARGETS = $(POSSIBLE_TARGETS) CSTYLE_TARGETS = $(POSSIBLE_TARGETS) @@ -90,16 +86,14 @@ uninstall: $(INSTALL_TARGETS:=-uninstall) clean: $(CLEAN_TARGETS:=-clean) clobber: $(CLOBBER_TARGETS:=-clobber) cstyle: $(CSTYLE_TARGETS:=-cstyle) -format: $(CSTYLE_TARGETS:=-format) -examples benchmarks: $(EXAMPLES_TARGETS) -benchmarks: examples +examples: $(EXAMPLES_TARGETS) sparse: $(SPARSE_TARGETS:=-sparse) custom_build = $(DEBUG)$(OBJDIR) tools: libpmem libpmemobj libpmempool libpmempool libpmemobj: libpmem -benchmarks test tools: common core +test tools: common core pkg-cfg-common: @printf "version=%s\nlibdir=%s\nprefix=%s\nrasdeps=%s\n" "$(SRCVERSION)" "$(libdir)" "$(prefix)" "$(LIBNDCTL_PKG_CONFIG_DEPS_VAR)" > $(PKG_CONFIG_COMMON) @@ -121,7 +115,6 @@ $(eval $(call sub-target,$(INSTALL_TARGETS),uninstall,y)) $(eval $(call sub-target,$(CLEAN_TARGETS),clean,y)) $(eval $(call sub-target,$(CLOBBER_TARGETS),clobber,y)) $(eval $(call sub-target,$(CSTYLE_TARGETS),cstyle,n)) -$(eval $(call sub-target,$(CSTYLE_TARGETS),format,n)) $(eval $(call sub-target,$(SPARSE_TARGETS),sparse,n)) $(DEBUG_RELEASE_TARGETS): @@ -177,12 +170,9 @@ uninstall: $(RM) $(PMREORDER_BIN)/pmreorder cstyle: - $(STYLE_CHECK) check $(HEADERS) + $(STYLE_CHECK) $(HEADERS) $(CHECK_SHEBANG) $(SCRIPTS) -format: - $(STYLE_CHECK) format $(HEADERS) - cscope: cscope -q -b $(SCOPEFILES) ctags -e $(SCOPEFILES) @@ -194,6 +184,6 @@ clean: clean-here clobber: clean-here -.PHONY: all install uninstall clean clobber cstyle format test check pcheck\ +.PHONY: all install uninstall clean clobber cstyle test check pcheck\ cscope $(ALL_TARGETS)\ pkg-config clean-here pkg-cfg-common diff --git a/src/benchmarks/.gitignore b/src/benchmarks/.gitignore deleted file mode 100644 index 965464d926..0000000000 --- a/src/benchmarks/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -pmembench -*.csv -testfile.* diff --git a/src/benchmarks/Makefile b/src/benchmarks/Makefile deleted file mode 100644 index 81691ccc76..0000000000 --- a/src/benchmarks/Makefile +++ /dev/null @@ -1,194 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2014-2024, Intel Corporation - -# -# src/benchmarks/Makefile -- build all benchmarks -# -TOP := $(dir $(lastword $(MAKEFILE_LIST)))../.. - -include $(TOP)/src/common.inc - -vpath %.c $(TOP)/src/examples/libpmemobj/tree_map -vpath %.c $(TOP)/src/examples/libpmemobj/map -vpath %.c $(TOP)/src/examples/libpmemobj/hashmap - -vpath %.c $(TOP)/src/libpmemobj -vpath %.c $(TOP)/src/common -vpath %.c $(TOP)/src/libpmempool - -BENCHMARK = pmembench - -GLIB:= $(call check_package, glib-2.0) -ifeq ($(GLIB),y) -TARGET = $(BENCHMARK) -else -$(info NOTE: Skipping pmembench because glib-2.0 is missing \ --- see src/benchmarks/README for details.) -endif - -all: $(TARGET) - -SRC=pmembench.cpp\ - benchmark_time.cpp\ - benchmark_worker.cpp\ - clo.cpp\ - clo_vec.cpp\ - config_reader.cpp\ - scenario.cpp\ - pmem_memset.cpp\ - pmem_memcpy.cpp\ - pmem_flush.cpp\ - pmemobj_gen.cpp\ - pmemobj_persist.cpp\ - obj_pmalloc.cpp\ - obj_locks.cpp\ - obj_lanes.cpp\ - map_bench.cpp\ - pmemobj_tx.cpp\ - pmemobj_atomic_lists.cpp\ - poolset_util.cpp\ - benchmark_empty.cpp\ - pmemobj_tx_add_range.cpp - -# Configuration file without the .cfg extension -CONFIGS=pmembench_memset\ - pmembench_memcpy\ - pmembench_flush\ - pmembench_obj_pmalloc\ - pmembench_obj_persist\ - pmembench_obj_gen\ - pmembench_obj_locks\ - pmembench_obj_lanes\ - pmembench_map\ - pmembench_tx\ - pmembench_atomic_lists - -OBJS=$(SRC:.cpp=.o) -ifneq ($(filter 1 2, $(CSTYLEON)),) -TMP_HEADERS := $(addsuffix tmp, $(HEADERS)) -endif -LDFLAGS = -L$(LIBS_PATH) $(OS_LIBS) -LDFLAGS += -L../examples/libpmemobj/map -LDFLAGS += $(EXTRA_LDFLAGS) -ifeq ($(DEBUG),) -LIBS += ../nondebug/libpmemcore.a -LIBS += ../nondebug/libpmemcommon.a -else -LIBS += ../debug/libpmemcore.a -LIBS += ../debug/libpmemcommon.a -endif -CFLAGS += $(LIBNDCTL_CFLAGS) -LIBS += -lpmemobj -lpmempool -lpmem -pthread -lm \ - $(LIBDL) $(LIBUUID) $(LIBNDCTL_LIBS) -ifeq ($(LIBRT_NEEDED), y) -LIBS += -lrt -endif - -CXXFLAGS = -Wall -CXXFLAGS += -Werror -CXXFLAGS += -std=c++11 -CXXFLAGS += -Wno-invalid-offsetof -CXXFLAGS += -Wpointer-arith -CXXFLAGS += -Wunused-macros -CXXFLAGS += -pthread -CXXFLAGS += -I../include -CXXFLAGS += -I../libpmemobj -CXXFLAGS += -I../common -CXXFLAGS += -I../core -CXXFLAGS += -I../examples/libpmemobj/map -CXXFLAGS += $(OS_INCS) -CXXFLAGS += -DSRCVERSION='"$(SRCVERSION)"' - -ifeq ($(OS_DIMM),ndctl) -CXXFLAGS += -DSDS_ENABLED -endif - -ifeq ($(COVERAGE),1) -CXXFLAGS += $(GCOV_CFLAGS) -LDFLAGS += $(GCOV_LDFLAGS) -LIBS += $(GCOV_LIBS) -endif - -ifeq ($(VALGRIND),0) -CFLAGS += -DVALGRIND_ENABLED=0 -CXXFLAGS += -DVALGRIND_ENABLED=0 -endif - -ifneq ($(SANITIZE),) -CXXFLAGS += -fsanitize=$(SANITIZE) -LDFLAGS += -fsanitize=$(SANITIZE) -endif - -ifeq ($(GLIB),y) -CXXFLAGS += $(shell $(PKG_CONFIG) --cflags glib-2.0) -LIBS += $(shell $(PKG_CONFIG) --libs glib-2.0) -endif - -LIBMAP_DIR=../examples/libpmemobj/map -LIBMAP=$(LIBMAP_DIR)/libmap.a - -OBJS += pmemobj.o - -ifeq ($(DEBUG),) -CXXFLAGS += -O3 -LIBS_PATH=../nondebug -else -CXXFLAGS += -ggdb -LIBS_PATH=../debug -endif - -GLIB_TEST_PROG="\#include \nint main(){return 0;}" -GLIB_SILENCE := $(shell printf $(GLIB_TEST_PROG) |\ - $(CXX) $(CXXFLAGS) -x c -o /dev/null - 2>/dev/null && echo n || echo y) - -ifeq ($(GLIB_SILENCE), y) -CXXFLAGS += -Wno-unknown-attributes -endif - -CXXFLAGS += $(EXTRA_CXXFLAGS) - -objdir=. - -%.o: %.cpp Makefile - $(call check-cstyle, $<) - @mkdir -p .deps - $(CXX) -MD -c -o $@ $(CXXFLAGS) $(call coverage-path, $<) - $(call check-os, $@, $<) - $(create-deps) - -%.htmp: %.h - $(call check-cstyle, $<, $@) - -%.hpptmp: %.hpp - $(call check-cstyle, $<, $@) - -$(BENCHMARK): $(TMP_HEADERS) $(OBJS) $(LIBMAP) - $(CXX) -o $@ $(LDFLAGS) $(OBJS) $(LIBMAP) $(LIBS) - -$(LIBMAP): - $(MAKE) -C $(LIBMAP_DIR) map - -clean: - $(RM) $(OBJS) $(TMP_HEADERS) - $(RM) *.csv - -clobber: clean - $(RM) $(BENCHMARK) - $(RM) *.csv - $(RM) -r .deps - -$(CONFIGS): - LD_LIBRARY_PATH=$(LIBS_PATH) ./$(BENCHMARK) $@.cfg > $@.csv - -run: $(BENCHMARK) $(CONFIGS) - -sparse: - -.PHONY: all clean clobber run $(CONFIGS) - -PMEMOBJ_SYMBOLS=pmalloc pfree lane_hold lane_release - -pmemobj.o: $(LIBS_PATH)/libpmemobj/libpmemobj_unscoped.o - $(OBJCOPY) --localize-hidden $(addprefix -G, $(PMEMOBJ_SYMBOLS)) $< $@ - --include .deps/*.P diff --git a/src/benchmarks/README b/src/benchmarks/README deleted file mode 100644 index 56510c917f..0000000000 --- a/src/benchmarks/README +++ /dev/null @@ -1,19 +0,0 @@ -Persistent Memory Development Kit - -This is benchmarks/README. - -This directory contains benchmarks for Persistent Memory Development Kit. - -Benchmarks may be built and run from this directory using: - $ make - $ make run - -See how to run benchmarks manually using: - $ LD_LIBRARY_PATH=../nondebug ./pmembench --help - -** DEPENDENCIES: ** -In order to build benchmarks you need to install glib-2.0 development -package. - -rpm-based systems : glibX-devel (where X is the API/ABI version) -dpkg-based systems: libglibX-dev (where X is the API/ABI version) diff --git a/src/benchmarks/benchdiff b/src/benchmarks/benchdiff deleted file mode 100755 index 26f914782e..0000000000 --- a/src/benchmarks/benchdiff +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/perl -w -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018, Intel Corporation - - -# A simple tool to compare the results of two benchmarks. -# Results assume a terminal, you can also install "colorized-logs" then pipe -# through ansi2txt or ansi2html. -# -# Numbers which improved are in green (bright if > 2×), ones which worsened -# in red, white means same (within 5%). Fields in light gray don't have an -# assigned direction. -# -# This tool needs to be taught which fields go up and which go down; -# please update the table below accordingly. -use Term::ANSIColor; - -# +1 means "more is better" -my %dir=( - "total-avg[sec]" => -1, - "ops-per-second[1/sec]" => +1, - "total-max[sec]" => -1, - "total-min[sec]" => -1, - "total-median[sec]" => -1, - "total-std-dev[sec]" => -1, - "latency-avg[nsec]" => -1, - "latency-min[nsec]" => -1, - "latency-max[nsec]" => -1, - "latency-std-dev[nsec]" => -1, - "latency-pctl-50.0%[nsec]" => -1, - "latency-pctl-99.0%[nsec]" => -1, - "latency-pctl-99.9%[nsec]" => -1, - "threads" => 0, - "ops-per-thread" => 0, - "data-size" => 0, - "seed" => 0, - "repeats" => 0, - "thread-affinity" => 0, - "main-affinity" => 0, - "min-exe-time" => 0, - "type-number" => 0, - "min-size" => 0, - "one-pool" => 0, - "one-object" => 0, - "operation" => 0, - "lib" => 0, - "nestings" => 0, # ? - "position" => 0, - "list-len" => 0, - "queue" => 0, - "no-warmup" => 0, - "mode" => 0, - "file-size" => 0, - "random" => 0, - "file-io" => 0, - "vector" => 0, - "src-offset" => 0, - "dest-offset" => 0, - "src-mode" => 0, - "dest-mode" => 0, - "libc-memcpy" => 0, - "persist" => 0, - "bandwidth[MiB/s]" => +1, - "mem-mode" => 0, - "memset" => 0, - "msync" => 0, - "objects" => 0, - "use_system_threads" => 0, - "numlocks" => 0, - "run_id" => 0, - "run_id_init_val" => 0, - "bench_type" => 0, - "rdlock" => 0, - "min-rsize" => 0, - "realloc-size" => 0, - "changed-type" => 0, - "stdlib-alloc" => 0, - "pool-per-thread" => 0, - "alloc-min" => 0, - "realloc-min" => 0, - "mix-thread" => 0, -); -my %head_colors = ( - +1 => color('green'), - -1 => color('red'), - 0 => "", -); -my %arrows = ( - +1 => "↑", - -1 => "↓", - 0 => "", -); - -scalar @ARGV==2 or die "Usage: benchdiff \n"; -open FA, "<", "$ARGV[0]" or die "Can't open 「$ARGV[0]」: $!\n"; -open FB, "<", "$ARGV[1]" or die "Can't open 「$ARGV[1]」: $!\n"; - -my ($A, $B, @head); -while (defined($A = )) { - defined ($B = ) or die "Benchmarks have unequal length!\n"; - - chomp $A; - chomp $B; - my @A = split /;/, $A; - my @B = split /;/, $B; - - $#A == $#B or die "Different # of fields: 「$A」 vs 「$B」\n"; - - unless ($#A) { - $A eq $B or die "Title/error differs: 「$A」 vs 「$B」\n"; - print colored("$A\n", "bright_cyan"); - next; - } - - if ($A[0] eq 'total-avg[sec]') { - $A eq $B or die "Header differs: 「$A」 vs 「$B」\n"; - @head = @A; - print join(colored(";", 'bright_black'), - map { "$_$head_colors{$dir{$_}//0}$arrows{$dir{$_}//0}" - . color('reset') } @head), "\n"; - next; - } - - for (0..$#head) { - print colored(";", 'bright_black') if $_; - my ($a, $b, $dir) = ($A[$_], $B[$_], $dir{$head[$_]}); - - unless (defined $dir) { - print STDERR colored("Unknown direction for 「" . $head[$_] - . "」\n", 'bright_red'); - $dir = $dir{$head[$_]} = 0; - } - - if ($dir) { - if (1.0 * ($dir > 0 ? $a : $b)) { - my $d = $dir > 0 ? $b / $a : $a / $b; - print $d < 0.5 ? color('bright_red') - : $d < 0.95 ? color('red') - : $d < 1/0.95 ? color('bright_white') - : $d < 2 ? color('green') - : color('bright_green'); - printf "%1.2f".color('reset'), $d; - } else { - # 0 or non-numeric -> non-zero - print $a eq $b ? $a : colored("$a↔$b", 'on_magenta'); - } - } else { - # All fields without a known direction are assumed to stay - # constant, warn if they're not. - print $a eq $b ? $a - : colored($a, 'bright_red on_magenta') . "↔" - . colored($b, 'bright_green on_magenta'); - } - } - print "\n"; -} diff --git a/src/benchmarks/benchmark.hpp b/src/benchmarks/benchmark.hpp deleted file mode 100644 index 27eb13c8b7..0000000000 --- a/src/benchmarks/benchmark.hpp +++ /dev/null @@ -1,325 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ - -/* - * benchmark.hpp -- This file contains interface for creating benchmarks to the - * pmembench framework. The _most_ important data structure is - * struct benchmark_info which should be properly filled and registered by the - * benchmark. Some fields should be filled by meta-data and information about - * the benchmark like: name, brief description, supported operation modes etc. - * The other group of fields are function callbacks which may be implemented by - * the benchmark. Some callbacks are required, others are optional. This is - * indicated in the structure description. - * - * To register a benchmark you can use the special macro - * REGISTER_BENCHMARK() which takes static benchmark_info data structure as an - * argument. You can also use the pmembench_register() function. Please note - * that registering a benchmark should be done at initialization time. You can - * achieve this by specifying pmembench_init macro in function attributes: - * - * static void pmembench_init my_benchmark_init() - * { - * pmembench_register(&my_benchmark); - * } - * - * However using the REGISTER_BENCHMARK() macro is recommended. - */ -#ifndef _BENCHMARK_H -#define _BENCHMARK_H - -#include -#include -#include -#include -#include - -#include "benchmark_time.hpp" -#include "os.h" -#include "rand.h" -#include "util.h" - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#endif -#define RRAND(max, min) (rand() % ((max) - (min)) + (min)) -#define RRAND_R(rng, max, min) (rnd64_r(rng) % ((max) - (min)) + (min)) - -struct benchmark; - -/* - * benchmark_args - Arguments for benchmark. - * - * It contains set of common arguments and pointer to benchmark's specific - * arguments which are automatically processed by framework according to - * clos, nclos and opt_size in benchmark_info structure. - */ -struct benchmark_args { - const char *fname; /* path to test file */ - size_t fsize; /* size of test file */ - bool is_poolset; /* test file is a poolset */ - bool is_dynamic_poolset; /* test file is directory in which - benchmark creates reusable files */ - mode_t fmode; /* test file's permissions */ - unsigned n_threads; /* number of working threads */ - size_t n_ops_per_thread; /* number of operations per thread */ - bool thread_affinity; /* set worker threads CPU affinity mask */ - ssize_t main_affinity; /* main thread affinity */ - char *affinity_list; /* set CPU affinity order */ - size_t dsize; /* data size */ - unsigned seed; /* PRNG seed */ - unsigned repeats; /* number of repeats of one scenario */ - unsigned min_exe_time; /* minimal execution time */ - bool help; /* print help for benchmark */ - void *opts; /* benchmark specific arguments */ -}; - -/* - * benchmark_results - Benchmark's execution results. - */ -struct benchmark_results { - uint64_t nbytes; /* number of bytes processed */ - uint64_t nops; /* number of operations executed */ - benchmark_time_t time; /* total execution time */ -}; - -/* - * struct results -- statistics for total measurements - */ -struct results { - double min; - double max; - double avg; - double std_dev; - double med; -}; - -/* - * struct latency -- statistics for latency measurements - */ -struct latency { - uint64_t max; - uint64_t min; - uint64_t avg; - double std_dev; - uint64_t pctl50_0p; - uint64_t pctl99_0p; - uint64_t pctl99_9p; -}; - -/* - * struct thread_results -- results of a single thread - */ -struct thread_results { - benchmark_time_t beg; - benchmark_time_t end; - benchmark_time_t end_op[]; -}; - -/* - * struct bench_results -- results of the whole benchmark - */ -struct bench_results { - struct thread_results **thres; -}; - -/* - * struct total_results -- results and statistics of the whole benchmark - */ -struct total_results { - size_t nrepeats; - size_t nthreads; - size_t nops; - double nopsps; - struct results total; - struct latency latency; - struct bench_results *res; -}; - -/* - * Command Line Option integer value base. - */ -#define CLO_INT_BASE_NONE 0x0 -#define CLO_INT_BASE_DEC 0x1 -#define CLO_INT_BASE_HEX 0x2 -#define CLO_INT_BASE_OCT 0x4 - -/* - * Command Line Option type. - */ -enum clo_type { - CLO_TYPE_FLAG, - CLO_TYPE_STR, - CLO_TYPE_INT, - CLO_TYPE_UINT, - - CLO_TYPE_MAX, -}; - -/* - * Description of command line option. - * - * This structure is used to declare command line options by the benchmark - * which will be automatically parsed by the framework. - * - * opt_short : Short option char. If there is no short option write 0. - * opt_long : Long option string. - * descr : Description of command line option. - * off : Offset in data structure in which the value should be stored. - * type : Type of command line option. - * def : Default value. If set to NULL, this options is required. - * ignore_in_res: Do not print in results. - * check : Optional callback for checking the command line option value. - * type_int : Parameters for signed integer. - * type_uint : Parameters for unsigned integer. - * type_str : Parameters for string. - * - * size : Size of integer value. Valid values: 1, 2, 4, 8. - * base : Integer base system from which the parsing should be - * performed. This field may be used as bit mask by logically - * adding different base types. - * limit_min : Indicates whether value should be limited by the minimum - * value. - * limit_max : Indicates whether value should be limited by the maximum - * value. - * min : Minimum value when limit_min is set. - * max : Maximum value when limit_min is set. - * - * alloc : If set to true the framework should allocate memory for the - * value. The memory will be freed by the framework at the end of - * execution. Otherwise benchmark must provide valid pointer in - * opt_var and max_size parameter must be set properly. - * max_size : Maximum size of string. - */ -struct benchmark_clo { - int opt_short; - const char *opt_long; - enum clo_type type; - const char *descr; - size_t off; - const char *def; - bool ignore_in_res; - struct { - size_t size; - int base; - int64_t min; - int64_t max; - } type_int; - struct { - size_t size; - int base; - uint64_t min; - uint64_t max; - } type_uint; - int used; -}; - -#define clo_field_offset(s, f) ((size_t) & ((s *)0)->f) -#define clo_field_size(s, f) (sizeof(((s *)0)->f)) - -/* - * worker_info - Worker thread's information structure. - */ -struct worker_info { - size_t index; /* index of worker thread */ - struct operation_info *opinfo; /* operation info structure */ - size_t nops; /* number of operations */ - void *priv; /* worker's private data */ - benchmark_time_t beg; /* start time */ - benchmark_time_t end; /* end time */ -}; - -/* - * operation_info - Information about operation. - */ -struct operation_info { - struct worker_info *worker; /* worker's info */ - struct benchmark_args *args; /* benchmark arguments */ - size_t index; /* operation's index */ - benchmark_time_t end; /* operation's end time */ -}; - -/* - * struct benchmark_info -- benchmark descriptor - * name : Name of benchmark. - * brief : Brief description of benchmark. - * clos : Command line options which will be automatically parsed by - * framework. - * nclos : Number of command line options. - * opts_size : Size of data structure where the parsed values should be - * stored in. - * print_help : Callback for printing help message. - * pre_init : Function for initialization of the benchmark before parsing - * command line arguments. - * init : Function for initialization of the benchmark after parsing - * command line arguments. - * exit : Function for de-initialization of the benchmark. - * multithread : Indicates whether the benchmark operation function may be - * run in many threads. - * multiops : Indicates whether the benchmark operation function may be - * run many time in a loop. - * measure_time : Indicates whether the benchmark framework should measure the - * execution time of operation function. If set to false, the - * benchmark must report the execution time by itself. - * init_worker : Callback for initialization thread specific data. Invoked in - * the worker thread but globally serialized. - * operation : Callback function which does the main job of benchmark. - * rm_file : Indicates whether the test file should be removed by - * framework before the init function will be called. - * allow_poolset: Indicates whether benchmark may use poolset files. - * If set to false and fname points to a poolset, an error - * will be returned. - * According to multithread and single_operation flags it may be - * invoked in different ways: - * +-------------+----------+-------------------------------------+ - * | multithread | multiops | description | - * +-------------+----------+-------------------------------------+ - * | false | false | invoked once, in one thread | - * +-------------+----------+-------------------------------------+ - * | false | true | invoked many times, in one thread | - * +-------------+----------+-------------------------------------+ - * | true | false | invoked once, in many threads | - * +-------------+----------+-------------------------------------+ - * | true | true | invoked many times, in many threads | - * +-------------+----------+-------------------------------------+ - * - */ -struct benchmark_info { - const char *name; - const char *brief; - struct benchmark_clo *clos; - size_t nclos; - size_t opts_size; - void (*print_help)(struct benchmark *bench); - int (*pre_init)(struct benchmark *bench); - int (*init)(struct benchmark *bench, struct benchmark_args *args); - int (*exit)(struct benchmark *bench, struct benchmark_args *args); - int (*init_worker)(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker); - void (*free_worker)(struct benchmark *bench, - struct benchmark_args *args, - struct worker_info *worker); - int (*operation)(struct benchmark *bench, struct operation_info *info); - void (*print_extra_headers)(); - void (*print_extra_values)(struct benchmark *bench, - struct benchmark_args *args, - struct total_results *res); - bool multithread; - bool multiops; - bool measure_time; - bool rm_file; - bool allow_poolset; - bool print_bandwidth; -}; - -void *pmembench_get_priv(struct benchmark *bench); -void pmembench_set_priv(struct benchmark *bench, void *priv); -struct benchmark_info *pmembench_get_info(struct benchmark *bench); -int pmembench_register(struct benchmark_info *bench_info); - -#define REGISTER_BENCHMARK(bench) \ - if (pmembench_register(&(bench))) { \ - fprintf(stderr, "Unable to register benchmark '%s'\n", \ - (bench).name); \ - } - -#endif /* _BENCHMARK_H */ diff --git a/src/benchmarks/benchmark_empty.cpp b/src/benchmarks/benchmark_empty.cpp deleted file mode 100644 index 77d1b764aa..0000000000 --- a/src/benchmarks/benchmark_empty.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019, Intel Corporation */ - -/* - * benchmark_empty.cpp -- empty template for benchmarks - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" - -/* - * prog_args -- benchmark specific command line options - */ -struct prog_args { - int my_value; -}; - -/* - * obj_bench -- benchmark context - */ -struct obj_bench { - struct prog_args *pa; /* prog_args structure */ -}; - -/* - * benchmark_empty_op -- actual benchmark operation - */ -static int -benchmark_empty_op(struct benchmark *bench, struct operation_info *info) -{ - return 0; -} - -/* - * benchmark_empty_init -- initialization function - */ -static int -benchmark_empty_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - return 0; -} - -/* - * benchmark_empty_exit -- benchmark cleanup function - */ -static int -benchmark_empty_exit(struct benchmark *bench, struct benchmark_args *args) -{ - return 0; -} - -static struct benchmark_clo benchmark_empty_clo[0]; - -/* Stores information about benchmark. */ -static struct benchmark_info benchmark_empty_info; -CONSTRUCTOR(benchmark_empty_constructor) -void -benchmark_empty_constructor(void) -{ - benchmark_empty_info.name = "benchmark_empty"; - benchmark_empty_info.brief = "Benchmark for benchmark_empty() " - "operation"; - benchmark_empty_info.init = benchmark_empty_init; - benchmark_empty_info.exit = benchmark_empty_exit; - benchmark_empty_info.multithread = true; - benchmark_empty_info.multiops = true; - benchmark_empty_info.operation = benchmark_empty_op; - benchmark_empty_info.measure_time = true; - benchmark_empty_info.clos = benchmark_empty_clo; - benchmark_empty_info.nclos = ARRAY_SIZE(benchmark_empty_clo); - benchmark_empty_info.opts_size = sizeof(struct prog_args); - benchmark_empty_info.rm_file = true; - benchmark_empty_info.allow_poolset = true; - REGISTER_BENCHMARK(benchmark_empty_info); -}; diff --git a/src/benchmarks/benchmark_time.cpp b/src/benchmarks/benchmark_time.cpp deleted file mode 100644 index 7fdf2bf0fb..0000000000 --- a/src/benchmarks/benchmark_time.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2017, Intel Corporation */ - -/* - * benchmark_time.cpp -- benchmark_time module definitions - */ -#include "benchmark_time.hpp" -#include "os.h" -#include -#include -#include -#include -#define NSECPSEC 1000000000 - -/* - * benchmark_time_get -- get timestamp from clock source - */ -void -benchmark_time_get(benchmark_time_t *time) -{ - os_clock_gettime(CLOCK_MONOTONIC, time); -} - -/* - * benchmark_time_diff -- get time interval - */ -void -benchmark_time_diff(benchmark_time_t *d, benchmark_time_t *t1, - benchmark_time_t *t2) -{ - long long nsecs = (t2->tv_sec - t1->tv_sec) * NSECPSEC + t2->tv_nsec - - t1->tv_nsec; - assert(nsecs >= 0); - d->tv_sec = nsecs / NSECPSEC; - d->tv_nsec = nsecs % NSECPSEC; -} - -/* - * benchmark_time_get_secs -- get total number of seconds - */ -double -benchmark_time_get_secs(benchmark_time_t *t) -{ - return (double)t->tv_sec + (double)t->tv_nsec / NSECPSEC; -} - -/* - * benchmark_time_get_nsecs -- get total number of nanoseconds - */ -unsigned long long -benchmark_time_get_nsecs(benchmark_time_t *t) -{ - unsigned long long ret = t->tv_nsec; - - ret += t->tv_sec * NSECPSEC; - - return ret; -} - -/* - * benchmark_time_compare -- compare two moments in time - */ -int -benchmark_time_compare(const benchmark_time_t *t1, const benchmark_time_t *t2) -{ - if (t1->tv_sec == t2->tv_sec) - return (int)((long long)t1->tv_nsec - (long long)t2->tv_nsec); - else - return (int)((long long)t1->tv_sec - (long long)t2->tv_sec); -} - -/* - * benchmark_time_set -- set time using number of nanoseconds - */ -void -benchmark_time_set(benchmark_time_t *time, unsigned long long nsecs) -{ - time->tv_sec = nsecs / NSECPSEC; - time->tv_nsec = nsecs % NSECPSEC; -} - -/* - * number of samples used to calculate average time required to get a current - * time from the system - */ -#define N_PROBES_GET_TIME 10000000UL - -/* - * benchmark_get_avg_get_time -- calculates average time required to get the - * current time from the system in nanoseconds - */ -unsigned long long -benchmark_get_avg_get_time(void) -{ - benchmark_time_t time; - benchmark_time_t start; - benchmark_time_t stop; - - benchmark_time_get(&start); - for (size_t i = 0; i < N_PROBES_GET_TIME; i++) { - benchmark_time_get(&time); - } - benchmark_time_get(&stop); - - benchmark_time_diff(&time, &start, &stop); - - unsigned long long avg = - benchmark_time_get_nsecs(&time) / N_PROBES_GET_TIME; - - return avg; -} diff --git a/src/benchmarks/benchmark_time.hpp b/src/benchmarks/benchmark_time.hpp deleted file mode 100644 index 75d9fbb99a..0000000000 --- a/src/benchmarks/benchmark_time.hpp +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ -/* - * benchmark_time.hpp -- declarations of benchmark_time module - */ -#include - -typedef struct timespec benchmark_time_t; - -void benchmark_time_get(benchmark_time_t *time); -void benchmark_time_diff(benchmark_time_t *d, benchmark_time_t *t1, - benchmark_time_t *t2); -double benchmark_time_get_secs(benchmark_time_t *t); -unsigned long long benchmark_time_get_nsecs(benchmark_time_t *t); -int benchmark_time_compare(const benchmark_time_t *t1, - const benchmark_time_t *t2); -void benchmark_time_set(benchmark_time_t *time, unsigned long long nsecs); -unsigned long long benchmark_get_avg_get_time(void); diff --git a/src/benchmarks/benchmark_worker.cpp b/src/benchmarks/benchmark_worker.cpp deleted file mode 100644 index 8ffe0a41ef..0000000000 --- a/src/benchmarks/benchmark_worker.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2019, Intel Corporation */ -/* - * benchmark_worker.cpp -- benchmark_worker module definitions - */ - -#include -#include - -#include "benchmark_worker.hpp" -#include "sys_util.h" - -/* - * worker_state_wait_for_transition -- wait for transition from and to - * specified states - */ -static void -worker_state_wait_for_transition(struct benchmark_worker *worker, - enum benchmark_worker_state state, - enum benchmark_worker_state new_state) -{ - while (worker->state == state) - os_cond_wait(&worker->cond, &worker->lock); - assert(worker->state == new_state); -} - -/* - * worker_state_transition -- change worker state from and to specified states - */ -static void -worker_state_transition(struct benchmark_worker *worker, - enum benchmark_worker_state old_state, - enum benchmark_worker_state new_state) -{ - assert(worker->state == old_state); - worker->state = new_state; - os_cond_signal(&worker->cond); -} - -/* - * thread_func -- (internal) callback for os_thread - */ -static void * -thread_func(void *arg) -{ - assert(arg != nullptr); - auto *worker = (struct benchmark_worker *)arg; - - util_mutex_lock(&worker->lock); - - worker_state_wait_for_transition(worker, WORKER_STATE_IDLE, - WORKER_STATE_INIT); - - if (worker->init) - worker->ret_init = worker->init(worker->bench, worker->args, - &worker->info); - - worker_state_transition(worker, WORKER_STATE_INIT, - WORKER_STATE_INITIALIZED); - - if (worker->ret_init) { - util_mutex_unlock(&worker->lock); - return nullptr; - } - - worker_state_wait_for_transition(worker, WORKER_STATE_INITIALIZED, - WORKER_STATE_RUN); - - worker->ret = worker->func(worker->bench, &worker->info); - - worker_state_transition(worker, WORKER_STATE_RUN, WORKER_STATE_END); - - worker_state_wait_for_transition(worker, WORKER_STATE_END, - WORKER_STATE_EXIT); - - if (worker->exit) - worker->exit(worker->bench, worker->args, &worker->info); - - worker_state_transition(worker, WORKER_STATE_EXIT, WORKER_STATE_DONE); - - util_mutex_unlock(&worker->lock); - return nullptr; -} - -/* - * benchmark_worker_alloc -- allocate benchmark worker - */ -struct benchmark_worker * -benchmark_worker_alloc(void) -{ - struct benchmark_worker *w = - (struct benchmark_worker *)calloc(1, sizeof(*w)); - - if (!w) - return nullptr; - - util_mutex_init(&w->lock); - - if (os_cond_init(&w->cond)) - goto err_destroy_mutex; - - if (os_thread_create(&w->thread, nullptr, thread_func, w)) - goto err_destroy_cond; - - return w; - -err_destroy_cond: - os_cond_destroy(&w->cond); -err_destroy_mutex: - util_mutex_destroy(&w->lock); - free(w); - return nullptr; -} - -/* - * benchmark_worker_free -- release benchmark worker - */ -void -benchmark_worker_free(struct benchmark_worker *w) -{ - os_thread_join(&w->thread, nullptr); - os_cond_destroy(&w->cond); - util_mutex_destroy(&w->lock); - free(w); -} - -/* - * benchmark_worker_init -- call init function for worker - */ -int -benchmark_worker_init(struct benchmark_worker *worker) -{ - util_mutex_lock(&worker->lock); - - worker_state_transition(worker, WORKER_STATE_IDLE, WORKER_STATE_INIT); - - worker_state_wait_for_transition(worker, WORKER_STATE_INIT, - WORKER_STATE_INITIALIZED); - - int ret = worker->ret_init; - - util_mutex_unlock(&worker->lock); - - return ret; -} - -/* - * benchmark_worker_exit -- call exit function for worker - */ -void -benchmark_worker_exit(struct benchmark_worker *worker) -{ - util_mutex_lock(&worker->lock); - - worker_state_transition(worker, WORKER_STATE_END, WORKER_STATE_EXIT); - - worker_state_wait_for_transition(worker, WORKER_STATE_EXIT, - WORKER_STATE_DONE); - - util_mutex_unlock(&worker->lock); -} - -/* - * benchmark_worker_run -- run benchmark worker - */ -int -benchmark_worker_run(struct benchmark_worker *worker) -{ - int ret = 0; - - util_mutex_lock(&worker->lock); - - worker_state_transition(worker, WORKER_STATE_INITIALIZED, - WORKER_STATE_RUN); - - util_mutex_unlock(&worker->lock); - - return ret; -} - -/* - * benchmark_worker_join -- join benchmark worker - */ -int -benchmark_worker_join(struct benchmark_worker *worker) -{ - util_mutex_lock(&worker->lock); - - worker_state_wait_for_transition(worker, WORKER_STATE_RUN, - WORKER_STATE_END); - - util_mutex_unlock(&worker->lock); - - return 0; -} diff --git a/src/benchmarks/benchmark_worker.hpp b/src/benchmarks/benchmark_worker.hpp deleted file mode 100644 index d431035676..0000000000 --- a/src/benchmarks/benchmark_worker.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ -/* - * benchmark_worker.hpp -- benchmark_worker module declarations - */ - -#include "benchmark.hpp" -#include "os_thread.h" -/* - * - * The following table shows valid state transitions upon specified - * API calls and operations performed by the worker thread: - * - * +========================+==========================+=============+ - * | Application | State | Worker | - * +========================+==========================+=============+ - * | benchmark_worker_alloc | WORKER_STATE_IDLE | wait | - * +------------------------+--------------------------+-------------+ - * | benchmark_worker_init | WORKER_STATE_INIT | invoke init | - * +------------------------+--------------------------+-------------+ - * | wait | WORKER_STATE_INITIALIZED | end of init | - * +------------------------+--------------------------+-------------+ - * | benchmark_worker_run | WORKER_STATE_RUN | invoke func | - * +------------------------+--------------------------+-------------+ - * | benchmark_worker_join | WORKER_STATE_END | end of func | - * +------------------------+--------------------------+-------------+ - * | benchmark_worker_exit | WORKER_STATE_EXIT | invoke exit | - * +------------------------+--------------------------+-------------+ - * | wait | WORKER_STATE_DONE | end of exit | - * +------------------------+--------------------------+-------------+ - */ -enum benchmark_worker_state { - WORKER_STATE_IDLE, - WORKER_STATE_INIT, - WORKER_STATE_INITIALIZED, - WORKER_STATE_RUN, - WORKER_STATE_END, - WORKER_STATE_EXIT, - WORKER_STATE_DONE, - - MAX_WORKER_STATE, -}; - -struct benchmark_worker { - os_thread_t thread; - struct benchmark *bench; - struct benchmark_args *args; - struct worker_info info; - int ret; - int ret_init; - int (*func)(struct benchmark *bench, struct worker_info *info); - int (*init)(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *info); - void (*exit)(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *info); - os_cond_t cond; - os_mutex_t lock; - enum benchmark_worker_state state; -}; - -struct benchmark_worker *benchmark_worker_alloc(void); -void benchmark_worker_free(struct benchmark_worker *); - -int benchmark_worker_init(struct benchmark_worker *); -void benchmark_worker_exit(struct benchmark_worker *); -int benchmark_worker_run(struct benchmark_worker *); -int benchmark_worker_join(struct benchmark_worker *); diff --git a/src/benchmarks/clo.cpp b/src/benchmarks/clo.cpp deleted file mode 100644 index 8c782a7c98..0000000000 --- a/src/benchmarks/clo.cpp +++ /dev/null @@ -1,1024 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ -/* - * clo.cpp -- command line options module definitions - */ -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "clo.hpp" -#include "clo_vec.hpp" -#include "queue.h" -#include "scenario.hpp" - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -typedef int (*clo_parse_fn)(struct benchmark_clo *clo, const char *arg, - struct clo_vec *clovec); - -typedef int (*clo_parse_single_fn)(struct benchmark_clo *clo, const char *arg, - void *ptr); - -typedef int (*clo_eval_range_fn)(struct benchmark_clo *clo, void *first, - void *step, void *last, char type, - struct clo_vec_vlist *vlist); - -typedef const char *(*clo_str_fn)(struct benchmark_clo *clo, void *addr, - size_t size); - -#define STR_BUFF_SIZE 1024 -static char str_buff[STR_BUFF_SIZE]; - -/* - * clo_parse_flag -- (internal) parse flag - */ -static int -clo_parse_flag(struct benchmark_clo *clo, const char *arg, - struct clo_vec *clovec) -{ - bool flag = true; - if (arg != nullptr) { - if (strcmp(arg, "true") == 0) - flag = true; - else if (strcmp(arg, "false") == 0) - flag = false; - else - return -1; - } - - return clo_vec_memcpy(clovec, clo->off, sizeof(flag), &flag); -} - -/* - * clo_parse_str -- (internal) parse string value - */ -static int -clo_parse_str(struct benchmark_clo *clo, const char *arg, - struct clo_vec *clovec) -{ - struct clo_vec_vlist *vlist = clo_vec_vlist_alloc(); - assert(vlist != nullptr); - - char *str = strdup(arg); - assert(str != nullptr); - clo_vec_add_alloc(clovec, str); - - char *next = strtok(str, ","); - while (next) { - clo_vec_vlist_add(vlist, &next, sizeof(next)); - next = strtok(nullptr, ","); - } - - int ret = clo_vec_memcpy_list(clovec, clo->off, sizeof(str), vlist); - - clo_vec_vlist_free(vlist); - - return ret; -} - -/* - * is_oct -- check if string may be octal number - */ -static int -is_oct(const char *arg, size_t len) -{ - return (arg[0] == '0' || (len > 1 && arg[0] == '-' && arg[1] == '0')); -} - -/* - * is_hex -- check if string may be hexadecimal number - */ -static int -is_hex(const char *arg, size_t len) -{ - if (arg[0] == '-') { - arg++; - len--; - } - - return (len > 2 && arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')); -} - -/* - * parse_number_base -- parse string as integer of given sign and base - */ -static int -parse_number_base(const char *arg, void *value, int s, int base) -{ - char *end; - errno = 0; - if (s) { - auto *v = (int64_t *)value; - *v = strtoll(arg, &end, base); - } else { - auto *v = (uint64_t *)value; - *v = strtoull(arg, &end, base); - } - - if (errno || *end != '\0') - return -1; - return 0; -} - -/* - * parse_number -- parse string as integer of given sign and allowed bases - */ -static int -parse_number(const char *arg, size_t len, void *value, int s, int base) -{ - if ((base & CLO_INT_BASE_HEX) && is_hex(arg, len)) { - if (!parse_number_base(arg, value, s, 16)) - return 0; - } - - if ((base & CLO_INT_BASE_OCT) && is_oct(arg, len)) { - if (!parse_number_base(arg, value, s, 8)) - return 0; - } - - if (base & CLO_INT_BASE_DEC) { - if (!parse_number_base(arg, value, s, 10)) - return 0; - } - - return -1; -} - -/* - * clo_parse_single_int -- (internal) parse single int value - */ -static int -clo_parse_single_int(struct benchmark_clo *clo, const char *arg, void *ptr) -{ - int64_t value = 0; - size_t len = strlen(arg); - - if (parse_number(arg, len, &value, 1, clo->type_int.base)) { - errno = EINVAL; - return -1; - } - - int64_t tmax = ((int64_t)1 << (8 * clo->type_int.size - 1)) - 1; - int64_t tmin = -((int64_t)1 << (8 * clo->type_int.size - 1)); - - tmax = min(tmax, clo->type_int.max); - tmin = max(tmin, clo->type_int.min); - - if (value > tmax || value < tmin) { - errno = ERANGE; - return -1; - } - - memcpy(ptr, &value, clo->type_int.size); - return 0; -} - -/* - * clo_parse_single_uint -- (internal) parse single uint value - */ -static int -clo_parse_single_uint(struct benchmark_clo *clo, const char *arg, void *ptr) -{ - if (arg[0] == '-') { - errno = EINVAL; - return -1; - } - - uint64_t value = 0; - size_t len = strlen(arg); - - if (parse_number(arg, len, &value, 0, clo->type_uint.base)) { - errno = EINVAL; - return -1; - } - - uint64_t tmax = ~0ULL >> (64 - 8 * clo->type_uint.size); - uint64_t tmin = 0; - - tmax = min(tmax, clo->type_uint.max); - tmin = max(tmin, clo->type_uint.min); - - if (value > tmax || value < tmin) { - errno = ERANGE; - return -1; - } - - memcpy(ptr, &value, clo->type_uint.size); - return 0; -} - -/* - * clo_eval_range_uint -- (internal) evaluate range for uint values - */ -static int -clo_eval_range_uint(struct benchmark_clo *clo, void *first, void *step, - void *last, char type, struct clo_vec_vlist *vlist) -{ - uint64_t curr = *(uint64_t *)first; - uint64_t l = *(uint64_t *)last; - int64_t s = *(int64_t *)step; - - while (1) { - clo_vec_vlist_add(vlist, &curr, clo->type_uint.size); - - switch (type) { - case '+': - curr += s; - if (curr > l) - return 0; - break; - case '-': - if (curr < (uint64_t)s) - return 0; - curr -= s; - if (curr < l) - return 0; - break; - case '*': - curr *= s; - if (curr > l) - return 0; - break; - case '/': - curr /= s; - if (curr < l) - return 0; - break; - default: - return -1; - } - } - - return -1; -} - -/* - * clo_eval_range_int -- (internal) evaluate range for int values - */ -static int -clo_eval_range_int(struct benchmark_clo *clo, void *first, void *step, - void *last, char type, struct clo_vec_vlist *vlist) -{ - int64_t curr = *(int64_t *)first; - int64_t l = *(int64_t *)last; - uint64_t s = *(uint64_t *)step; - - while (1) { - clo_vec_vlist_add(vlist, &curr, clo->type_int.size); - - switch (type) { - case '+': - curr += s; - if (curr > l) - return 0; - break; - case '-': - curr -= s; - if (curr < l) - return 0; - break; - case '*': - curr *= s; - if (curr > l) - return 0; - break; - case '/': - curr /= s; - if (curr < l) - return 0; - break; - default: - return -1; - } - } - - return -1; -} - -/* - * clo_check_range_params -- (internal) validate step and step type - */ -static int -clo_check_range_params(uint64_t step, char step_type) -{ - switch (step_type) { - /* - * Cannot construct range with step equal to 0 - * for '+' or '-' range. - */ - case '+': - case '-': - if (step == 0) - return -1; - break; - /* - * Cannot construct range with step equal to 0 or 1 - * for '*' or '/' range. - */ - case '*': - case '/': - if (step == 0 || step == 1) - return -1; - break; - default: - return -1; - } - - return 0; -} - -/* - * clo_parse_range -- (internal) parse range or value - * - * The range may be in the following format: - * :: - * - * Step type must be one of the following: +, -, *, /. - */ -static int -clo_parse_range(struct benchmark_clo *clo, const char *arg, - clo_parse_single_fn parse_single, clo_eval_range_fn eval_range, - struct clo_vec_vlist *vlist) -{ - auto *str_first = (char *)malloc(strlen(arg) + 1); - assert(str_first != nullptr); - auto *str_step = (char *)malloc(strlen(arg) + 1); - assert(str_step != nullptr); - char step_type = '\0'; - auto *str_last = (char *)malloc(strlen(arg) + 1); - assert(str_last != nullptr); - - int ret = sscanf(arg, "%[^:]:%c%[^:]:%[^:]", str_first, &step_type, - str_step, str_last); - if (ret == 1) { - /* single value */ - uint64_t value; - - if (parse_single(clo, arg, &value)) { - ret = -1; - } else { - if (clo->type == CLO_TYPE_UINT) - clo_vec_vlist_add(vlist, &value, - clo->type_uint.size); - else - clo_vec_vlist_add(vlist, &value, - clo->type_int.size); - - ret = 0; - } - } else if (ret == 4) { - /* range */ - uint64_t first = 0; - uint64_t last = 0; - uint64_t step = 0; - - if (parse_single(clo, str_first, &first)) { - ret = -1; - goto out; - } - - char *end; - errno = 0; - step = strtoull(str_step, &end, 10); - if (errno || !end || *end != '\0') { - ret = -1; - goto out; - } - - if (parse_single(clo, str_last, &last)) { - ret = -1; - goto out; - } - - if (clo_check_range_params(step, step_type)) { - ret = -1; - goto out; - } - - /* evaluate the range */ - if (eval_range(clo, &first, &step, &last, step_type, vlist)) { - ret = -1; - goto out; - } - - ret = 0; - } else { - ret = -1; - } - -out: - free(str_first); - free(str_step); - free(str_last); - - return ret; -} - -/* - * clo_parse_ranges -- (internal) parse ranges/values separated by commas - */ -static int -clo_parse_ranges(struct benchmark_clo *clo, const char *arg, - struct clo_vec *clovec, clo_parse_single_fn parse_single, - clo_eval_range_fn eval_range) -{ - struct clo_vec_vlist *vlist = clo_vec_vlist_alloc(); - assert(vlist != nullptr); - - int ret = 0; - char *args = strdup(arg); - assert(args != nullptr); - - char *curr = args; - char *next; - - /* iterate through all values separated by comma */ - while ((next = strchr(curr, ',')) != nullptr) { - *next = '\0'; - next++; - - /* parse each comma separated value as range or single value */ - if ((ret = clo_parse_range(clo, curr, parse_single, eval_range, - vlist))) - goto out; - - curr = next; - } - - /* parse each comma separated value as range or single value */ - if ((ret = clo_parse_range(clo, curr, parse_single, eval_range, vlist))) - goto out; - - /* add list of values to CLO vector */ - if (clo->type == CLO_TYPE_UINT) - ret = clo_vec_memcpy_list(clovec, clo->off, clo->type_uint.size, - vlist); - else - ret = clo_vec_memcpy_list(clovec, clo->off, clo->type_int.size, - vlist); - -out: - free(args); - clo_vec_vlist_free(vlist); - - return ret; -} - -/* - * clo_parse_int -- (internal) parse int value - */ -static int -clo_parse_int(struct benchmark_clo *clo, const char *arg, - struct clo_vec *clovec) -{ - return clo_parse_ranges(clo, arg, clovec, clo_parse_single_int, - clo_eval_range_int); -} - -/* - * clo_parse_uint -- (internal) parse uint value - */ -static int -clo_parse_uint(struct benchmark_clo *clo, const char *arg, - struct clo_vec *clovec) -{ - return clo_parse_ranges(clo, arg, clovec, clo_parse_single_uint, - clo_eval_range_uint); -} - -/* - * clo_str_flag -- (internal) convert flag value to string - */ -static const char * -clo_str_flag(struct benchmark_clo *clo, void *addr, size_t size) -{ - if (clo->off + sizeof(bool) > size) - return nullptr; - - bool flag = *(bool *)((char *)addr + clo->off); - - return flag ? "true" : "false"; -} - -/* - * clo_str_str -- (internal) convert str value to string - */ -static const char * -clo_str_str(struct benchmark_clo *clo, void *addr, size_t size) -{ - if (clo->off + sizeof(char *) > size) - return nullptr; - - return *(char **)((char *)addr + clo->off); -} - -/* - * clo_str_int -- (internal) convert int value to string - */ -static const char * -clo_str_int(struct benchmark_clo *clo, void *addr, size_t size) -{ - if (clo->off + clo->type_int.size > size) - return nullptr; - - void *val = (char *)addr + clo->off; - - int ret = 0; - switch (clo->type_int.size) { - case 1: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRId8, - *(int8_t *)val); - break; - case 2: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRId16, - *(int16_t *)val); - break; - case 4: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRId32, - *(int32_t *)val); - break; - case 8: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRId64, - *(int64_t *)val); - break; - default: - return nullptr; - } - if (ret < 0) - return nullptr; - - return str_buff; -} - -/* - * clo_str_uint -- (internal) convert uint value to string - */ -static const char * -clo_str_uint(struct benchmark_clo *clo, void *addr, size_t size) -{ - if (clo->off + clo->type_uint.size > size) - return nullptr; - - void *val = (char *)addr + clo->off; - - int ret = 0; - switch (clo->type_uint.size) { - case 1: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRIu8, - *(uint8_t *)val); - break; - case 2: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRIu16, - *(uint16_t *)val); - break; - case 4: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRIu32, - *(uint32_t *)val); - break; - case 8: - ret = util_snprintf(str_buff, STR_BUFF_SIZE, "%" PRIu64, - *(uint64_t *)val); - break; - default: - return nullptr; - } - if (ret < 0) - return nullptr; - - return str_buff; -} - -/* - * clo_parse -- (internal) array with functions for parsing CLOs - */ -static clo_parse_fn clo_parse[CLO_TYPE_MAX] = { - /* [CLO_TYPE_FLAG] = */ clo_parse_flag, - /* [CLO_TYPE_STR] = */ clo_parse_str, - /* [CLO_TYPE_INT] = */ clo_parse_int, - /* [CLO_TYPE_UINT] = */ clo_parse_uint, -}; - -/* - * clo_str -- (internal) array with functions for converting to string - */ -static clo_str_fn clo_str[CLO_TYPE_MAX] = { - /* [CLO_TYPE_FLAG] = */ clo_str_flag, - /* [CLO_TYPE_STR] = */ clo_str_str, - /* [CLO_TYPE_INT] = */ clo_str_int, - /* [CLO_TYPE_UINT] = */ clo_str_uint, -}; - -/* - * clo_get_by_short -- (internal) return CLO with specified short opt - */ -static struct benchmark_clo * -clo_get_by_short(struct benchmark_clo *clos, size_t nclo, char opt_short) -{ - size_t i; - - for (i = 0; i < nclo; i++) { - if (clos[i].opt_short == opt_short) - return &clos[i]; - } - - return nullptr; -} - -/* - * clo_get_by_long -- (internal) return CLO with specified long opt - */ -static struct benchmark_clo * -clo_get_by_long(struct benchmark_clo *clos, size_t nclo, const char *opt_long) -{ - size_t i; - - for (i = 0; i < nclo; i++) { - if (strcmp(clos[i].opt_long, opt_long) == 0) - return &clos[i]; - } - - return nullptr; -} - -/* - * clo_get_optstr -- (internal) returns option string from CLOs - * - * This function returns option string which contains all short - * options from CLO structure. - * The returned value must be freed by caller. - */ -static char * -clo_get_optstr(struct benchmark_clo *clos, size_t nclo) -{ - size_t i; - char *optstr; - char *ptr; - /* - * In worst case every option requires an argument - * so we need space for ':' character + terminating - * NULL. - */ - size_t optstrlen = nclo * 2 + 1; - - optstr = (char *)calloc(1, optstrlen); - assert(optstr != nullptr); - - ptr = optstr; - for (i = 0; i < nclo; i++) { - if (clos[i].opt_short) { - *(ptr++) = clos[i].opt_short; - if (clos[i].type != CLO_TYPE_FLAG) - *(ptr++) = ':'; - } - } - - return optstr; -} - -/* - * clo_get_long_options -- (internal) allocate long options structure - * - * This function allocates structure for long options and fills all - * entries according to values from becnhmark_clo. This is essentially - * conversion from struct benchmark_clo to struct option. - * The returned value must be freed by caller. - */ -static struct option * -clo_get_long_options(struct benchmark_clo *clos, size_t nclo) -{ - size_t i; - struct option *options; - - options = (struct option *)calloc(nclo + 1, sizeof(struct option)); - assert(options != nullptr); - - for (i = 0; i < nclo; i++) { - options[i].name = clos[i].opt_long; - options[i].val = clos[i].opt_short; - /* no optional arguments */ - if (clos[i].type == CLO_TYPE_FLAG) { - options[i].has_arg = no_argument; - } else { - options[i].has_arg = required_argument; - } - } - - return options; -} - -/* - * clo_set_defaults -- (internal) set default values - * - * Default values are stored as strings in CLO - * structure so this function parses default values in - * the same manner as values passed by user. Returns -1 - * if argument was not passed by user and default value - * is missing. - */ -static int -clo_set_defaults(struct benchmark_clo *clos, size_t nclo, - struct clo_vec *clovec) -{ - size_t i; - - for (i = 0; i < nclo; i++) { - - if (clos[i].used) - continue; - /* - * If option was not used and default value - * is not specified, return error. Otherwise - * parse the default value in the same way as - * values passed by user. Except for the flag. - * If the flag default value was not specified - * assign "false" value to it. - */ - if (clos[i].def) { - if (clo_parse[clos[i].type](&clos[i], clos[i].def, - clovec)) - return -1; - } else if (clos[i].type == CLO_TYPE_FLAG) { - if (clo_parse[clos[i].type](&clos[i], "false", clovec)) - return -1; - } else { - printf("'%s' is required option\n", clos[i].opt_long); - return -1; - } - } - - return 0; -} - -/* - * benchmark_clo_parse -- parse CLOs and store values in desired structure - * - * This function parses command line arguments according to information - * from CLOs structure. The parsed values are stored in CLO vector - * pointed by clovec. If any of command line options are not passed by user, - * the default value is stored if exists. Otherwise it means the argument is - * required and error is returned. - * - * - argc - number of command line options passed by user - * - argv - command line options passed by user - * - clos - description of available command line options - * - nclos - number of available command line options - * - clovec - vector of arguments - */ -int -benchmark_clo_parse(int argc, char *argv[], struct benchmark_clo *clos, - ssize_t nclos, struct clo_vec *clovec) -{ - char *optstr; - struct option *options; - int ret = 0; - int opt; - int optindex; - - /* convert CLOs to option string and long options structure */ - optstr = clo_get_optstr(clos, nclos); - options = clo_get_long_options(clos, nclos); - - /* parse CLOs as long and/or short options */ - while ((opt = getopt_long(argc, argv, optstr, options, &optindex)) != - -1) { - struct benchmark_clo *clo = nullptr; - if (opt) { - clo = clo_get_by_short(clos, nclos, opt); - } else { - assert(optindex < nclos); - clo = &clos[optindex]; - } - if (!clo) { - ret = -1; - goto out; - } - - /* invoke parser according to type of CLO */ - assert(clo->type < CLO_TYPE_MAX); - ret = clo_parse[clo->type](clo, optarg, clovec); - if (ret) - goto out; - - /* mark CLO as used */ - clo->used = optarg != nullptr || clo->type == CLO_TYPE_FLAG; - } - - if (optind < argc) { - fprintf(stderr, "Unknown option: %s\n", argv[optind]); - ret = -1; - goto out; - } - /* parse unused CLOs with default values */ - ret = clo_set_defaults(clos, nclos, clovec); - -out: - free(options); - free(optstr); - - if (ret) - errno = EINVAL; - - return ret; -} - -/* - * benchmark_clo_parse_scenario -- parse CLOs from scenario - * - * This function parses command line arguments according to information - * from CLOs structure. The parsed values are stored in CLO vector - * pointed by clovec. If any of command line options are not passed by user, - * the default value is stored if exists. Otherwise it means the argument is - * required and error is returned. - * - * - scenario - scenario with key value arguments - * - clos - description of available command line options - * - nclos - number of available command line options - * - clovec - vector of arguments - */ -int -benchmark_clo_parse_scenario(struct scenario *scenario, - struct benchmark_clo *clos, size_t nclos, - struct clo_vec *clovec) -{ - struct kv *kv; - - FOREACH_KV(kv, scenario) - { - struct benchmark_clo *clo = - clo_get_by_long(clos, nclos, kv->key); - if (!clo) { - fprintf(stderr, "unrecognized option -- '%s'\n", - kv->key); - return -1; - } - - assert(clo->type < CLO_TYPE_MAX); - if (clo_parse[clo->type](clo, kv->value, clovec)) { - fprintf(stderr, "parsing option -- '%s' failed\n", - kv->value); - return -1; - } - - /* mark CLO as used */ - clo->used = 1; - } - - return clo_set_defaults(clos, nclos, clovec); -} - -/* - * benchmark_override_clos_in_scenario - parse the command line arguments and - * override/add the parameters in/to the scenario by replacing/adding the kv - * struct in/to the scenario. - * - * - scenario - scenario with key value arguments - * - argc - command line arguments number - * - argv - command line arguments vector - * - clos - description of available command line options - * - nclos - number of available command line options - */ -int -benchmark_override_clos_in_scenario(struct scenario *scenario, int argc, - char *argv[], struct benchmark_clo *clos, - int nclos) -{ - char *optstr; - struct option *options; - int ret = 0; - int opt; - int optindex; - const char *true_str = "true"; - - /* convert CLOs to option string and long options structure */ - optstr = clo_get_optstr(clos, nclos); - options = clo_get_long_options(clos, nclos); - - /* parse CLOs as long and/or short options */ - while ((opt = getopt_long(argc, argv, optstr, options, &optindex)) != - -1) { - struct benchmark_clo *clo = nullptr; - if (opt) { - clo = clo_get_by_short(clos, nclos, opt); - } else { - assert(optindex < nclos); - clo = &clos[optindex]; - } - if (!clo) { - ret = -1; - goto out; - } - - /* Check if the given clo is defined in the scenario */ - struct kv *kv = find_kv_in_scenario(clo->opt_long, scenario); - if (kv) { /* replace the value in the scenario */ - if (optarg != nullptr && clo->type != CLO_TYPE_FLAG) { - free(kv->value); - kv->value = strdup(optarg); - } else if (optarg == nullptr && - clo->type == CLO_TYPE_FLAG) { - free(kv->value); - kv->value = strdup(true_str); - } else { - ret = -1; - goto out; - } - } else { /* add a new param to the scenario */ - if (optarg != nullptr && clo->type != CLO_TYPE_FLAG) { - kv = kv_alloc(clo->opt_long, optarg); - PMDK_TAILQ_INSERT_TAIL(&scenario->head, kv, - next); - } else if (optarg == nullptr && - clo->type == CLO_TYPE_FLAG) { - kv = kv_alloc(clo->opt_long, true_str); - PMDK_TAILQ_INSERT_TAIL(&scenario->head, kv, - next); - } else { - ret = -1; - goto out; - } - } - } - - if (optind < argc) { - fprintf(stderr, "Unknown option: %s\n", argv[optind]); - ret = -1; - goto out; - } - -out: - free(options); - free(optstr); - - if (ret) - errno = EINVAL; - - return ret; -} - -/* - * benchmark_clo_str -- converts command line option to string - * - * According to command line option type and parameters, converts - * the value from structure pointed by args of size size. - */ -const char * -benchmark_clo_str(struct benchmark_clo *clo, void *args, size_t size) -{ - assert(clo->type < CLO_TYPE_MAX); - return clo_str[clo->type](clo, args, size); -} - -/* - * clo_get_scenarios - search the command line arguments for scenarios listed in - * available_scenarios and put them in found_scenarios. Returns the number of - * found scenarios in the cmd line or -1 on error. The passed cmd line - * args should contain the scenario name(s) as the first argument(s) - starting - * from index 0 - */ -int -clo_get_scenarios(int argc, char *argv[], struct scenarios *available_scenarios, - struct scenarios *found_scenarios) -{ - assert(argv != nullptr); - assert(available_scenarios != nullptr); - assert(found_scenarios != nullptr); - - if (argc <= 0) { - fprintf(stderr, "clo get scenarios, argc invalid value: %d\n", - argc); - return -1; - } - int tmp_argc = argc; - char **tmp_argv = argv; - - do { - struct scenario *scenario = - scenarios_get_scenario(available_scenarios, *tmp_argv); - - if (!scenario) { - fprintf(stderr, "unknown scenario: %s\n", *tmp_argv); - return -1; - } - - struct scenario *new_scenario = clone_scenario(scenario); - assert(new_scenario != nullptr); - - PMDK_TAILQ_INSERT_TAIL(&found_scenarios->head, new_scenario, - next); - tmp_argc--; - tmp_argv++; - } while (tmp_argc && - contains_scenarios(tmp_argc, tmp_argv, available_scenarios)); - - return argc - tmp_argc; -} diff --git a/src/benchmarks/clo.hpp b/src/benchmarks/clo.hpp deleted file mode 100644 index a246f840d6..0000000000 --- a/src/benchmarks/clo.hpp +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ -/* - * clo.hpp -- command line options module declarations - */ -int benchmark_clo_parse(int argc, char *argv[], struct benchmark_clo *clos, - ssize_t nclo, struct clo_vec *clovec); -int benchmark_clo_parse_scenario(struct scenario *scenario, - struct benchmark_clo *clos, size_t nclo, - struct clo_vec *clovec); -const char *benchmark_clo_str(struct benchmark_clo *clo, void *args, - size_t size); -int clo_get_scenarios(int argc, char *argv[], - struct scenarios *available_scenarios, - struct scenarios *found_scenarios); -int benchmark_override_clos_in_scenario(struct scenario *scenario, int argc, - char *argv[], - struct benchmark_clo *clos, int nclos); diff --git a/src/benchmarks/clo_vec.cpp b/src/benchmarks/clo_vec.cpp deleted file mode 100644 index ffe245f231..0000000000 --- a/src/benchmarks/clo_vec.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2019, Intel Corporation */ -/* - * clo_vec.cpp -- command line options vector definitions - */ -#include -#include -#include - -#include "clo_vec.hpp" - -/* - * clo_vec_alloc -- allocate new CLO vector - */ -struct clo_vec * -clo_vec_alloc(size_t size) -{ - struct clo_vec *clovec = (struct clo_vec *)malloc(sizeof(*clovec)); - assert(clovec != nullptr); - - /* init list of arguments and allocations */ - PMDK_TAILQ_INIT(&clovec->allocs); - PMDK_TAILQ_INIT(&clovec->args); - - clovec->nallocs = 0; - - /* size of each struct */ - clovec->size = size; - - /* add first struct to list */ - struct clo_vec_args *args = - (struct clo_vec_args *)malloc(sizeof(*args)); - - assert(args != nullptr); - - args->args = calloc(1, size); - assert(args->args != nullptr); - - PMDK_TAILQ_INSERT_TAIL(&clovec->args, args, next); - - clovec->nargs = 1; - - return clovec; -} - -/* - * clo_vec_free -- free CLO vector and all allocations - */ -void -clo_vec_free(struct clo_vec *clovec) -{ - assert(clovec != nullptr); - - /* free all allocations */ - while (!PMDK_TAILQ_EMPTY(&clovec->allocs)) { - struct clo_vec_alloc *alloc = PMDK_TAILQ_FIRST(&clovec->allocs); - PMDK_TAILQ_REMOVE(&clovec->allocs, alloc, next); - free(alloc->ptr); - free(alloc); - } - - /* free all arguments */ - while (!PMDK_TAILQ_EMPTY(&clovec->args)) { - struct clo_vec_args *args = PMDK_TAILQ_FIRST(&clovec->args); - PMDK_TAILQ_REMOVE(&clovec->args, args, next); - free(args->args); - free(args); - } - - free(clovec); -} - -/* - * clo_vec_get_args -- return pointer to CLO arguments at specified index - */ -void * -clo_vec_get_args(struct clo_vec *clovec, size_t i) -{ - if (i >= clovec->nargs) - return nullptr; - size_t c = 0; - struct clo_vec_args *args; - PMDK_TAILQ_FOREACH(args, &clovec->args, next) - { - if (c == i) - return args->args; - c++; - } - - return nullptr; -} - -/* - * clo_vec_add_alloc -- add allocation to CLO vector - */ -int -clo_vec_add_alloc(struct clo_vec *clovec, void *ptr) -{ - struct clo_vec_alloc *alloc = - (struct clo_vec_alloc *)malloc(sizeof(*alloc)); - - assert(alloc != nullptr); - - alloc->ptr = ptr; - PMDK_TAILQ_INSERT_TAIL(&clovec->allocs, alloc, next); - clovec->nallocs++; - return 0; -} - -/* - * clo_vec_grow -- (internal) grow in size the CLO vector - */ -static void -clo_vec_grow(struct clo_vec *clovec, size_t new_len) -{ - size_t nargs = new_len - clovec->nargs; - size_t i; - - for (i = 0; i < nargs; i++) { - struct clo_vec_args *args = - (struct clo_vec_args *)calloc(1, sizeof(*args)); - - assert(args != nullptr); - - PMDK_TAILQ_INSERT_TAIL(&clovec->args, args, next); - - args->args = malloc(clovec->size); - assert(args->args != nullptr); - - void *argscpy = clo_vec_get_args(clovec, i % clovec->nargs); - assert(argscpy != nullptr); - - memcpy(args->args, argscpy, clovec->size); - } - - clovec->nargs = new_len; -} - -/* - * clo_vec_vlist_alloc -- allocate list of values - */ -struct clo_vec_vlist * -clo_vec_vlist_alloc(void) -{ - struct clo_vec_vlist *list = - (struct clo_vec_vlist *)malloc(sizeof(*list)); - - assert(list != nullptr); - - list->nvalues = 0; - PMDK_TAILQ_INIT(&list->head); - - return list; -} - -/* - * clo_vec_vlist_free -- release list of values - */ -void -clo_vec_vlist_free(struct clo_vec_vlist *list) -{ - assert(list != nullptr); - - while (!PMDK_TAILQ_EMPTY(&list->head)) { - struct clo_vec_value *val = PMDK_TAILQ_FIRST(&list->head); - PMDK_TAILQ_REMOVE(&list->head, val, next); - free(val->ptr); - free(val); - } - - free(list); -} - -/* - * clo_vec_vlist_add -- add value to list - */ -void -clo_vec_vlist_add(struct clo_vec_vlist *list, void *ptr, size_t size) -{ - struct clo_vec_value *val = - (struct clo_vec_value *)malloc(sizeof(*val)); - assert(val != nullptr); - - val->ptr = malloc(size); - assert(val->ptr != nullptr); - - memcpy(val->ptr, ptr, size); - PMDK_TAILQ_INSERT_TAIL(&list->head, val, next); - list->nvalues++; -} - -/* - * clo_vec_memcpy -- copy value to CLO vector - * - * - clovec - CLO vector - * - off - offset to value in structure - * - size - size of value field - * - ptr - pointer to value - */ -int -clo_vec_memcpy(struct clo_vec *clovec, size_t off, size_t size, void *ptr) -{ - if (off + size > clovec->size) - return -1; - - size_t i; - for (i = 0; i < clovec->nargs; i++) { - auto *args = (char *)clo_vec_get_args(clovec, i); - char *dptr = args + off; - memcpy(dptr, ptr, size); - } - - return 0; -} - -/* - * clo_vec_memcpy_list -- copy values from list to CLO vector - * - * - clovec - CLO vector - * - off - offset to value in structure - * - size - size of value field - * - list - list of values - */ -int -clo_vec_memcpy_list(struct clo_vec *clovec, size_t off, size_t size, - struct clo_vec_vlist *list) -{ - if (off + size > clovec->size) - return -1; - - size_t len = clovec->nargs; - if (list->nvalues > 1) - clo_vec_grow(clovec, clovec->nargs * list->nvalues); - - struct clo_vec_value *value; - size_t value_i = 0; - size_t i; - - PMDK_TAILQ_FOREACH(value, &list->head, next) - { - for (i = value_i * len; i < (value_i + 1) * len; i++) { - auto *args = (char *)clo_vec_get_args(clovec, i); - char *dptr = args + off; - memcpy(dptr, value->ptr, size); - } - value_i++; - } - - return 0; -} diff --git a/src/benchmarks/clo_vec.hpp b/src/benchmarks/clo_vec.hpp deleted file mode 100644 index a7b6fe9682..0000000000 --- a/src/benchmarks/clo_vec.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ -/* - * clo_vec.hpp -- command line options vector declarations - */ -#include "queue.h" -#include - -struct clo_vec_args { - PMDK_TAILQ_ENTRY(clo_vec_args) next; - void *args; -}; - -struct clo_vec_alloc { - PMDK_TAILQ_ENTRY(clo_vec_alloc) next; - void *ptr; -}; - -struct clo_vec_value { - PMDK_TAILQ_ENTRY(clo_vec_value) next; - void *ptr; -}; - -struct clo_vec_vlist { - PMDK_TAILQ_HEAD(valueshead, clo_vec_value) head; - size_t nvalues; -}; - -struct clo_vec { - size_t size; - PMDK_TAILQ_HEAD(argshead, clo_vec_args) args; - size_t nargs; - PMDK_TAILQ_HEAD(allochead, clo_vec_alloc) allocs; - size_t nallocs; -}; - -struct clo_vec *clo_vec_alloc(size_t size); -void clo_vec_free(struct clo_vec *clovec); -void *clo_vec_get_args(struct clo_vec *clovec, size_t i); -int clo_vec_add_alloc(struct clo_vec *clovec, void *ptr); -int clo_vec_memcpy(struct clo_vec *clovec, size_t off, size_t size, void *ptr); -int clo_vec_memcpy_list(struct clo_vec *clovec, size_t off, size_t size, - struct clo_vec_vlist *list); -struct clo_vec_vlist *clo_vec_vlist_alloc(void); -void clo_vec_vlist_free(struct clo_vec_vlist *list); -void clo_vec_vlist_add(struct clo_vec_vlist *list, void *ptr, size_t size); diff --git a/src/benchmarks/config_reader.cpp b/src/benchmarks/config_reader.cpp deleted file mode 100644 index 281b63625d..0000000000 --- a/src/benchmarks/config_reader.cpp +++ /dev/null @@ -1,280 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ -/* - * config_reader.cpp -- config reader module definitions - */ -#include -#include -#include -#include -#include -#include - -#include "config_reader.hpp" -#include "scenario.hpp" - -#define SECTION_GLOBAL "global" -#define KEY_BENCHMARK "bench" -#define KEY_GROUP "group" - -/* - * config_reader -- handle structure - */ -struct config_reader { - GKeyFile *key_file; -}; - -/* - * config_reader_alloc -- allocate config reader - */ -struct config_reader * -config_reader_alloc(void) -{ - struct config_reader *cr = (struct config_reader *)malloc(sizeof(*cr)); - assert(cr != nullptr); - - cr->key_file = g_key_file_new(); - if (!cr->key_file) - goto err; - - return cr; - -err: - free(cr); - return nullptr; -} - -/* - * config_reader_read -- read config file - */ -int -config_reader_read(struct config_reader *cr, const char *fname) -{ - if (g_key_file_load_from_file(cr->key_file, fname, G_KEY_FILE_NONE, - nullptr) != TRUE) - return -1; - - return 0; -} - -/* - * config_reader_free -- free config reader - */ -void -config_reader_free(struct config_reader *cr) -{ - g_key_file_free(cr->key_file); - free(cr); -} - -/* - * is_scenario -- (internal) return true if _name_ is scenario name - * - * This filters out the _global_ and _config_ sections. - */ -static int -is_scenario(const char *name) -{ - return strcmp(name, SECTION_GLOBAL); -} - -/* - * is_argument -- (internal) return true if _name_ is argument name - * - * This filters out the _benchmark_ key. - */ -static int -is_argument(const char *name) -{ - return strcmp(name, KEY_BENCHMARK) != 0 && strcmp(name, KEY_GROUP) != 0; -} - -/* - * config_reader_get_scenarios -- return scenarios from config file - * - * This function reads the config file and returns a list of scenarios. - * Each scenario contains a list of key/value arguments. - * The scenario's arguments are merged with arguments from global section. - */ -int -config_reader_get_scenarios(struct config_reader *cr, - struct scenarios **scenarios) -{ - /* - * Read all groups. - * The config file must have at least one group, otherwise - * it is considered as invalid. - */ - gsize ngroups; - gsize g; - gchar **groups = g_key_file_get_groups(cr->key_file, &ngroups); - assert(nullptr != groups); - if (!groups) - return -1; - - /* - * Check if global section is present and read keys from it. - */ - int ret = 0; - int has_global = - g_key_file_has_group(cr->key_file, SECTION_GLOBAL) == TRUE; - gsize ngkeys; - gchar **gkeys = nullptr; - struct scenarios *s; - if (has_global) { - gkeys = g_key_file_get_keys(cr->key_file, SECTION_GLOBAL, - &ngkeys, nullptr); - assert(nullptr != gkeys); - if (!gkeys) { - ret = -1; - goto err_groups; - } - } - - s = scenarios_alloc(); - assert(nullptr != s); - if (!s) { - ret = -1; - goto err_gkeys; - } - - for (g = 0; g < ngroups; g++) { - /* - * Check whether a group is a scenario - * or global section. - */ - if (!is_scenario(groups[g])) - continue; - - /* - * Check for KEY_BENCHMARK which contains benchmark name. - * If not present the benchmark name is the same as the - * name of the section. - */ - struct scenario *scenario = nullptr; - if (g_key_file_has_key(cr->key_file, groups[g], KEY_BENCHMARK, - nullptr) == FALSE) { - scenario = scenario_alloc(groups[g], groups[g]); - assert(scenario != nullptr); - } else { - gchar *benchmark = - g_key_file_get_value(cr->key_file, groups[g], - KEY_BENCHMARK, nullptr); - assert(benchmark != nullptr); - if (!benchmark) { - ret = -1; - goto err_scenarios; - } - scenario = scenario_alloc(groups[g], benchmark); - assert(scenario != nullptr); - free(benchmark); - } - - gsize k; - if (has_global) { - /* - * Merge key/values from global section. - */ - for (k = 0; k < ngkeys; k++) { - if (g_key_file_has_key(cr->key_file, groups[g], - gkeys[k], - nullptr) == TRUE) - continue; - - if (!is_argument(gkeys[k])) - continue; - - char *value = g_key_file_get_value( - cr->key_file, SECTION_GLOBAL, gkeys[k], - nullptr); - assert(nullptr != value); - if (!value) { - ret = -1; - goto err_scenarios; - } - - struct kv *kv = kv_alloc(gkeys[k], value); - assert(nullptr != kv); - - free(value); - if (!kv) { - ret = -1; - goto err_scenarios; - } - - PMDK_TAILQ_INSERT_TAIL(&scenario->head, kv, - next); - } - } - - /* check for group name */ - if (g_key_file_has_key(cr->key_file, groups[g], KEY_GROUP, - nullptr) != FALSE) { - gchar *group = g_key_file_get_value( - cr->key_file, groups[g], KEY_GROUP, nullptr); - assert(group != nullptr); - scenario_set_group(scenario, group); - } else if (g_key_file_has_key(cr->key_file, SECTION_GLOBAL, - KEY_GROUP, nullptr) != FALSE) { - gchar *group = g_key_file_get_value(cr->key_file, - SECTION_GLOBAL, - KEY_GROUP, nullptr); - assert(group != nullptr); - scenario_set_group(scenario, group); - } - - gsize nkeys; - gchar **keys = g_key_file_get_keys(cr->key_file, groups[g], - &nkeys, nullptr); - assert(nullptr != keys); - if (!keys) { - ret = -1; - goto err_scenarios; - } - - /* - * Read key/values from the scenario's section. - */ - for (k = 0; k < nkeys; k++) { - if (!is_argument(keys[k])) - continue; - char *value = g_key_file_get_value( - cr->key_file, groups[g], keys[k], nullptr); - assert(nullptr != value); - if (!value) { - ret = -1; - g_strfreev(keys); - goto err_scenarios; - } - - struct kv *kv = kv_alloc(keys[k], value); - assert(nullptr != kv); - - free(value); - if (!kv) { - g_strfreev(keys); - ret = -1; - goto err_scenarios; - } - - PMDK_TAILQ_INSERT_TAIL(&scenario->head, kv, next); - } - - g_strfreev(keys); - - PMDK_TAILQ_INSERT_TAIL(&s->head, scenario, next); - } - - g_strfreev(gkeys); - g_strfreev(groups); - - *scenarios = s; - return 0; -err_scenarios: - scenarios_free(s); -err_gkeys: - g_strfreev(gkeys); -err_groups: - g_strfreev(groups); - return ret; -} diff --git a/src/benchmarks/config_reader.hpp b/src/benchmarks/config_reader.hpp deleted file mode 100644 index 926510e1e7..0000000000 --- a/src/benchmarks/config_reader.hpp +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ -/* - * config_reader.hpp -- config reader module declarations - */ -struct config_reader; - -struct config_reader *config_reader_alloc(void); -int config_reader_read(struct config_reader *cr, const char *fname); -void config_reader_free(struct config_reader *cr); -int config_reader_get_scenarios(struct config_reader *cr, - struct scenarios **scenarios); diff --git a/src/benchmarks/map_bench.cpp b/src/benchmarks/map_bench.cpp deleted file mode 100644 index 07e5e1f3f3..0000000000 --- a/src/benchmarks/map_bench.cpp +++ /dev/null @@ -1,846 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2018, Intel Corporation */ -/* - * map_bench.cpp -- benchmarks for: ctree, btree, rtree, rbtree, hashmap_atomic - * and hashmap_tx from examples. - */ -#include - -#include "benchmark.hpp" -#include "file.h" -#include "os.h" -#include "os_thread.h" -#include "poolset_util.hpp" - -#include "map.h" -#include "map_btree.h" -#include "map_ctree.h" -#include "map_hashmap_atomic.h" -#include "map_hashmap_rp.h" -#include "map_hashmap_tx.h" -#include "map_rbtree.h" -#include "map_rtree.h" - -/* Values less than 3 is not suitable for current rtree implementation */ -#define FACTOR 3 -#define ALLOC_OVERHEAD 64 - -TOID_DECLARE_ROOT(struct root); - -struct root { - TOID(struct map) map; -}; - -#define OBJ_TYPE_NUM 1 - -#define swap(a, b) \ - do { \ - __typeof__(a) _tmp = (a); \ - (a) = (b); \ - (b) = _tmp; \ - } while (0) - -/* Values less than 2048 is not suitable for current rtree implementation */ -#define SIZE_PER_KEY 2048 - -static const struct { - const char *str; - const struct map_ops *ops; -} map_types[] = { - {"ctree", MAP_CTREE}, {"btree", MAP_BTREE}, - {"rtree", MAP_RTREE}, {"rbtree", MAP_RBTREE}, - {"hashmap_tx", MAP_HASHMAP_TX}, {"hashmap_atomic", MAP_HASHMAP_ATOMIC}, - {"hashmap_rp", MAP_HASHMAP_RP}}; - -#define MAP_TYPES_NUM (sizeof(map_types) / sizeof(map_types[0])) - -struct map_bench_args { - unsigned seed; - uint64_t max_key; - char *type; - bool ext_tx; - bool alloc; -}; - -struct map_bench_worker { - uint64_t *keys; - size_t nkeys; -}; - -struct map_bench { - struct map_ctx *mapc; - os_mutex_t lock; - PMEMobjpool *pop; - size_t pool_size; - - size_t nkeys; - size_t init_nkeys; - uint64_t *keys; - struct benchmark_args *args; - struct map_bench_args *margs; - - TOID(struct root) root; - PMEMoid root_oid; - TOID(struct map) map; - - int (*insert)(struct map_bench *, uint64_t); - int (*remove)(struct map_bench *, uint64_t); - int (*get)(struct map_bench *, uint64_t); -}; - -/* - * mutex_lock_nofail -- locks mutex and aborts if locking failed - */ -static void -mutex_lock_nofail(os_mutex_t *lock) -{ - errno = os_mutex_lock(lock); - if (errno) { - perror("os_mutex_lock"); - abort(); - } -} - -/* - * mutex_unlock_nofail -- unlocks mutex and aborts if unlocking failed - */ -static void -mutex_unlock_nofail(os_mutex_t *lock) -{ - errno = os_mutex_unlock(lock); - if (errno) { - perror("os_mutex_unlock"); - abort(); - } -} - -/* - * get_key -- return 64-bit random key - */ -static uint64_t -get_key(unsigned *seed, uint64_t max_key) -{ - unsigned key_lo = os_rand_r(seed); - unsigned key_hi = os_rand_r(seed); - uint64_t key = (((uint64_t)key_hi) << 32) | ((uint64_t)key_lo); - - if (max_key) - key = key % max_key; - - return key; -} - -/* - * parse_map_type -- parse type of map - */ -static const struct map_ops * -parse_map_type(const char *str) -{ - for (unsigned i = 0; i < MAP_TYPES_NUM; i++) { - if (strcmp(str, map_types[i].str) == 0) - return map_types[i].ops; - } - - return nullptr; -} - -/* - * map_remove_free_op -- remove and free object from map - */ -static int -map_remove_free_op(struct map_bench *map_bench, uint64_t key) -{ - volatile int ret = 0; - TX_BEGIN(map_bench->pop) - { - PMEMoid val = map_remove(map_bench->mapc, map_bench->map, key); - if (OID_IS_NULL(val)) - ret = -1; - else - pmemobj_tx_free(val); - } - TX_ONABORT - { - ret = -1; - } - TX_END - - return ret; -} - -/* - * map_remove_root_op -- remove root object from map - */ -static int -map_remove_root_op(struct map_bench *map_bench, uint64_t key) -{ - PMEMoid val = map_remove(map_bench->mapc, map_bench->map, key); - - return !OID_EQUALS(val, map_bench->root_oid); -} - -/* - * map_remove_op -- main operation for map_remove benchmark - */ -static int -map_remove_op(struct benchmark *bench, struct operation_info *info) -{ - auto *map_bench = (struct map_bench *)pmembench_get_priv(bench); - auto *tworker = (struct map_bench_worker *)info->worker->priv; - - uint64_t key = tworker->keys[info->index]; - - mutex_lock_nofail(&map_bench->lock); - - int ret = map_bench->remove(map_bench, key); - - mutex_unlock_nofail(&map_bench->lock); - - return ret; -} - -/* - * map_insert_alloc_op -- allocate an object and insert to map - */ -static int -map_insert_alloc_op(struct map_bench *map_bench, uint64_t key) -{ - int ret = 0; - - TX_BEGIN(map_bench->pop) - { - PMEMoid oid = - pmemobj_tx_alloc(map_bench->args->dsize, OBJ_TYPE_NUM); - ret = map_insert(map_bench->mapc, map_bench->map, key, oid); - } - TX_ONABORT - { - ret = -1; - } - TX_END - - return ret; -} - -/* - * map_insert_root_op -- insert root object to map - */ -static int -map_insert_root_op(struct map_bench *map_bench, uint64_t key) -{ - return map_insert(map_bench->mapc, map_bench->map, key, - map_bench->root_oid); -} - -/* - * map_insert_op -- main operation for map_insert benchmark - */ -static int -map_insert_op(struct benchmark *bench, struct operation_info *info) -{ - auto *map_bench = (struct map_bench *)pmembench_get_priv(bench); - auto *tworker = (struct map_bench_worker *)info->worker->priv; - uint64_t key = tworker->keys[info->index]; - - mutex_lock_nofail(&map_bench->lock); - - int ret = map_bench->insert(map_bench, key); - - mutex_unlock_nofail(&map_bench->lock); - - return ret; -} - -/* - * map_get_obj_op -- get object from map at specified key - */ -static int -map_get_obj_op(struct map_bench *map_bench, uint64_t key) -{ - PMEMoid val = map_get(map_bench->mapc, map_bench->map, key); - - return OID_IS_NULL(val); -} - -/* - * map_get_root_op -- get root object from map at specified key - */ -static int -map_get_root_op(struct map_bench *map_bench, uint64_t key) -{ - PMEMoid val = map_get(map_bench->mapc, map_bench->map, key); - - return !OID_EQUALS(val, map_bench->root_oid); -} - -/* - * map_get_op -- main operation for map_get benchmark - */ -static int -map_get_op(struct benchmark *bench, struct operation_info *info) -{ - auto *map_bench = (struct map_bench *)pmembench_get_priv(bench); - auto *tworker = (struct map_bench_worker *)info->worker->priv; - - uint64_t key = tworker->keys[info->index]; - - mutex_lock_nofail(&map_bench->lock); - - int ret = map_bench->get(map_bench, key); - - mutex_unlock_nofail(&map_bench->lock); - - return ret; -} - -/* - * map_common_init_worker -- common init worker function for map_* benchmarks - */ -static int -map_common_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - struct map_bench_worker *tworker = - (struct map_bench_worker *)calloc(1, sizeof(*tworker)); - struct map_bench *tree; - struct map_bench_args *targs; - - if (!tworker) { - perror("calloc"); - return -1; - } - - tworker->nkeys = args->n_ops_per_thread; - tworker->keys = - (uint64_t *)malloc(tworker->nkeys * sizeof(*tworker->keys)); - - if (!tworker->keys) { - perror("malloc"); - goto err_free_worker; - } - - tree = (struct map_bench *)pmembench_get_priv(bench); - targs = (struct map_bench_args *)args->opts; - if (targs->ext_tx) { - int ret = pmemobj_tx_begin(tree->pop, nullptr); - if (ret) { - (void)pmemobj_tx_end(); - goto err_free_keys; - } - } - - worker->priv = tworker; - - return 0; -err_free_keys: - free(tworker->keys); -err_free_worker: - free(tworker); - return -1; -} - -/* - * map_common_free_worker -- common cleanup worker function for map_* - * benchmarks - */ -static void -map_common_free_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *tworker = (struct map_bench_worker *)worker->priv; - auto *targs = (struct map_bench_args *)args->opts; - - if (targs->ext_tx) { - pmemobj_tx_commit(); - (void)pmemobj_tx_end(); - } - free(tworker->keys); - free(tworker); -} - -/* - * map_insert_init_worker -- init worker function for map_insert benchmark - */ -static int -map_insert_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - int ret = map_common_init_worker(bench, args, worker); - if (ret) - return ret; - - auto *targs = (struct map_bench_args *)args->opts; - assert(targs); - auto *tworker = (struct map_bench_worker *)worker->priv; - - assert(tworker); - - for (size_t i = 0; i < tworker->nkeys; i++) - tworker->keys[i] = get_key(&targs->seed, targs->max_key); - - return 0; -} - -/* - * map_global_rand_keys_init -- assign random keys from global keys array - */ -static int -map_global_rand_keys_init(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - - auto *tree = (struct map_bench *)pmembench_get_priv(bench); - assert(tree); - auto *targs = (struct map_bench_args *)args->opts; - assert(targs); - auto *tworker = (struct map_bench_worker *)worker->priv; - - assert(tworker); - assert(tree->init_nkeys); - - /* - * Assign random keys from global tree->keys array without repetitions. - */ - for (size_t i = 0; i < tworker->nkeys; i++) { - uint64_t index = get_key(&targs->seed, tree->init_nkeys); - tworker->keys[i] = tree->keys[index]; - swap(tree->keys[index], tree->keys[tree->init_nkeys - 1]); - tree->init_nkeys--; - } - - return 0; -} - -/* - * map_remove_init_worker -- init worker function for map_remove benchmark - */ -static int -map_remove_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - int ret = map_common_init_worker(bench, args, worker); - if (ret) - return ret; - - ret = map_global_rand_keys_init(bench, args, worker); - if (ret) - goto err_common_free_worker; - return 0; -err_common_free_worker: - map_common_free_worker(bench, args, worker); - return -1; -} - -/* - * map_bench_get_init_worker -- init worker function for map_get benchmark - */ -static int -map_bench_get_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - int ret = map_common_init_worker(bench, args, worker); - if (ret) - return ret; - - ret = map_global_rand_keys_init(bench, args, worker); - if (ret) - goto err_common_free_worker; - return 0; -err_common_free_worker: - map_common_free_worker(bench, args, worker); - return -1; -} - -/* - * map_common_init -- common init function for map_* benchmarks - */ -static int -map_common_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench); - assert(args); - assert(args->opts); - - char path[PATH_MAX]; - if (util_safe_strcpy(path, args->fname, sizeof(path)) != 0) - return -1; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - size_t size_per_key; - struct map_bench *map_bench = - (struct map_bench *)calloc(1, sizeof(*map_bench)); - - if (!map_bench) { - perror("calloc"); - return -1; - } - - map_bench->args = args; - map_bench->margs = (struct map_bench_args *)args->opts; - - const struct map_ops *ops = parse_map_type(map_bench->margs->type); - if (!ops) { - fprintf(stderr, "invalid map type value specified -- '%s'\n", - map_bench->margs->type); - goto err_free_bench; - } - - if (map_bench->margs->ext_tx && args->n_threads > 1) { - fprintf(stderr, - "external transaction requires single thread\n"); - goto err_free_bench; - } - - if (map_bench->margs->alloc) { - map_bench->insert = map_insert_alloc_op; - map_bench->remove = map_remove_free_op; - map_bench->get = map_get_obj_op; - } else { - map_bench->insert = map_insert_root_op; - map_bench->remove = map_remove_root_op; - map_bench->get = map_get_root_op; - } - - map_bench->nkeys = args->n_threads * args->n_ops_per_thread; - map_bench->init_nkeys = map_bench->nkeys; - size_per_key = map_bench->margs->alloc - ? SIZE_PER_KEY + map_bench->args->dsize + ALLOC_OVERHEAD - : SIZE_PER_KEY; - - map_bench->pool_size = map_bench->nkeys * size_per_key * FACTOR; - - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < map_bench->pool_size) { - fprintf(stderr, "file size too large\n"); - goto err_free_bench; - } - - map_bench->pool_size = 0; - } else if (map_bench->pool_size < 2 * PMEMOBJ_MIN_POOL) { - map_bench->pool_size = 2 * PMEMOBJ_MIN_POOL; - } - - if (args->is_dynamic_poolset) { - int ret = dynamic_poolset_create(args->fname, - map_bench->pool_size); - if (ret == -1) - goto err_free_bench; - - if (util_safe_strcpy(path, POOLSET_PATH, sizeof(path)) != 0) - goto err_free_bench; - - map_bench->pool_size = 0; - } - - map_bench->pop = pmemobj_create(path, "map_bench", map_bench->pool_size, - args->fmode); - if (!map_bench->pop) { - fprintf(stderr, "pmemobj_create: %s\n", pmemobj_errormsg()); - goto err_free_bench; - } - - errno = os_mutex_init(&map_bench->lock); - if (errno) { - perror("os_mutex_init"); - goto err_close; - } - - map_bench->mapc = map_ctx_init(ops, map_bench->pop); - if (!map_bench->mapc) { - perror("map_ctx_init"); - goto err_destroy_lock; - } - - map_bench->root = POBJ_ROOT(map_bench->pop, struct root); - if (TOID_IS_NULL(map_bench->root)) { - fprintf(stderr, "pmemobj_root: %s\n", pmemobj_errormsg()); - goto err_free_map; - } - - map_bench->root_oid = map_bench->root.oid; - - if (map_create(map_bench->mapc, &D_RW(map_bench->root)->map, nullptr)) { - perror("map_new"); - goto err_free_map; - } - - map_bench->map = D_RO(map_bench->root)->map; - - pmembench_set_priv(bench, map_bench); - return 0; -err_free_map: - map_ctx_free(map_bench->mapc); -err_destroy_lock: - os_mutex_destroy(&map_bench->lock); -err_close: - pmemobj_close(map_bench->pop); -err_free_bench: - free(map_bench); - return -1; -} - -/* - * map_common_exit -- common cleanup function for map_* benchmarks - */ -static int -map_common_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *tree = (struct map_bench *)pmembench_get_priv(bench); - - os_mutex_destroy(&tree->lock); - map_ctx_free(tree->mapc); - pmemobj_close(tree->pop); - free(tree); - return 0; -} - -/* - * map_keys_init -- initialize array with keys - */ -static int -map_keys_init(struct benchmark *bench, struct benchmark_args *args) -{ - auto *map_bench = (struct map_bench *)pmembench_get_priv(bench); - assert(map_bench); - auto *targs = (struct map_bench_args *)args->opts; - assert(targs); - - assert(map_bench->nkeys != 0); - map_bench->keys = - (uint64_t *)malloc(map_bench->nkeys * sizeof(*map_bench->keys)); - - if (!map_bench->keys) { - perror("malloc"); - return -1; - } - - int ret = 0; - - mutex_lock_nofail(&map_bench->lock); - - TX_BEGIN(map_bench->pop) - { - for (size_t i = 0; i < map_bench->nkeys; i++) { - uint64_t key; - PMEMoid oid; - do { - key = get_key(&targs->seed, targs->max_key); - oid = map_get(map_bench->mapc, map_bench->map, - key); - } while (!OID_IS_NULL(oid)); - - if (targs->alloc) - oid = pmemobj_tx_alloc(args->dsize, - OBJ_TYPE_NUM); - else - oid = map_bench->root_oid; - - ret = map_insert(map_bench->mapc, map_bench->map, key, - oid); - if (ret) - break; - - map_bench->keys[i] = key; - } - } - TX_ONABORT - { - ret = -1; - } - TX_END - - mutex_unlock_nofail(&map_bench->lock); - - if (!ret) - return 0; - - free(map_bench->keys); - return ret; -} - -/* - * map_keys_exit -- cleanup of keys array - */ -static int -map_keys_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *tree = (struct map_bench *)pmembench_get_priv(bench); - free(tree->keys); - return 0; -} - -/* - * map_remove_init -- init function for map_remove benchmark - */ -static int -map_remove_init(struct benchmark *bench, struct benchmark_args *args) -{ - int ret = map_common_init(bench, args); - if (ret) - return ret; - ret = map_keys_init(bench, args); - if (ret) - goto err_exit_common; - - return 0; -err_exit_common: - map_common_exit(bench, args); - return -1; -} - -/* - * map_remove_exit -- cleanup function for map_remove benchmark - */ -static int -map_remove_exit(struct benchmark *bench, struct benchmark_args *args) -{ - map_keys_exit(bench, args); - return map_common_exit(bench, args); -} - -/* - * map_bench_get_init -- init function for map_get benchmark - */ -static int -map_bench_get_init(struct benchmark *bench, struct benchmark_args *args) -{ - int ret = map_common_init(bench, args); - if (ret) - return ret; - ret = map_keys_init(bench, args); - if (ret) - goto err_exit_common; - - return 0; -err_exit_common: - map_common_exit(bench, args); - return -1; -} - -/* - * map_get_exit -- exit function for map_get benchmark - */ -static int -map_get_exit(struct benchmark *bench, struct benchmark_args *args) -{ - map_keys_exit(bench, args); - return map_common_exit(bench, args); -} - -static struct benchmark_clo map_bench_clos[5]; - -static struct benchmark_info map_insert_info; -static struct benchmark_info map_remove_info; -static struct benchmark_info map_get_info; - -CONSTRUCTOR(map_bench_constructor) -void -map_bench_constructor(void) -{ - map_bench_clos[0].opt_short = 'T'; - map_bench_clos[0].opt_long = "type"; - map_bench_clos[0].descr = - "Type of container " - "[ctree|btree|rtree|rbtree|hashmap_tx|hashmap_atomic]"; - - map_bench_clos[0].off = clo_field_offset(struct map_bench_args, type); - map_bench_clos[0].type = CLO_TYPE_STR; - map_bench_clos[0].def = "ctree"; - - map_bench_clos[1].opt_short = 's'; - map_bench_clos[1].opt_long = "seed"; - map_bench_clos[1].descr = "PRNG seed"; - map_bench_clos[1].off = clo_field_offset(struct map_bench_args, seed); - map_bench_clos[1].type = CLO_TYPE_UINT; - map_bench_clos[1].def = "1"; - map_bench_clos[1].type_uint.size = - clo_field_size(struct map_bench_args, seed); - map_bench_clos[1].type_uint.base = CLO_INT_BASE_DEC; - map_bench_clos[1].type_uint.min = 1; - map_bench_clos[1].type_uint.max = UINT_MAX; - - map_bench_clos[2].opt_short = 'M'; - map_bench_clos[2].opt_long = "max-key"; - map_bench_clos[2].descr = "maximum key (0 means no limit)"; - map_bench_clos[2].off = - clo_field_offset(struct map_bench_args, max_key); - map_bench_clos[2].type = CLO_TYPE_UINT; - map_bench_clos[2].def = "0"; - map_bench_clos[2].type_uint.size = - clo_field_size(struct map_bench_args, seed); - map_bench_clos[2].type_uint.base = CLO_INT_BASE_DEC; - map_bench_clos[2].type_uint.min = 0; - map_bench_clos[2].type_uint.max = UINT64_MAX; - - map_bench_clos[3].opt_short = 'x'; - map_bench_clos[3].opt_long = "external-tx"; - map_bench_clos[3].descr = "Use external transaction for all " - "operations (works with single " - "thread only)"; - map_bench_clos[3].off = clo_field_offset(struct map_bench_args, ext_tx); - map_bench_clos[3].type = CLO_TYPE_FLAG; - - map_bench_clos[4].opt_short = 'A'; - map_bench_clos[4].opt_long = "alloc"; - map_bench_clos[4].descr = "Allocate object of specified size " - "when inserting"; - map_bench_clos[4].off = clo_field_offset(struct map_bench_args, alloc); - map_bench_clos[4].type = CLO_TYPE_FLAG; - - map_insert_info.name = "map_insert"; - map_insert_info.brief = "Inserting to tree map"; - map_insert_info.init = map_common_init; - map_insert_info.exit = map_common_exit; - map_insert_info.multithread = true; - map_insert_info.multiops = true; - map_insert_info.init_worker = map_insert_init_worker; - map_insert_info.free_worker = map_common_free_worker; - map_insert_info.operation = map_insert_op; - map_insert_info.measure_time = true; - map_insert_info.clos = map_bench_clos; - map_insert_info.nclos = ARRAY_SIZE(map_bench_clos); - map_insert_info.opts_size = sizeof(struct map_bench_args); - map_insert_info.rm_file = true; - map_insert_info.allow_poolset = true; - REGISTER_BENCHMARK(map_insert_info); - - map_remove_info.name = "map_remove"; - map_remove_info.brief = "Removing from tree map"; - map_remove_info.init = map_remove_init; - map_remove_info.exit = map_remove_exit; - map_remove_info.multithread = true; - map_remove_info.multiops = true; - map_remove_info.init_worker = map_remove_init_worker; - map_remove_info.free_worker = map_common_free_worker; - map_remove_info.operation = map_remove_op; - map_remove_info.measure_time = true; - map_remove_info.clos = map_bench_clos; - map_remove_info.nclos = ARRAY_SIZE(map_bench_clos); - map_remove_info.opts_size = sizeof(struct map_bench_args); - map_remove_info.rm_file = true; - map_remove_info.allow_poolset = true; - REGISTER_BENCHMARK(map_remove_info); - - map_get_info.name = "map_get"; - map_get_info.brief = "Tree lookup"; - map_get_info.init = map_bench_get_init; - map_get_info.exit = map_get_exit; - map_get_info.multithread = true; - map_get_info.multiops = true; - map_get_info.init_worker = map_bench_get_init_worker; - map_get_info.free_worker = map_common_free_worker; - map_get_info.operation = map_get_op; - map_get_info.measure_time = true; - map_get_info.clos = map_bench_clos; - map_get_info.nclos = ARRAY_SIZE(map_bench_clos); - map_get_info.opts_size = sizeof(struct map_bench_args); - map_get_info.rm_file = true; - map_get_info.allow_poolset = true; - REGISTER_BENCHMARK(map_get_info); -} diff --git a/src/benchmarks/obj_lanes.cpp b/src/benchmarks/obj_lanes.cpp deleted file mode 100644 index 7e2e7a2d85..0000000000 --- a/src/benchmarks/obj_lanes.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2018, Intel Corporation */ - -/* - * obj_lanes.cpp -- lane benchmark definition - */ - -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" - -/* an internal libpmemobj code */ -#include "lane.h" - -/* - * The number of times to repeat the operation, used to get more accurate - * results, because the operation time was minimal compared to the framework - * overhead. - */ -#define OPERATION_REPEAT_COUNT 10000 - -/* - * obj_bench - variables used in benchmark, passed within functions - */ -struct obj_bench { - PMEMobjpool *pop; /* persistent pool handle */ - struct prog_args *pa; /* prog_args structure */ -}; - -/* - * lanes_init -- benchmark initialization - */ -static int -lanes_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - auto *ob = (struct obj_bench *)malloc(sizeof(struct obj_bench)); - if (ob == nullptr) { - perror("malloc"); - return -1; - } - pmembench_set_priv(bench, ob); - - ob->pa = (struct prog_args *)args->opts; - size_t psize; - - if (args->is_poolset || type == TYPE_DEVDAX) - psize = 0; - else - psize = PMEMOBJ_MIN_POOL; - - /* create pmemobj pool */ - ob->pop = pmemobj_create(args->fname, "obj_lanes", psize, args->fmode); - if (ob->pop == nullptr) { - fprintf(stderr, "%s\n", pmemobj_errormsg()); - goto err; - } - - return 0; - -err: - free(ob); - return -1; -} - -/* - * lanes_exit -- benchmark clean up - */ -static int -lanes_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - pmemobj_close(ob->pop); - free(ob); - - return 0; -} - -/* - * lanes_op -- performs the lane hold and release operations - */ -static int -lanes_op(struct benchmark *bench, struct operation_info *info) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - struct lane *lane; - - for (int i = 0; i < OPERATION_REPEAT_COUNT; i++) { - lane_hold(ob->pop, &lane); - - lane_release(ob->pop); - } - - return 0; -} -static struct benchmark_info lanes_info; - -CONSTRUCTOR(obj_lines_constructor) -void -obj_lines_constructor(void) -{ - lanes_info.name = "obj_lanes"; - lanes_info.brief = "Benchmark for internal lanes " - "operation"; - lanes_info.init = lanes_init; - lanes_info.exit = lanes_exit; - lanes_info.multithread = true; - lanes_info.multiops = true; - lanes_info.operation = lanes_op; - lanes_info.measure_time = true; - lanes_info.clos = NULL; - lanes_info.nclos = 0; - lanes_info.opts_size = 0; - lanes_info.rm_file = true; - lanes_info.allow_poolset = true; - REGISTER_BENCHMARK(lanes_info); -} diff --git a/src/benchmarks/obj_locks.cpp b/src/benchmarks/obj_locks.cpp deleted file mode 100644 index 18197476a1..0000000000 --- a/src/benchmarks/obj_locks.cpp +++ /dev/null @@ -1,849 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ - -/* - * obj_locks.cpp -- main source file for PMEM locks benchmark - */ - -#include -#include - -#include "benchmark.hpp" -#include "libpmemobj.h" - -#include "file.h" -#include "lane.h" -#include "list.h" -#include "memops.h" -#include "obj.h" -#include "os_thread.h" -#include "out.h" -#include "pmalloc.h" -#include "sync.h" - -struct prog_args { - bool use_system_threads; /* use system locks instead of PMEM locks */ - unsigned n_locks; /* number of mutex/rwlock objects */ - bool run_id_increment; /* increment run_id after each lock/unlock */ - uint64_t runid_initial_value; /* initial value of run_id */ - char *lock_mode; /* "1by1" or "all-lock" */ - char *lock_type; /* "mutex", "rwlock" or "ram-mutex" */ - bool use_rdlock; /* use read lock, instead of write lock */ -}; - -/* - * mutex similar to PMEMmutex, but with os_mutex_t in RAM - */ -typedef union padded_volatile_pmemmutex { - char padding[_POBJ_CL_SIZE]; - struct { - uint64_t runid; - os_mutex_t *mutexp; /* pointer to os_thread mutex in RAM */ - } volatile_pmemmutex; -} PMEM_volatile_mutex; - -typedef union lock_union { - PMEMmutex pm_mutex; - PMEMrwlock pm_rwlock; - PMEM_volatile_mutex pm_vmutex; - os_mutex_t pt_mutex; - os_rwlock_t pt_rwlock; -} lock_t; - -POBJ_LAYOUT_BEGIN(pmembench_lock_layout); -POBJ_LAYOUT_ROOT(pmembench_lock_layout, struct my_root); -POBJ_LAYOUT_TOID(pmembench_lock_layout, lock_t); -POBJ_LAYOUT_END(pmembench_lock_layout); - -/* - * my_root -- root object structure - */ -struct my_root { - TOID(lock_t) locks; /* an array of locks */ -}; - -/* - * lock usage - */ -enum operation_mode { - OP_MODE_1BY1, /* lock and unlock one lock at a time */ - OP_MODE_ALL_LOCK, /* grab all locks, then unlock them all */ - OP_MODE_MAX, -}; - -/* - * lock type - */ -enum benchmark_mode { - BENCH_MODE_MUTEX, /* PMEMmutex vs. os_mutex_t */ - BENCH_MODE_RWLOCK, /* PMEMrwlock vs. os_rwlock_t */ - BENCH_MODE_VOLATILE_MUTEX, /* PMEMmutex with os_thread mutex in RAM */ - BENCH_MODE_MAX -}; - -struct mutex_bench; - -struct bench_ops { - int (*bench_init)(struct mutex_bench *); - int (*bench_exit)(struct mutex_bench *); - int (*bench_op)(struct mutex_bench *); -}; - -/* - * mutex_bench -- stores variables used in benchmark, passed within functions - */ -struct mutex_bench { - PMEMobjpool *pop; /* pointer to the persistent pool */ - TOID(struct my_root) root; /* OID of the root object */ - struct prog_args *pa; /* prog_args structure */ - enum operation_mode lock_mode; /* lock usage mode */ - enum benchmark_mode lock_type; /* lock type */ - lock_t *locks; /* pointer to the array of locks */ - struct bench_ops *ops; -}; - -#define GET_VOLATILE_MUTEX(pop, mutexp) \ - (os_mutex_t *)get_lock( \ - (pop)->run_id, &(mutexp)->volatile_pmemmutex.runid, \ - (mutexp)->volatile_pmemmutex.mutexp, \ - (int (*)(void **lock, void *arg))volatile_mutex_init) - -typedef int (*lock_fun_wrapper)(PMEMobjpool *pop, void *lock); - -/* - * bench_operation_1by1 -- acquire lock and unlock release locks - */ -static void -bench_operation_1by1(lock_fun_wrapper flock, lock_fun_wrapper funlock, - struct mutex_bench *mb, PMEMobjpool *pop) -{ - for (unsigned i = 0; i < (mb)->pa->n_locks; (i)++) { - auto *o = (void *)(&(mb)->locks[i]); - flock(pop, o); - funlock(pop, o); - } -} - -/* - * bench_operation_all_lock -- acquire all locks and release all locks - */ -static void -bench_operation_all_lock(lock_fun_wrapper flock, lock_fun_wrapper funlock, - struct mutex_bench *mb, PMEMobjpool *pop) -{ - for (unsigned i = 0; i < (mb)->pa->n_locks; (i)++) { - auto *o = (void *)(&(mb)->locks[i]); - flock(pop, o); - } - for (unsigned i = 0; i < (mb)->pa->n_locks; i++) { - auto *o = (void *)(&(mb)->locks[i]); - funlock(pop, o); - } -} - -/* - * get_lock -- atomically initialize and return a lock - */ -static void * -get_lock(uint64_t pop_runid, volatile uint64_t *runid, void *lock, - int (*init_lock)(void **lock, void *arg)) -{ - uint64_t tmp_runid; - while ((tmp_runid = *runid) != pop_runid) { - if ((tmp_runid != (pop_runid - 1))) { - if (util_bool_compare_and_swap64(runid, tmp_runid, - (pop_runid - 1))) { - if (init_lock(&lock, nullptr)) { - util_fetch_and_and64(runid, 0); - return nullptr; - } - - if (util_bool_compare_and_swap64( - runid, (pop_runid - 1), - pop_runid) == 0) { - return nullptr; - } - } - } - } - return lock; -} - -/* - * volatile_mutex_init -- initialize the volatile mutex object - * - * Allocate memory for the os_thread mutex and initialize it. - * Set the runid to the same value as in the memory pool. - */ -static int -volatile_mutex_init(os_mutex_t **mutexp, void *attr) -{ - if (*mutexp == nullptr) { - *mutexp = (os_mutex_t *)malloc(sizeof(os_mutex_t)); - if (*mutexp == nullptr) { - perror("volatile_mutex_init alloc"); - return ENOMEM; - } - } - - return os_mutex_init(*mutexp); -} - -/* - * volatile_mutex_lock -- initialize the mutex object if needed and lock it - */ -static int -volatile_mutex_lock(PMEMobjpool *pop, PMEM_volatile_mutex *mutexp) -{ - auto *mutex = GET_VOLATILE_MUTEX(pop, mutexp); - if (mutex == nullptr) - return EINVAL; - - return os_mutex_lock(mutex); -} - -/* - * volatile_mutex_unlock -- unlock the mutex - */ -static int -volatile_mutex_unlock(PMEMobjpool *pop, PMEM_volatile_mutex *mutexp) -{ - auto *mutex = (os_mutex_t *)GET_VOLATILE_MUTEX(pop, mutexp); - if (mutex == nullptr) - return EINVAL; - - return os_mutex_unlock(mutex); -} - -/* - * volatile_mutex_destroy -- destroy os_thread mutex and release memory - */ -static int -volatile_mutex_destroy(PMEMobjpool *pop, PMEM_volatile_mutex *mutexp) -{ - auto *mutex = (os_mutex_t *)GET_VOLATILE_MUTEX(pop, mutexp); - if (mutex == nullptr) - return EINVAL; - - int ret = os_mutex_destroy(mutex); - if (ret != 0) - return ret; - - free(mutex); - - return 0; -} - -/* - * os_mutex_lock_wrapper -- wrapper for os_mutex_lock - */ -static int -os_mutex_lock_wrapper(PMEMobjpool *pop, void *lock) -{ - return os_mutex_lock((os_mutex_t *)lock); -} - -/* - * os_mutex_unlock_wrapper -- wrapper for os_mutex_unlock - */ -static int -os_mutex_unlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return os_mutex_unlock((os_mutex_t *)lock); -} - -/* - * pmemobj_mutex_lock_wrapper -- wrapper for pmemobj_mutex_lock - */ -static int -pmemobj_mutex_lock_wrapper(PMEMobjpool *pop, void *lock) -{ - return pmemobj_mutex_lock(pop, (PMEMmutex *)lock); -} - -/* - * pmemobj_mutex_unlock_wrapper -- wrapper for pmemobj_mutex_unlock - */ -static int -pmemobj_mutex_unlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return pmemobj_mutex_unlock(pop, (PMEMmutex *)lock); -} - -/* - * os_rwlock_wrlock_wrapper -- wrapper for os_rwlock_wrlock - */ -static int -os_rwlock_wrlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return os_rwlock_wrlock((os_rwlock_t *)lock); -} - -/* - * os_rwlock_rdlock_wrapper -- wrapper for os_rwlock_rdlock - */ -static int -os_rwlock_rdlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return os_rwlock_rdlock((os_rwlock_t *)lock); -} - -/* - * os_rwlock_unlock_wrapper -- wrapper for os_rwlock_unlock - */ -static int -os_rwlock_unlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return os_rwlock_unlock((os_rwlock_t *)lock); -} - -/* - * pmemobj_rwlock_wrlock_wrapper -- wrapper for pmemobj_rwlock_wrlock - */ -static int -pmemobj_rwlock_wrlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return pmemobj_rwlock_wrlock(pop, (PMEMrwlock *)lock); -} - -/* - * pmemobj_rwlock_rdlock_wrapper -- wrapper for pmemobj_rwlock_rdlock - */ -static int -pmemobj_rwlock_rdlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return pmemobj_rwlock_rdlock(pop, (PMEMrwlock *)lock); -} - -/* - * pmemobj_rwlock_unlock_wrapper -- wrapper for pmemobj_rwlock_unlock - */ -static int -pmemobj_rwlock_unlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return pmemobj_rwlock_unlock(pop, (PMEMrwlock *)lock); -} - -/* - * volatile_mutex_lock_wrapper -- wrapper for volatile_mutex_lock - */ -static int -volatile_mutex_lock_wrapper(PMEMobjpool *pop, void *lock) -{ - return volatile_mutex_lock(pop, (PMEM_volatile_mutex *)lock); -} - -/* - * volatile_mutex_unlock_wrapper -- wrapper for volatile_mutex_unlock - */ -static int -volatile_mutex_unlock_wrapper(PMEMobjpool *pop, void *lock) -{ - return volatile_mutex_unlock(pop, (PMEM_volatile_mutex *)lock); -} - -/* - * init_bench_mutex -- allocate and initialize mutex objects - */ -static int -init_bench_mutex(struct mutex_bench *mb) -{ - POBJ_ZALLOC(mb->pop, &D_RW(mb->root)->locks, lock_t, - mb->pa->n_locks * sizeof(lock_t)); - if (TOID_IS_NULL(D_RO(mb->root)->locks)) { - perror("POBJ_ZALLOC"); - return -1; - } - - struct my_root *root = D_RW(mb->root); - assert(root != nullptr); - mb->locks = D_RW(root->locks); - assert(mb->locks != nullptr); - - if (!mb->pa->use_system_threads) { - /* initialize PMEM mutexes */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (PMEMmutex_internal *)&mb->locks[i]; - p->pmemmutex.runid = mb->pa->runid_initial_value; - os_mutex_init(&p->PMEMmutex_lock); - } - } else { - /* initialize os_thread mutexes */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (os_mutex_t *)&mb->locks[i]; - os_mutex_init(p); - } - } - - return 0; -} - -/* - * exit_bench_mutex -- destroy the mutex objects and release memory - */ -static int -exit_bench_mutex(struct mutex_bench *mb) -{ - if (mb->pa->use_system_threads) { - /* deinitialize os_thread mutex objects */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (os_mutex_t *)&mb->locks[i]; - os_mutex_destroy(p); - } - } - - POBJ_FREE(&D_RW(mb->root)->locks); - - return 0; -} - -/* - * op_bench_mutex -- lock and unlock the mutex object - * - * If requested, increment the run_id of the memory pool. In case of PMEMmutex - * this will force the rwlock object(s) reinitialization at the lock operation. - */ -static int -op_bench_mutex(struct mutex_bench *mb) -{ - if (!mb->pa->use_system_threads) { - if (mb->lock_mode == OP_MODE_1BY1) { - bench_operation_1by1(pmemobj_mutex_lock_wrapper, - pmemobj_mutex_unlock_wrapper, mb, - mb->pop); - } else { - bench_operation_all_lock(pmemobj_mutex_lock_wrapper, - pmemobj_mutex_unlock_wrapper, - mb, mb->pop); - } - if (mb->pa->run_id_increment) - mb->pop->run_id += 2; /* must be a multiple of 2 */ - } else { - if (mb->lock_mode == OP_MODE_1BY1) { - bench_operation_1by1(os_mutex_lock_wrapper, - os_mutex_unlock_wrapper, mb, - nullptr); - } else { - bench_operation_all_lock(os_mutex_lock_wrapper, - os_mutex_unlock_wrapper, mb, - nullptr); - } - } - - return 0; -} - -/* - * init_bench_rwlock -- allocate and initialize rwlock objects - */ -static int -init_bench_rwlock(struct mutex_bench *mb) -{ - struct my_root *root = D_RW(mb->root); - assert(root != nullptr); - - POBJ_ZALLOC(mb->pop, &root->locks, lock_t, - mb->pa->n_locks * sizeof(lock_t)); - if (TOID_IS_NULL(root->locks)) { - perror("POBJ_ZALLOC"); - return -1; - } - - mb->locks = D_RW(root->locks); - assert(mb->locks != nullptr); - - if (!mb->pa->use_system_threads) { - /* initialize PMEM rwlocks */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (PMEMrwlock_internal *)&mb->locks[i]; - p->pmemrwlock.runid = mb->pa->runid_initial_value; - os_rwlock_init(&p->PMEMrwlock_lock); - } - } else { - /* initialize os_thread rwlocks */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (os_rwlock_t *)&mb->locks[i]; - os_rwlock_init(p); - } - } - - return 0; -} - -/* - * exit_bench_rwlock -- destroy the rwlocks and release memory - */ -static int -exit_bench_rwlock(struct mutex_bench *mb) -{ - if (mb->pa->use_system_threads) { - /* deinitialize os_thread mutex objects */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (os_rwlock_t *)&mb->locks[i]; - os_rwlock_destroy(p); - } - } - - POBJ_FREE(&D_RW(mb->root)->locks); - - return 0; -} - -/* - * op_bench_rwlock -- lock and unlock the rwlock object - * - * If requested, increment the run_id of the memory pool. In case of PMEMrwlock - * this will force the rwlock object(s) reinitialization at the lock operation. - */ -static int -op_bench_rwlock(struct mutex_bench *mb) -{ - if (!mb->pa->use_system_threads) { - if (mb->lock_mode == OP_MODE_1BY1) { - bench_operation_1by1( - !mb->pa->use_rdlock - ? pmemobj_rwlock_wrlock_wrapper - : pmemobj_rwlock_rdlock_wrapper, - pmemobj_rwlock_unlock_wrapper, mb, mb->pop); - } else { - bench_operation_all_lock( - !mb->pa->use_rdlock - ? pmemobj_rwlock_wrlock_wrapper - : pmemobj_rwlock_rdlock_wrapper, - pmemobj_rwlock_unlock_wrapper, mb, mb->pop); - } - if (mb->pa->run_id_increment) - mb->pop->run_id += 2; /* must be a multiple of 2 */ - } else { - if (mb->lock_mode == OP_MODE_1BY1) { - bench_operation_1by1( - !mb->pa->use_rdlock ? os_rwlock_wrlock_wrapper - : os_rwlock_rdlock_wrapper, - os_rwlock_unlock_wrapper, mb, nullptr); - } else { - bench_operation_all_lock( - !mb->pa->use_rdlock ? os_rwlock_wrlock_wrapper - : os_rwlock_rdlock_wrapper, - os_rwlock_unlock_wrapper, mb, nullptr); - } - } - return 0; -} - -/* - * init_bench_vmutex -- allocate and initialize mutexes - */ -static int -init_bench_vmutex(struct mutex_bench *mb) -{ - struct my_root *root = D_RW(mb->root); - assert(root != nullptr); - - POBJ_ZALLOC(mb->pop, &root->locks, lock_t, - mb->pa->n_locks * sizeof(lock_t)); - if (TOID_IS_NULL(root->locks)) { - perror("POBJ_ZALLOC"); - return -1; - } - - mb->locks = D_RW(root->locks); - assert(mb->locks != nullptr); - - /* initialize PMEM volatile mutexes */ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (PMEM_volatile_mutex *)&mb->locks[i]; - p->volatile_pmemmutex.runid = mb->pa->runid_initial_value; - volatile_mutex_init(&p->volatile_pmemmutex.mutexp, nullptr); - } - - return 0; -} - -/* - * exit_bench_vmutex -- destroy the mutex objects and release their - * memory - */ -static int -exit_bench_vmutex(struct mutex_bench *mb) -{ - for (unsigned i = 0; i < mb->pa->n_locks; i++) { - auto *p = (PMEM_volatile_mutex *)&mb->locks[i]; - volatile_mutex_destroy(mb->pop, p); - } - - POBJ_FREE(&D_RW(mb->root)->locks); - - return 0; -} - -/* - * op_bench_volatile_mutex -- lock and unlock the mutex object - */ -static int -op_bench_vmutex(struct mutex_bench *mb) -{ - if (mb->lock_mode == OP_MODE_1BY1) { - bench_operation_1by1(volatile_mutex_lock_wrapper, - volatile_mutex_unlock_wrapper, mb, - mb->pop); - } else { - bench_operation_all_lock(volatile_mutex_lock_wrapper, - volatile_mutex_unlock_wrapper, mb, - mb->pop); - } - - if (mb->pa->run_id_increment) - mb->pop->run_id += 2; /* must be a multiple of 2 */ - - return 0; -} - -struct bench_ops benchmark_ops[BENCH_MODE_MAX] = { - {init_bench_mutex, exit_bench_mutex, op_bench_mutex}, - {init_bench_rwlock, exit_bench_rwlock, op_bench_rwlock}, - {init_bench_vmutex, exit_bench_vmutex, op_bench_vmutex}}; - -/* - * operation_mode -- parses command line "--mode" and returns - * proper operation mode - */ -static enum operation_mode -parse_op_mode(const char *arg) -{ - if (strcmp(arg, "1by1") == 0) - return OP_MODE_1BY1; - else if (strcmp(arg, "all-lock") == 0) - return OP_MODE_ALL_LOCK; - else - return OP_MODE_MAX; -} - -/* - * benchmark_mode -- parses command line "--bench_type" and returns - * proper benchmark ops - */ -static struct bench_ops * -parse_benchmark_mode(const char *arg) -{ - if (strcmp(arg, "mutex") == 0) - return &benchmark_ops[BENCH_MODE_MUTEX]; - else if (strcmp(arg, "rwlock") == 0) - return &benchmark_ops[BENCH_MODE_RWLOCK]; - else if (strcmp(arg, "volatile-mutex") == 0) - return &benchmark_ops[BENCH_MODE_VOLATILE_MUTEX]; - else - return nullptr; -} - -/* - * locks_init -- allocates persistent memory, maps it, creates the appropriate - * objects in the allocated memory and initializes them - */ -static int -locks_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - int ret = 0; - size_t poolsize; - - struct mutex_bench *mb = (struct mutex_bench *)malloc(sizeof(*mb)); - if (mb == nullptr) { - perror("malloc"); - return -1; - } - - mb->pa = (struct prog_args *)args->opts; - - mb->lock_mode = parse_op_mode(mb->pa->lock_mode); - if (mb->lock_mode >= OP_MODE_MAX) { - fprintf(stderr, "Invalid mutex mode: %s\n", mb->pa->lock_mode); - errno = EINVAL; - goto err_free_mb; - } - - mb->ops = parse_benchmark_mode(mb->pa->lock_type); - if (mb->ops == nullptr) { - fprintf(stderr, "Invalid benchmark type: %s\n", - mb->pa->lock_type); - errno = EINVAL; - goto err_free_mb; - } - - /* reserve some space for metadata */ - poolsize = mb->pa->n_locks * sizeof(lock_t) + PMEMOBJ_MIN_POOL; - - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < poolsize) { - fprintf(stderr, "file size too large\n"); - goto err_free_mb; - } - - poolsize = 0; - } - - mb->pop = pmemobj_create(args->fname, - POBJ_LAYOUT_NAME(pmembench_lock_layout), - poolsize, args->fmode); - - if (mb->pop == nullptr) { - ret = -1; - perror("pmemobj_create"); - goto err_free_mb; - } - - mb->root = POBJ_ROOT(mb->pop, struct my_root); - assert(!TOID_IS_NULL(mb->root)); - - ret = mb->ops->bench_init(mb); - if (ret != 0) - goto err_free_pop; - - pmembench_set_priv(bench, mb); - - return 0; - -err_free_pop: - pmemobj_close(mb->pop); - -err_free_mb: - free(mb); - return ret; -} - -/* - * locks_exit -- destroys allocated objects and release memory - */ -static int -locks_exit(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - - auto *mb = (struct mutex_bench *)pmembench_get_priv(bench); - assert(mb != nullptr); - - mb->ops->bench_exit(mb); - - pmemobj_close(mb->pop); - free(mb); - - return 0; -} - -/* - * locks_op -- actual benchmark operation - * - * Performs lock and unlock as by the program arguments. - */ -static int -locks_op(struct benchmark *bench, struct operation_info *info) -{ - auto *mb = (struct mutex_bench *)pmembench_get_priv(bench); - assert(mb != nullptr); - assert(mb->pop != nullptr); - assert(!TOID_IS_NULL(mb->root)); - assert(mb->locks != nullptr); - assert(mb->lock_mode < OP_MODE_MAX); - - mb->ops->bench_op(mb); - - return 0; -} - -/* structure to define command line arguments */ -static struct benchmark_clo locks_clo[7]; -static struct benchmark_info locks_info; -CONSTRUCTOR(pmem_locks_constructor) -void -pmem_locks_constructor(void) -{ - locks_clo[0].opt_short = 'p'; - locks_clo[0].opt_long = "use_system_threads"; - locks_clo[0].descr = "Use os_thread locks instead of PMEM, " - "does not matter for volatile mutex"; - locks_clo[0].def = "false"; - locks_clo[0].off = - clo_field_offset(struct prog_args, use_system_threads); - locks_clo[0].type = CLO_TYPE_FLAG; - - locks_clo[1].opt_short = 'm'; - locks_clo[1].opt_long = "numlocks"; - locks_clo[1].descr = "The number of lock objects used " - "for benchmark"; - locks_clo[1].def = "1"; - locks_clo[1].off = clo_field_offset(struct prog_args, n_locks); - locks_clo[1].type = CLO_TYPE_UINT; - locks_clo[1].type_uint.size = clo_field_size(struct prog_args, n_locks); - locks_clo[1].type_uint.base = CLO_INT_BASE_DEC; - locks_clo[1].type_uint.min = 1; - locks_clo[1].type_uint.max = UINT_MAX; - - locks_clo[2].opt_short = 0; - locks_clo[2].opt_long = "mode"; - locks_clo[2].descr = "Locking mode"; - locks_clo[2].type = CLO_TYPE_STR; - locks_clo[2].off = clo_field_offset(struct prog_args, lock_mode); - locks_clo[2].def = "1by1"; - - locks_clo[3].opt_short = 'r'; - locks_clo[3].opt_long = "run_id"; - locks_clo[3].descr = "Increment the run_id of PMEM object " - "pool after each operation"; - locks_clo[3].def = "false"; - locks_clo[3].off = clo_field_offset(struct prog_args, run_id_increment); - locks_clo[3].type = CLO_TYPE_FLAG; - - locks_clo[4].opt_short = 'i'; - locks_clo[4].opt_long = "run_id_init_val"; - locks_clo[4].descr = "Use this value for initializing the " - "run_id of each PMEMmutex object"; - locks_clo[4].def = "2"; - locks_clo[4].off = - clo_field_offset(struct prog_args, runid_initial_value); - locks_clo[4].type = CLO_TYPE_UINT; - - locks_clo[4].type_uint.size = - clo_field_size(struct prog_args, runid_initial_value); - locks_clo[4].type_uint.base = CLO_INT_BASE_DEC; - locks_clo[4].type_uint.min = 0; - locks_clo[4].type_uint.max = UINT64_MAX; - - locks_clo[5].opt_short = 'b'; - locks_clo[5].opt_long = "bench_type"; - locks_clo[5].descr = "The Benchmark type: mutex, " - "rwlock or volatile-mutex"; - locks_clo[5].type = CLO_TYPE_STR; - locks_clo[5].off = clo_field_offset(struct prog_args, lock_type); - locks_clo[5].def = "mutex"; - - locks_clo[6].opt_short = 'R'; - locks_clo[6].opt_long = "rdlock"; - locks_clo[6].descr = "Select read over write lock, only " - "valid when lock_type is \"rwlock\""; - locks_clo[6].type = CLO_TYPE_FLAG; - locks_clo[6].off = clo_field_offset(struct prog_args, use_rdlock); - - locks_info.name = "obj_locks"; - locks_info.brief = "Benchmark for pmem locks operations"; - locks_info.init = locks_init; - locks_info.exit = locks_exit; - locks_info.multithread = false; - locks_info.multiops = true; - locks_info.operation = locks_op; - locks_info.measure_time = true; - locks_info.clos = locks_clo; - locks_info.nclos = ARRAY_SIZE(locks_clo); - locks_info.opts_size = sizeof(struct prog_args); - locks_info.rm_file = true; - locks_info.allow_poolset = true; - REGISTER_BENCHMARK(locks_info); -}; diff --git a/src/benchmarks/obj_pmalloc.cpp b/src/benchmarks/obj_pmalloc.cpp deleted file mode 100644 index c0efdffd8b..0000000000 --- a/src/benchmarks/obj_pmalloc.cpp +++ /dev/null @@ -1,504 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2024, Intel Corporation */ - -/* - * obj_pmalloc.cpp -- pmalloc benchmarks definition - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" -#include "memops.h" -#include "os.h" -#include "pmalloc.h" -#include "poolset_util.hpp" -#include "valgrind_internal.h" - -/* - * The factor used for PMEM pool size calculation, accounts for metadata, - * fragmentation and etc. - */ -#define FACTOR 1.9f - -/* The minimum allocation size that pmalloc can perform */ -#define ALLOC_MIN_SIZE 64 - -/* OOB and allocation header size */ -#define OOB_HEADER_SIZE 64 - -/* - * prog_args - command line parsed arguments - */ -struct prog_args { - size_t minsize; /* minimum size for random allocation size */ - bool use_random_size; /* if set, use random size allocations */ - unsigned seed; /* PRNG seed */ -}; - -POBJ_LAYOUT_BEGIN(pmalloc_layout); -POBJ_LAYOUT_ROOT(pmalloc_layout, struct my_root); -POBJ_LAYOUT_TOID(pmalloc_layout, uint64_t); -POBJ_LAYOUT_END(pmalloc_layout); - -/* - * my_root - root object - */ -struct my_root { - TOID(uint64_t) offs; /* vector of the allocated object offsets */ -}; - -/* - * obj_bench - variables used in benchmark, passed within functions - */ -struct obj_bench { - PMEMobjpool *pop; /* persistent pool handle */ - struct prog_args *pa; /* prog_args structure */ - size_t *sizes; /* sizes for allocations */ - TOID(struct my_root) root; /* root object's OID */ - uint64_t *offs; /* pointer to the vector of offsets */ -}; - -/* - * obj_init -- common part of the benchmark initialization for pmalloc and - * pfree. It allocates the PMEM memory pool and the necessary offset vector. - */ -static int -obj_init(struct benchmark *bench, struct benchmark_args *args) -{ - struct my_root *root = nullptr; - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - char path[PATH_MAX]; - if (util_safe_strcpy(path, args->fname, sizeof(path)) != 0) - return -1; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - if (((struct prog_args *)(args->opts))->minsize >= args->dsize) { - fprintf(stderr, "Wrong params - allocation size\n"); - return -1; - } - - auto *ob = (struct obj_bench *)malloc(sizeof(struct obj_bench)); - if (ob == nullptr) { - perror("malloc"); - return -1; - } - pmembench_set_priv(bench, ob); - - ob->pa = (struct prog_args *)args->opts; - - size_t n_ops_total = args->n_ops_per_thread * args->n_threads; - assert(n_ops_total != 0); - - /* Create pmemobj pool. */ - size_t alloc_size = args->dsize; - if (alloc_size < ALLOC_MIN_SIZE) - alloc_size = ALLOC_MIN_SIZE; - - /* For data objects */ - size_t poolsize = PMEMOBJ_MIN_POOL + - (n_ops_total * (alloc_size + OOB_HEADER_SIZE)) - /* for offsets */ - + n_ops_total * sizeof(uint64_t); - - /* multiply by FACTOR for metadata, fragmentation, etc. */ - poolsize = (size_t)(poolsize * FACTOR); - - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < poolsize) { - fprintf(stderr, "file size too large\n"); - goto free_ob; - } - poolsize = 0; - } else if (poolsize < PMEMOBJ_MIN_POOL) { - poolsize = PMEMOBJ_MIN_POOL; - } - - if (args->is_dynamic_poolset) { - int ret = dynamic_poolset_create(args->fname, poolsize); - if (ret == -1) - goto free_ob; - - if (util_safe_strcpy(path, POOLSET_PATH, sizeof(path)) != 0) - goto free_ob; - - poolsize = 0; - } - - ob->pop = pmemobj_create(path, POBJ_LAYOUT_NAME(pmalloc_layout), - poolsize, args->fmode); - if (ob->pop == nullptr) { - fprintf(stderr, "%s\n", pmemobj_errormsg()); - goto free_ob; - } - - ob->root = POBJ_ROOT(ob->pop, struct my_root); - if (TOID_IS_NULL(ob->root)) { - fprintf(stderr, "POBJ_ROOT: %s\n", pmemobj_errormsg()); - goto free_pop; - } - - root = D_RW(ob->root); - assert(root != nullptr); - POBJ_ZALLOC(ob->pop, &root->offs, uint64_t, - n_ops_total * sizeof(PMEMoid)); - if (TOID_IS_NULL(root->offs)) { - fprintf(stderr, "POBJ_ZALLOC off_vect: %s\n", - pmemobj_errormsg()); - goto free_pop; - } - - ob->offs = D_RW(root->offs); - - ob->sizes = (size_t *)malloc(n_ops_total * sizeof(size_t)); - if (ob->sizes == nullptr) { - fprintf(stderr, "malloc rand size vect err\n"); - goto free_pop; - } - - if (ob->pa->use_random_size) { - size_t width = args->dsize - ob->pa->minsize; - for (size_t i = 0; i < n_ops_total; i++) { - auto hr = (uint32_t)os_rand_r(&ob->pa->seed); - auto lr = (uint32_t)os_rand_r(&ob->pa->seed); - uint64_t r64 = (uint64_t)hr << 32 | lr; - ob->sizes[i] = r64 % width + ob->pa->minsize; - } - } else { - for (size_t i = 0; i < n_ops_total; i++) - ob->sizes[i] = args->dsize; - } - - return 0; - -free_pop: - pmemobj_close(ob->pop); - -free_ob: - free(ob); - return -1; -} - -/* - * obj_exit -- common part for the exit function for pmalloc and pfree - * benchmarks. It frees the allocated offset vector and the memory pool. - */ -static int -obj_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - free(ob->sizes); - - POBJ_FREE(&D_RW(ob->root)->offs); - pmemobj_close(ob->pop); - - return 0; -} - -/* - * pmalloc_init -- initialization for the pmalloc benchmark. Performs only the - * common initialization. - */ -static int -pmalloc_init(struct benchmark *bench, struct benchmark_args *args) -{ - return obj_init(bench, args); -} - -/* - * pmalloc_op -- actual benchmark operation. Performs the pmalloc allocations. - */ -static int -pmalloc_op(struct benchmark *bench, struct operation_info *info) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - uint64_t i = info->index + - info->worker->index * info->args->n_ops_per_thread; - - int ret = pmalloc(ob->pop, &ob->offs[i], ob->sizes[i], 0, 0); - if (ret) { - perror("pmalloc"); - return ret; - } - - return 0; -} - -struct pmix_worker { - size_t nobjects; - size_t shuffle_start; - rng_t rng; -}; - -/* - * pmix_worker_init -- initialization of the worker structure - */ -static int -pmix_worker_init(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - struct pmix_worker *w = (struct pmix_worker *)calloc(1, sizeof(*w)); - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - if (w == nullptr) - return -1; - - randomize_r(&w->rng, ob->pa->seed); - - worker->priv = w; - - return 0; -} - -/* - * pmix_worker_fini -- destruction of the worker structure - */ -static void -pmix_worker_fini(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *w = (struct pmix_worker *)worker->priv; - free(w); -} - -/* - * shuffle_objects -- randomly shuffle elements on a list - * - * Ideally, we wouldn't count the time this function takes, but for all - * practical purposes this is fast enough and isn't visible on the results. - * Just make sure the amount of objects to shuffle is not large. - */ -static void -shuffle_objects(uint64_t *objects, size_t start, size_t nobjects, rng_t *rng) -{ - uint64_t tmp; - size_t dest; - for (size_t n = start; n < nobjects; ++n) { - dest = RRAND_R(rng, nobjects - 1, 0); - tmp = objects[n]; - objects[n] = objects[dest]; - objects[dest] = tmp; - } -} - -#define FREE_PCT 10 -#define FREE_OPS 10 - -/* - * pmix_op -- mixed workload benchmark - */ -static int -pmix_op(struct benchmark *bench, struct operation_info *info) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - auto *w = (struct pmix_worker *)info->worker->priv; - - uint64_t idx = info->worker->index * info->args->n_ops_per_thread; - - uint64_t *objects = &ob->offs[idx]; - - if (w->nobjects > FREE_OPS && FREE_PCT > RRAND_R(&w->rng, 100, 0)) { - shuffle_objects(objects, w->shuffle_start, w->nobjects, - &w->rng); - - for (int i = 0; i < FREE_OPS; ++i) { - uint64_t off = objects[--w->nobjects]; - pfree(ob->pop, &off); - } - w->shuffle_start = w->nobjects; - } else { - int ret = pmalloc(ob->pop, &objects[w->nobjects++], - ob->sizes[idx + info->index], 0, 0); - if (ret) { - fprintf(stderr, "pmalloc ret: %d\n", ret); - return ret; - } - } - - return 0; -} - -/* - * pmalloc_exit -- the end of the pmalloc benchmark. Frees the memory allocated - * during pmalloc_op and performs the common exit operations. - */ -static int -pmalloc_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - for (size_t i = 0; i < args->n_ops_per_thread * args->n_threads; i++) { - if (ob->offs[i]) - pfree(ob->pop, &ob->offs[i]); - } - - return obj_exit(bench, args); -} - -/* - * pfree_init -- initialization for the pfree benchmark. Performs the common - * initialization and allocates the memory to be freed during pfree_op. - */ -static int -pfree_init(struct benchmark *bench, struct benchmark_args *args) -{ - int ret = obj_init(bench, args); - if (ret) - return ret; - - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - for (size_t i = 0; i < args->n_ops_per_thread * args->n_threads; i++) { - ret = pmalloc(ob->pop, &ob->offs[i], ob->sizes[i], 0, 0); - if (ret) { - fprintf(stderr, "pmalloc at idx %" PRIu64 " ret: %s\n", - i, pmemobj_errormsg()); - /* free the allocated memory */ - while (i != 0) { - pfree(ob->pop, &ob->offs[i - 1]); - i--; - } - obj_exit(bench, args); - return ret; - } - } - - return 0; -} - -/* - * pmalloc_op -- actual benchmark operation. Performs the pfree operation. - */ -static int -pfree_op(struct benchmark *bench, struct operation_info *info) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - uint64_t i = info->index + - info->worker->index * info->args->n_ops_per_thread; - - pfree(ob->pop, &ob->offs[i]); - - return 0; -} - -/* command line options definition */ -static struct benchmark_clo pmalloc_clo[3]; -/* - * Stores information about pmalloc benchmark. - */ -static struct benchmark_info pmalloc_info; -/* - * Stores information about pfree benchmark. - */ -static struct benchmark_info pfree_info; -/* - * Stores information about pmix benchmark. - */ -static struct benchmark_info pmix_info; - -CONSTRUCTOR(obj_pmalloc_constructor) -void -obj_pmalloc_constructor(void) -{ - pmalloc_clo[0].opt_short = 'r'; - pmalloc_clo[0].opt_long = "random"; - pmalloc_clo[0].descr = "Use random size allocations - " - "from min-size to data-size"; - pmalloc_clo[0].off = - clo_field_offset(struct prog_args, use_random_size); - pmalloc_clo[0].type = CLO_TYPE_FLAG; - - pmalloc_clo[1].opt_short = 'm'; - pmalloc_clo[1].opt_long = "min-size"; - pmalloc_clo[1].descr = "Minimum size of allocation for " - "random mode"; - pmalloc_clo[1].type = CLO_TYPE_UINT; - pmalloc_clo[1].off = clo_field_offset(struct prog_args, minsize); - pmalloc_clo[1].def = "1"; - pmalloc_clo[1].type_uint.size = - clo_field_size(struct prog_args, minsize); - pmalloc_clo[1].type_uint.base = CLO_INT_BASE_DEC; - pmalloc_clo[1].type_uint.min = 1; - pmalloc_clo[1].type_uint.max = UINT64_MAX; - - pmalloc_clo[2].opt_short = 'S'; - pmalloc_clo[2].opt_long = "seed"; - pmalloc_clo[2].descr = "Random mode seed value"; - pmalloc_clo[2].off = clo_field_offset(struct prog_args, seed); - pmalloc_clo[2].def = "1"; - pmalloc_clo[2].type = CLO_TYPE_UINT; - pmalloc_clo[2].type_uint.size = clo_field_size(struct prog_args, seed); - pmalloc_clo[2].type_uint.base = CLO_INT_BASE_DEC; - pmalloc_clo[2].type_uint.min = 1; - pmalloc_clo[2].type_uint.max = UINT_MAX; - - pmalloc_info.name = "pmalloc", - pmalloc_info.brief = "Benchmark for internal pmalloc() " - "operation"; - pmalloc_info.init = pmalloc_init; - pmalloc_info.exit = pmalloc_exit; - pmalloc_info.multithread = true; - pmalloc_info.multiops = true; - pmalloc_info.operation = pmalloc_op; - pmalloc_info.measure_time = true; - pmalloc_info.clos = pmalloc_clo; - pmalloc_info.nclos = ARRAY_SIZE(pmalloc_clo); - pmalloc_info.opts_size = sizeof(struct prog_args); - pmalloc_info.rm_file = true; - pmalloc_info.allow_poolset = true; - REGISTER_BENCHMARK(pmalloc_info); - - pfree_info.name = "pfree"; - pfree_info.brief = "Benchmark for internal pfree() " - "operation"; - pfree_info.init = pfree_init; - - pfree_info.exit = pmalloc_exit; /* same as for pmalloc */ - pfree_info.multithread = true; - pfree_info.multiops = true; - pfree_info.operation = pfree_op; - pfree_info.measure_time = true; - pfree_info.clos = pmalloc_clo; - pfree_info.nclos = ARRAY_SIZE(pmalloc_clo); - pfree_info.opts_size = sizeof(struct prog_args); - pfree_info.rm_file = true; - pfree_info.allow_poolset = true; - REGISTER_BENCHMARK(pfree_info); - - pmix_info.name = "pmix"; - pmix_info.brief = "Benchmark for mixed alloc/free workload"; - pmix_info.init = pmalloc_init; - - pmix_info.exit = pmalloc_exit; /* same as for pmalloc */ - pmix_info.multithread = true; - pmix_info.multiops = true; - pmix_info.operation = pmix_op; - pmix_info.init_worker = pmix_worker_init; - pmix_info.free_worker = pmix_worker_fini; - pmix_info.measure_time = true; - pmix_info.clos = pmalloc_clo; - pmix_info.nclos = ARRAY_SIZE(pmalloc_clo); - pmix_info.opts_size = sizeof(struct prog_args); - pmix_info.rm_file = true; - pmix_info.allow_poolset = true; - REGISTER_BENCHMARK(pmix_info); -}; diff --git a/src/benchmarks/perf.cfg b/src/benchmarks/perf.cfg deleted file mode 100644 index ede7ac6536..0000000000 --- a/src/benchmarks/perf.cfg +++ /dev/null @@ -1,102 +0,0 @@ -[global] -file = testfile -repeats = 3 - -# pmemobj_tx_alloc(size = 256) vs threads -[obj_tx_alloc_small_v_thread] -bench = obj_tx_alloc -group = pmemobj -ops-per-thread = 6000000 -threads = 1:*2:32 -type-number = per-thread -data-size = 256 - -# pmemobj_tx_alloc(size = 128k) vs threads -[obj_tx_alloc_huge_v_threads] -bench = obj_tx_alloc -group = pmemobj -ops-per-thread = 11000 -threads = 1:+1:32 -type-number = per-thread -data-size = 131072 - -# pmemobj_tx_alloc vs data-size -[obj_tx_alloc_v_data_size] -bench = obj_tx_alloc -group = pmemobj -ops-per-thread = 50000 -threads = 1 -type-number = one -data-size = 64:*2:32768 - -# pmalloc (size = 100) vs threads -[obj_pmalloc_small_v_threads] -bench = pmalloc -group = pmemobj -ops-per-thread = 2000000 -threads = 1:*2:32 -data-size = 100 - -# pmalloc (size = 128k) vs threads -[obj_pmalloc_huge_v_threads] -bench = pmalloc -group = pmemobj -ops-per-thread = 11000 -threads = 1:+1:32 -data-size = 131072 - -# pmalloc vs data-size -[obj_pmalloc_v_data_size] -bench = pmalloc -group = pmemobj -ops-per-thread = 50000 -threads = 1 -data-size = 64:*2:32768 - -# btree_map_insert -[obj_btree_map_insert] -bench = map_insert -group = pmemobj -ops-per-thread = 5000000 -type = btree -threads = 1 - -# ctree_map_insert -[obj_ctree_map_insert] -bench = map_insert -group = pmemobj -ops-per-thread = 5000000 -type = ctree -threads = 1 - -# rtree_map_insert -[obj_rtree_map_insert] -bench = map_insert -group = pmemobj -ops-per-thread = 1000000 -type = rtree -threads = 1 - -# rbtree_map_insert -[obj_rbtree_map_insert] -bench = map_insert -group = pmemobj -ops-per-thread = 5000000 -type = rbtree -threads = 1 - -# hashmap_tx_map_insert -[obj_hashmap_tx_map_insert] -bench = map_insert -group = pmemobj -ops-per-thread = 5000000 -type = hashmap_tx -threads = 1 - -# hashmap_atomic_map_insert -[obj_hashmap_atomic_map_insert] -bench = map_insert -group = pmemobj -ops-per-thread = 5000000 -type = hashmap_atomic -threads = 1 diff --git a/src/benchmarks/pmem_flush.cpp b/src/benchmarks/pmem_flush.cpp deleted file mode 100644 index cfdfbbafc3..0000000000 --- a/src/benchmarks/pmem_flush.cpp +++ /dev/null @@ -1,540 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2020, Intel Corporation */ - -/* - * pmem_flush.cpp -- benchmark implementation for pmem_persist and pmem_msync - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" - -#define PAGE_4K ((uintptr_t)1 << 12) -#define PAGE_2M ((uintptr_t)1 << 21) - -/* - * align_addr -- round addr down to given boundary - */ -static void * -align_addr(void *addr, uintptr_t align) -{ - return (char *)((uintptr_t)addr & ~(align - 1)); -} - -/* - * align_len -- increase len by the amount we gain when we round addr down - */ -static size_t -align_len(size_t len, void *addr, uintptr_t align) -{ - return len + ((uintptr_t)addr & (align - 1)); -} - -/* - * roundup_len -- increase len by the amount we gain when we round addr down, - * then round up to the nearest multiple of 4K - */ -static size_t -roundup_len(size_t len, void *addr, uintptr_t align) -{ - return (align_len(len, addr, align) + align - 1) & ~(align - 1); -} - -/* - * pmem_args -- benchmark specific arguments - */ -struct pmem_args { - char *operation; /* msync, dummy_msync, persist, ... */ - char *mode; /* stat, seq, rand */ - bool no_warmup; /* don't do warmup */ -}; - -/* - * pmem_bench -- benchmark context - */ -struct pmem_bench { - uint64_t *offsets; /* write offsets */ - size_t n_offsets; /* number of elements in offsets array */ - size_t fsize; /* The size of the allocated PMEM */ - - struct pmem_args *pargs; /* prog_args structure */ - - void *pmem_addr; /* PMEM base address */ - size_t pmem_len; /* length of PMEM mapping */ - - void *invalid_addr; /* invalid pages */ - void *nondirty_addr; /* non-dirty pages */ - - void *pmem_addr_aligned; /* PMEM pages - 2M aligned */ - void *invalid_addr_aligned; /* invalid pages - 2M aligned */ - void *nondirty_addr_aligned; /* non-dirty pages - 2M aligned */ - - /* the actual benchmark operation */ - int (*func_op)(struct pmem_bench *pmb, void *addr, size_t len); -}; - -/* - * mode_seq -- if copy mode is sequential, returns index of a chunk. - */ -static uint64_t -mode_seq(struct pmem_bench *pmb, uint64_t index) -{ - return index; -} - -/* - * mode_stat -- if mode is static, the offset is always 0 - */ -static uint64_t -mode_stat(struct pmem_bench *pmb, uint64_t index) -{ - return 0; -} - -/* - * mode_rand -- if mode is random, returns index of a random chunk - */ -static uint64_t -mode_rand(struct pmem_bench *pmb, uint64_t index) -{ - return rand() % pmb->n_offsets; -} - -/* - * operation_mode -- the mode of the copy process - * - * * static - write always the same chunk, - * * sequential - write chunk by chunk, - * * random - write to chunks selected randomly. - */ -struct op_mode { - const char *mode; - uint64_t (*func_mode)(struct pmem_bench *pmb, uint64_t index); -}; - -static struct op_mode modes[] = { - {"stat", mode_stat}, - {"seq", mode_seq}, - {"rand", mode_rand}, -}; - -#define MODES (sizeof(modes) / sizeof(modes[0])) - -/* - * parse_op_mode -- parses command line "--mode" - * and returns proper operation mode index. - */ -static int -parse_op_mode(const char *arg) -{ - for (unsigned i = 0; i < MODES; i++) { - if (strcmp(arg, modes[i].mode) == 0) - return i; - } - return -1; -} - -/* - * flush_noop -- dummy flush, does nothing - */ -static int -flush_noop(struct pmem_bench *pmb, void *addr, size_t len) -{ - return 0; -} - -/* - * flush_persist -- flush data to persistence using pmem_persist() - */ -static int -flush_persist(struct pmem_bench *pmb, void *addr, size_t len) -{ - pmem_persist(addr, len); - return 0; -} - -/* - * flush_persist_4K -- always flush entire 4K page(s) using pmem_persist() - */ -static int -flush_persist_4K(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_4K); - len = roundup_len(len, addr, PAGE_4K); - - pmem_persist(ptr, len); - return 0; -} - -/* - * flush_persist_2M -- always flush entire 2M page(s) using pmem_persist() - */ -static int -flush_persist_2M(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_2M); - len = roundup_len(len, addr, PAGE_2M); - - pmem_persist(ptr, len); - return 0; -} - -/* - * flush_msync -- flush data to persistence using pmem_msync() - */ -static int -flush_msync(struct pmem_bench *pmb, void *addr, size_t len) -{ - pmem_msync(addr, len); - return 0; -} - -/* - * flush_msync_async -- emulate dummy msync() using MS_ASYNC flag - */ -static int -flush_msync_async(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_4K); - len = align_len(len, addr, PAGE_4K); - - msync(ptr, len, MS_ASYNC); - return 0; -} - -/* - * flush_msync_0 -- emulate dummy msync() using zero length - */ -static int -flush_msync_0(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_4K); - (void)len; - - msync(ptr, 0, MS_SYNC); - return 0; -} - -/* - * flush_persist_4K_msync_0 -- emulate msync() that only flushes CPU cache - * - * Do flushing in user space (4K pages) + dummy syscall. - */ -static int -flush_persist_4K_msync_0(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_4K); - len = roundup_len(len, addr, PAGE_4K); - - pmem_persist(ptr, len); - msync(ptr, 0, MS_SYNC); - return 0; -} - -/* - * flush_persist_2M_msync_0 -- emulate msync() that only flushes CPU cache - * - * Do flushing in user space (2M pages) + dummy syscall. - */ -static int -flush_persist_2M_msync_0(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_2M); - len = roundup_len(len, addr, PAGE_2M); - - pmem_persist(ptr, len); - msync(ptr, 0, MS_SYNC); - return 0; -} - -/* - * flush_msync_err -- emulate dummy msync() using invalid flags - */ -static int -flush_msync_err(struct pmem_bench *pmb, void *addr, size_t len) -{ - void *ptr = align_addr(addr, PAGE_4K); - len = align_len(len, addr, PAGE_4K); - - msync(ptr, len, MS_SYNC | MS_ASYNC); - return 0; -} - -/* - * flush_msync_nodirty -- call msync() on non-dirty pages - */ -static int -flush_msync_nodirty(struct pmem_bench *pmb, void *addr, size_t len) -{ - uintptr_t uptr = (uintptr_t)addr - (uintptr_t)pmb->pmem_addr_aligned; - uptr += (uintptr_t)pmb->nondirty_addr_aligned; - - void *ptr = align_addr((void *)uptr, PAGE_4K); - len = align_len(len, (void *)uptr, PAGE_4K); - - pmem_msync(ptr, len); - return 0; -} - -/* - * flush_msync_invalid -- emulate dummy msync() using invalid address - */ -static int -flush_msync_invalid(struct pmem_bench *pmb, void *addr, size_t len) -{ - uintptr_t uptr = (uintptr_t)addr - (uintptr_t)pmb->pmem_addr_aligned; - uptr += (uintptr_t)pmb->invalid_addr_aligned; - - void *ptr = align_addr((void *)uptr, PAGE_4K); - len = align_len(len, (void *)uptr, PAGE_4K); - - pmem_msync(ptr, len); - return 0; -} - -struct op { - const char *opname; - int (*func_op)(struct pmem_bench *pmb, void *addr, size_t len); -}; - -static struct op ops[] = { - {"noop", flush_noop}, - {"persist", flush_persist}, - {"persist_4K", flush_persist_4K}, - {"persist_2M", flush_persist_2M}, - {"msync", flush_msync}, - {"msync_0", flush_msync_0}, - {"msync_err", flush_msync_err}, - {"persist_4K_msync_0", flush_persist_4K_msync_0}, - {"persist_2M_msync_0", flush_persist_2M_msync_0}, - {"msync_async", flush_msync_async}, - {"msync_nodirty", flush_msync_nodirty}, - {"msync_invalid", flush_msync_invalid}, -}; - -#define NOPS (sizeof(ops) / sizeof(ops[0])) - -/* - * parse_op_type -- parses command line "--operation" argument - * and returns proper operation type. - */ -static int -parse_op_type(const char *arg) -{ - for (unsigned i = 0; i < NOPS; i++) { - if (strcmp(arg, ops[i].opname) == 0) - return i; - } - return -1; -} - -/* - * pmem_flush_init -- benchmark initialization - * - * Parses command line arguments, allocates persistent memory, and maps it. - */ -static int -pmem_flush_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - size_t file_size = 0; - int flags = 0; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - uint64_t (*func_mode)(struct pmem_bench * pmb, uint64_t index); - - auto *pmb = (struct pmem_bench *)malloc(sizeof(struct pmem_bench)); - assert(pmb != nullptr); - - pmb->pargs = (struct pmem_args *)args->opts; - assert(pmb->pargs != nullptr); - - int i = parse_op_type(pmb->pargs->operation); - if (i == -1) { - fprintf(stderr, "wrong operation: %s\n", pmb->pargs->operation); - goto err_free_pmb; - } - pmb->func_op = ops[i].func_op; - - pmb->n_offsets = args->n_ops_per_thread * args->n_threads; - - pmb->fsize = pmb->n_offsets * args->dsize + (2 * PAGE_2M); - - /* round up to 2M boundary */ - pmb->fsize = (pmb->fsize + PAGE_2M - 1) & ~(PAGE_2M - 1); - - i = parse_op_mode(pmb->pargs->mode); - if (i == -1) { - fprintf(stderr, "wrong mode: %s\n", pmb->pargs->mode); - goto err_free_pmb; - } - func_mode = modes[i].func_mode; - - /* populate offsets array */ - assert(pmb->n_offsets != 0); - pmb->offsets = (size_t *)malloc(pmb->n_offsets * sizeof(*pmb->offsets)); - assert(pmb->offsets != nullptr); - - for (size_t i = 0; i < pmb->n_offsets; ++i) - pmb->offsets[i] = func_mode(pmb, i); - - if (type != TYPE_DEVDAX) { - file_size = pmb->fsize; - flags = PMEM_FILE_CREATE | PMEM_FILE_EXCL; - } - - /* create a pmem file and memory map it */ - pmb->pmem_addr = pmem_map_file(args->fname, file_size, flags, - args->fmode, &pmb->pmem_len, nullptr); - - if (pmb->pmem_addr == nullptr) { - perror("pmem_map_file"); - goto err_free_pmb; - } - - pmb->nondirty_addr = mmap(nullptr, pmb->fsize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - - if (pmb->nondirty_addr == MAP_FAILED) { - perror("mmap(1)"); - goto err_unmap1; - } - - pmb->invalid_addr = mmap(nullptr, pmb->fsize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - - if (pmb->invalid_addr == MAP_FAILED) { - perror("mmap(2)"); - goto err_unmap2; - } - munmap(pmb->invalid_addr, pmb->fsize); - - pmb->pmem_addr_aligned = - (void *)(((uintptr_t)pmb->pmem_addr + PAGE_2M - 1) & - ~(PAGE_2M - 1)); - - pmb->nondirty_addr_aligned = - (void *)(((uintptr_t)pmb->nondirty_addr + PAGE_2M - 1) & - ~(PAGE_2M - 1)); - - pmb->invalid_addr_aligned = - (void *)(((uintptr_t)pmb->invalid_addr + PAGE_2M - 1) & - ~(PAGE_2M - 1)); - - pmembench_set_priv(bench, pmb); - - if (!pmb->pargs->no_warmup) { - size_t off; - for (off = 0; off < pmb->fsize - PAGE_2M; off += PAGE_4K) { - *(int *)((char *)pmb->pmem_addr_aligned + off) = 0; - *(int *)((char *)pmb->nondirty_addr_aligned + off) = 0; - } - } - - return 0; - -err_unmap2: - munmap(pmb->nondirty_addr, pmb->fsize); -err_unmap1: - pmem_unmap(pmb->pmem_addr, pmb->pmem_len); -err_free_pmb: - free(pmb); - - return -1; -} - -/* - * pmem_flush_exit -- benchmark cleanup - */ -static int -pmem_flush_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *pmb = (struct pmem_bench *)pmembench_get_priv(bench); - pmem_unmap(pmb->pmem_addr, pmb->fsize); - munmap(pmb->nondirty_addr, pmb->fsize); - free(pmb); - return 0; -} - -/* - * pmem_flush_operation -- actual benchmark operation - */ -static int -pmem_flush_operation(struct benchmark *bench, struct operation_info *info) -{ - auto *pmb = (struct pmem_bench *)pmembench_get_priv(bench); - - size_t op_idx = info->index; - assert(op_idx < pmb->n_offsets); - - uint64_t chunk_idx = pmb->offsets[op_idx]; - void *addr = - (char *)pmb->pmem_addr_aligned + chunk_idx * info->args->dsize; - - /* store + flush */ - *(int *)addr = *(int *)addr + 1; - pmb->func_op(pmb, addr, info->args->dsize); - return 0; -} - -/* structure to define command line arguments */ -static struct benchmark_clo pmem_flush_clo[3]; -/* Stores information about benchmark. */ -static struct benchmark_info pmem_flush_bench; -CONSTRUCTOR(pmem_flush_constructor) -void -pmem_flush_constructor(void) -{ - pmem_flush_clo[0].opt_short = 'o'; - pmem_flush_clo[0].opt_long = "operation"; - pmem_flush_clo[0].descr = "Operation type - persist," - " msync, ..."; - pmem_flush_clo[0].type = CLO_TYPE_STR; - pmem_flush_clo[0].off = clo_field_offset(struct pmem_args, operation); - pmem_flush_clo[0].def = "noop"; - - pmem_flush_clo[1].opt_short = 0; - pmem_flush_clo[1].opt_long = "mode"; - pmem_flush_clo[1].descr = "mode - stat, seq or rand"; - pmem_flush_clo[1].type = CLO_TYPE_STR; - pmem_flush_clo[1].off = clo_field_offset(struct pmem_args, mode); - pmem_flush_clo[1].def = "stat"; - - pmem_flush_clo[2].opt_short = 'w'; - pmem_flush_clo[2].opt_long = "no-warmup"; - pmem_flush_clo[2].descr = "Don't do warmup"; - pmem_flush_clo[2].type = CLO_TYPE_FLAG; - pmem_flush_clo[2].off = clo_field_offset(struct pmem_args, no_warmup); - - pmem_flush_bench.name = "pmem_flush"; - pmem_flush_bench.brief = "Benchmark for pmem_msync() " - "and pmem_persist()"; - pmem_flush_bench.init = pmem_flush_init; - pmem_flush_bench.exit = pmem_flush_exit; - pmem_flush_bench.multithread = true; - pmem_flush_bench.multiops = true; - pmem_flush_bench.operation = pmem_flush_operation; - pmem_flush_bench.measure_time = true; - pmem_flush_bench.clos = pmem_flush_clo; - pmem_flush_bench.nclos = ARRAY_SIZE(pmem_flush_clo); - pmem_flush_bench.opts_size = sizeof(struct pmem_args); - pmem_flush_bench.rm_file = true; - pmem_flush_bench.allow_poolset = false; - REGISTER_BENCHMARK(pmem_flush_bench); -} diff --git a/src/benchmarks/pmem_memcpy.cpp b/src/benchmarks/pmem_memcpy.cpp deleted file mode 100644 index 12a2166c98..0000000000 --- a/src/benchmarks/pmem_memcpy.cpp +++ /dev/null @@ -1,613 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2019, Intel Corporation */ - -/* - * pmem_memcpy.cpp -- benchmark implementation for pmem_memcpy - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" - -#define FLUSH_ALIGN 64 - -#define MAX_OFFSET (FLUSH_ALIGN - 1) - -struct pmem_bench; - -typedef size_t (*offset_fn)(struct pmem_bench *pmb, - struct operation_info *info); - -/* - * pmem_args -- benchmark specific arguments - */ -struct pmem_args { - /* - * Defines the copy operation direction. Whether it is - * writing from RAM to PMEM (for argument value "write") - * or PMEM to RAM (for argument value "read"). - */ - char *operation; - - /* - * The source address offset used to test pmem_memcpy() - * performance when source address is not aligned. - */ - size_t src_off; - - /* - * The destination address offset used to test - * pmem_memcpy() performance when destination address - * is not aligned. - */ - size_t dest_off; - - /* The size of data chunk. */ - size_t chunk_size; - - /* - * Specifies the order in which data chunks are selected - * to be copied. There are three modes supported: - * stat, seq, rand. - */ - char *src_mode; - - /* - * Specifies the order in which data chunks are written - * to the destination address. There are three modes - * supported: stat, seq, rand. - */ - char *dest_mode; - - /* - * When this flag is set to true, PMEM is not used. - * This option is useful, when comparing performance - * of pmem_memcpy() function to regular memcpy(). - */ - bool memcpy; - - /* - * When this flag is set to true, pmem_persist() - * function is used, otherwise pmem_flush() is performed. - */ - bool persist; - - /* do not do warmup */ - bool no_warmup; -}; - -/* - * pmem_bench -- benchmark context - */ -struct pmem_bench { - /* random offsets */ - unsigned *rand_offsets; - - /* number of elements in randoms array */ - size_t n_rand_offsets; - - /* The size of the allocated PMEM */ - size_t fsize; - - /* The size of the allocated buffer */ - size_t bsize; - - /* Pointer to the allocated volatile memory */ - unsigned char *buf; - - /* Pointer to the allocated PMEM */ - unsigned char *pmem_addr; - - /* - * This field gets 'buf' or 'pmem_addr' fields assigned, - * depending on the prog_args operation direction. - */ - unsigned char *src_addr; - - /* - * This field gets 'buf' or 'pmem_addr' fields assigned, - * depending on the prog_args operation direction. - */ - unsigned char *dest_addr; - - /* Stores prog_args structure */ - struct pmem_args *pargs; - - /* - * Function which returns src offset. Matches src_mode. - */ - offset_fn func_src; - - /* - * Function which returns dst offset. Matches dst_mode. - */ - offset_fn func_dest; - - /* - * The actual operation performed based on benchmark specific - * arguments. - */ - int (*func_op)(void *dest, void *source, size_t len); -}; - -/* - * operation_type -- type of operation relative to persistent memory - */ -enum operation_type { OP_TYPE_UNKNOWN, OP_TYPE_READ, OP_TYPE_WRITE }; - -/* - * operation_mode -- the mode of the copy process - * - * * static - read/write always the same chunk, - * * sequential - read/write chunk by chunk, - * * random - read/write to chunks selected randomly. - * - * It is used to determine source mode as well as the destination mode. - */ -enum operation_mode { - OP_MODE_UNKNOWN, - OP_MODE_STAT, - OP_MODE_SEQ, - OP_MODE_RAND -}; - -/* - * parse_op_type -- parses command line "--operation" argument - * and returns proper operation type. - */ -static enum operation_type -parse_op_type(const char *arg) -{ - if (strcmp(arg, "read") == 0) - return OP_TYPE_READ; - else if (strcmp(arg, "write") == 0) - return OP_TYPE_WRITE; - else - return OP_TYPE_UNKNOWN; -} - -/* - * parse_op_mode -- parses command line "--src-mode" or "--dest-mode" - * and returns proper operation mode. - */ -static enum operation_mode -parse_op_mode(const char *arg) -{ - if (strcmp(arg, "stat") == 0) - return OP_MODE_STAT; - else if (strcmp(arg, "seq") == 0) - return OP_MODE_SEQ; - else if (strcmp(arg, "rand") == 0) - return OP_MODE_RAND; - else - return OP_MODE_UNKNOWN; -} - -/* - * mode_seq -- if copy mode is sequential mode_seq() returns - * index of a chunk. - */ -static uint64_t -mode_seq(struct pmem_bench *pmb, struct operation_info *info) -{ - return info->args->n_ops_per_thread * info->worker->index + info->index; -} - -/* - * mode_stat -- if mode is static, the offset is always 0, - * as only one block is used. - */ -static uint64_t -mode_stat(struct pmem_bench *pmb, struct operation_info *info) -{ - return 0; -} - -/* - * mode_rand -- if mode is random returns index of a random chunk - */ -static uint64_t -mode_rand(struct pmem_bench *pmb, struct operation_info *info) -{ - assert(info->index < pmb->n_rand_offsets); - return info->args->n_ops_per_thread * info->worker->index + - pmb->rand_offsets[info->index]; -} - -/* - * assign_mode_func -- parses "--src-mode" and "--dest-mode" command line - * arguments and returns one of the above mode functions. - */ -static offset_fn -assign_mode_func(char *option) -{ - enum operation_mode op_mode = parse_op_mode(option); - - switch (op_mode) { - case OP_MODE_STAT: - return mode_stat; - case OP_MODE_SEQ: - return mode_seq; - case OP_MODE_RAND: - return mode_rand; - default: - return nullptr; - } -} - -/* - * libc_memcpy -- copy using libc memcpy() function - * followed by pmem_flush(). - */ -static int -libc_memcpy(void *dest, void *source, size_t len) -{ - memcpy(dest, source, len); - - pmem_flush(dest, len); - - return 0; -} - -/* - * libc_memcpy_persist -- copy using libc memcpy() function - * followed by pmem_persist(). - */ -static int -libc_memcpy_persist(void *dest, void *source, size_t len) -{ - memcpy(dest, source, len); - - pmem_persist(dest, len); - - return 0; -} - -/* - * lipmem_memcpy_nodrain -- copy using libpmem pmem_memcpy_no_drain() - * function without pmem_persist(). - */ -static int -libpmem_memcpy_nodrain(void *dest, void *source, size_t len) -{ - pmem_memcpy_nodrain(dest, source, len); - - return 0; -} - -/* - * libpmem_memcpy_persist -- copy using libpmem pmem_memcpy_persist() function. - */ -static int -libpmem_memcpy_persist(void *dest, void *source, size_t len) -{ - pmem_memcpy_persist(dest, source, len); - - return 0; -} - -/* - * assign_size -- assigns file and buffer size - * depending on the operation mode and type. - */ -static int -assign_size(struct pmem_bench *pmb, struct benchmark_args *args, - enum operation_type *op_type) -{ - *op_type = parse_op_type(pmb->pargs->operation); - - if (*op_type == OP_TYPE_UNKNOWN) { - fprintf(stderr, "Invalid operation argument '%s'", - pmb->pargs->operation); - return -1; - } - enum operation_mode op_mode_src = parse_op_mode(pmb->pargs->src_mode); - if (op_mode_src == OP_MODE_UNKNOWN) { - fprintf(stderr, "Invalid source mode argument '%s'", - pmb->pargs->src_mode); - return -1; - } - enum operation_mode op_mode_dest = parse_op_mode(pmb->pargs->dest_mode); - if (op_mode_dest == OP_MODE_UNKNOWN) { - fprintf(stderr, "Invalid destination mode argument '%s'", - pmb->pargs->dest_mode); - return -1; - } - - size_t large = args->n_ops_per_thread * pmb->pargs->chunk_size * - args->n_threads; - size_t little = pmb->pargs->chunk_size; - - if (*op_type == OP_TYPE_WRITE) { - pmb->bsize = op_mode_src == OP_MODE_STAT ? little : large; - pmb->fsize = op_mode_dest == OP_MODE_STAT ? little : large; - - if (pmb->pargs->src_off != 0) - pmb->bsize += MAX_OFFSET; - if (pmb->pargs->dest_off != 0) - pmb->fsize += MAX_OFFSET; - } else { - pmb->fsize = op_mode_src == OP_MODE_STAT ? little : large; - pmb->bsize = op_mode_dest == OP_MODE_STAT ? little : large; - - if (pmb->pargs->src_off != 0) - pmb->fsize += MAX_OFFSET; - if (pmb->pargs->dest_off != 0) - pmb->bsize += MAX_OFFSET; - } - - return 0; -} - -/* - * pmem_memcpy_init -- benchmark initialization - * - * Parses command line arguments, allocates persistent memory, and maps it. - */ -static int -pmem_memcpy_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - int ret = 0; - size_t file_size = 0; - int flags = 0; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - auto *pmb = (struct pmem_bench *)malloc(sizeof(struct pmem_bench)); - assert(pmb != nullptr); - - pmb->pargs = (struct pmem_args *)args->opts; - assert(pmb->pargs != nullptr); - - pmb->pargs->chunk_size = args->dsize; - - enum operation_type op_type; - /* - * Assign file and buffer size depending on the operation type - * (READ from PMEM or WRITE to PMEM) - */ - if (assign_size(pmb, args, &op_type) != 0) { - ret = -1; - goto err_free_pmb; - } - pmb->buf = - (unsigned char *)util_aligned_malloc(FLUSH_ALIGN, pmb->bsize); - if (pmb->buf == nullptr) { - perror("posix_memalign"); - ret = -1; - goto err_free_pmb; - } - - pmb->n_rand_offsets = args->n_ops_per_thread * args->n_threads; - assert(pmb->n_rand_offsets != 0); - pmb->rand_offsets = (unsigned *)malloc(pmb->n_rand_offsets * - sizeof(*pmb->rand_offsets)); - - if (pmb->rand_offsets == nullptr) { - perror("malloc"); - ret = -1; - goto err_free_pmb_buf; - } - - for (size_t i = 0; i < pmb->n_rand_offsets; ++i) - pmb->rand_offsets[i] = rand() % args->n_ops_per_thread; - - if (type != TYPE_DEVDAX) { - file_size = pmb->fsize; - flags = PMEM_FILE_CREATE | PMEM_FILE_EXCL; - } - - /* create a pmem file and memory map it */ - pmb->pmem_addr = (unsigned char *)pmem_map_file( - args->fname, file_size, flags, args->fmode, nullptr, nullptr); - if (pmb->pmem_addr == nullptr) { - perror(args->fname); - ret = -1; - goto err_free_pmb_rand_offsets; - } - - if (op_type == OP_TYPE_READ) { - pmb->src_addr = pmb->pmem_addr; - pmb->dest_addr = pmb->buf; - } else { - pmb->src_addr = pmb->buf; - pmb->dest_addr = pmb->pmem_addr; - } - - /* set proper func_src() and func_dest() depending on benchmark args */ - if ((pmb->func_src = assign_mode_func(pmb->pargs->src_mode)) == - nullptr) { - fprintf(stderr, "wrong src_mode parameter -- '%s'", - pmb->pargs->src_mode); - ret = -1; - goto err_unmap; - } - - if ((pmb->func_dest = assign_mode_func(pmb->pargs->dest_mode)) == - nullptr) { - fprintf(stderr, "wrong dest_mode parameter -- '%s'", - pmb->pargs->dest_mode); - ret = -1; - goto err_unmap; - } - - if (pmb->pargs->memcpy) { - pmb->func_op = - pmb->pargs->persist ? libc_memcpy_persist : libc_memcpy; - } else { - pmb->func_op = pmb->pargs->persist ? libpmem_memcpy_persist - : libpmem_memcpy_nodrain; - } - - if (!pmb->pargs->no_warmup) { - memset(pmb->buf, 0, pmb->bsize); - pmem_memset_persist(pmb->pmem_addr, 0, pmb->fsize); - } - - pmembench_set_priv(bench, pmb); - - return 0; - -err_unmap: - pmem_unmap(pmb->pmem_addr, pmb->fsize); -err_free_pmb_rand_offsets: - free(pmb->rand_offsets); -err_free_pmb_buf: - util_aligned_free(pmb->buf); -err_free_pmb: - free(pmb); - - return ret; -} - -/* - * pmem_memcpy_operation -- actual benchmark operation - * - * Depending on the memcpy flag "-m" tested operation will be memcpy() - * or pmem_memcpy_persist(). - */ -static int -pmem_memcpy_operation(struct benchmark *bench, struct operation_info *info) -{ - auto *pmb = (struct pmem_bench *)pmembench_get_priv(bench); - - size_t src_index = pmb->func_src(pmb, info); - - size_t dest_index = pmb->func_dest(pmb, info); - - void *source = pmb->src_addr + src_index * pmb->pargs->chunk_size + - pmb->pargs->src_off; - void *dest = pmb->dest_addr + dest_index * pmb->pargs->chunk_size + - pmb->pargs->dest_off; - size_t len = pmb->pargs->chunk_size; - - pmb->func_op(dest, source, len); - return 0; -} - -/* - * pmem_memcpy_exit -- benchmark cleanup - */ -static int -pmem_memcpy_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *pmb = (struct pmem_bench *)pmembench_get_priv(bench); - pmem_unmap(pmb->pmem_addr, pmb->fsize); - util_aligned_free(pmb->buf); - free(pmb->rand_offsets); - free(pmb); - return 0; -} - -/* structure to define command line arguments */ -static struct benchmark_clo pmem_memcpy_clo[8]; - -/* Stores information about benchmark. */ -static struct benchmark_info pmem_memcpy_bench; -CONSTRUCTOR(pmem_memcpy_constructor) -void -pmem_memcpy_constructor(void) -{ - pmem_memcpy_clo[0].opt_short = 'o'; - pmem_memcpy_clo[0].opt_long = "operation"; - pmem_memcpy_clo[0].descr = "Operation type - write, read"; - pmem_memcpy_clo[0].type = CLO_TYPE_STR; - pmem_memcpy_clo[0].off = clo_field_offset(struct pmem_args, operation); - pmem_memcpy_clo[0].def = "write"; - - pmem_memcpy_clo[1].opt_short = 'S'; - pmem_memcpy_clo[1].opt_long = "src-offset"; - pmem_memcpy_clo[1].descr = "Source cache line alignment" - " offset"; - pmem_memcpy_clo[1].type = CLO_TYPE_UINT; - pmem_memcpy_clo[1].off = clo_field_offset(struct pmem_args, src_off); - pmem_memcpy_clo[1].def = "0"; - pmem_memcpy_clo[1].type_uint.size = - clo_field_size(struct pmem_args, src_off); - pmem_memcpy_clo[1].type_uint.base = CLO_INT_BASE_DEC; - pmem_memcpy_clo[1].type_uint.min = 0; - pmem_memcpy_clo[1].type_uint.max = MAX_OFFSET; - - pmem_memcpy_clo[2].opt_short = 'D'; - pmem_memcpy_clo[2].opt_long = "dest-offset"; - pmem_memcpy_clo[2].descr = "Destination cache line " - "alignment offset"; - pmem_memcpy_clo[2].type = CLO_TYPE_UINT; - pmem_memcpy_clo[2].off = clo_field_offset(struct pmem_args, dest_off); - pmem_memcpy_clo[2].def = "0"; - pmem_memcpy_clo[2].type_uint.size = - clo_field_size(struct pmem_args, dest_off); - pmem_memcpy_clo[2].type_uint.base = CLO_INT_BASE_DEC; - pmem_memcpy_clo[2].type_uint.min = 0; - pmem_memcpy_clo[2].type_uint.max = MAX_OFFSET; - - pmem_memcpy_clo[3].opt_short = 0; - pmem_memcpy_clo[3].opt_long = "src-mode"; - pmem_memcpy_clo[3].descr = "Source reading mode"; - pmem_memcpy_clo[3].type = CLO_TYPE_STR; - pmem_memcpy_clo[3].off = clo_field_offset(struct pmem_args, src_mode); - pmem_memcpy_clo[3].def = "seq"; - - pmem_memcpy_clo[4].opt_short = 0; - pmem_memcpy_clo[4].opt_long = "dest-mode"; - pmem_memcpy_clo[4].descr = "Destination writing mode"; - pmem_memcpy_clo[4].type = CLO_TYPE_STR; - pmem_memcpy_clo[4].off = clo_field_offset(struct pmem_args, dest_mode); - pmem_memcpy_clo[4].def = "seq"; - - pmem_memcpy_clo[5].opt_short = 'm'; - pmem_memcpy_clo[5].opt_long = "libc-memcpy"; - pmem_memcpy_clo[5].descr = "Use libc memcpy()"; - pmem_memcpy_clo[5].type = CLO_TYPE_FLAG; - pmem_memcpy_clo[5].off = clo_field_offset(struct pmem_args, memcpy); - pmem_memcpy_clo[5].def = "false"; - - pmem_memcpy_clo[6].opt_short = 'p'; - pmem_memcpy_clo[6].opt_long = "persist"; - pmem_memcpy_clo[6].descr = "Use pmem_persist()"; - pmem_memcpy_clo[6].type = CLO_TYPE_FLAG; - pmem_memcpy_clo[6].off = clo_field_offset(struct pmem_args, persist); - pmem_memcpy_clo[6].def = "true"; - - pmem_memcpy_clo[7].opt_short = 'w'; - pmem_memcpy_clo[7].opt_long = "no-warmup"; - pmem_memcpy_clo[7].descr = "Don't do warmup"; - pmem_memcpy_clo[7].def = "false"; - pmem_memcpy_clo[7].type = CLO_TYPE_FLAG; - pmem_memcpy_clo[7].off = clo_field_offset(struct pmem_args, no_warmup); - - pmem_memcpy_bench.name = "pmem_memcpy"; - pmem_memcpy_bench.brief = "Benchmark for" - "pmem_memcpy_persist() and " - "pmem_memcpy_nodrain()" - "operations"; - pmem_memcpy_bench.init = pmem_memcpy_init; - pmem_memcpy_bench.exit = pmem_memcpy_exit; - pmem_memcpy_bench.multithread = true; - pmem_memcpy_bench.multiops = true; - pmem_memcpy_bench.operation = pmem_memcpy_operation; - pmem_memcpy_bench.measure_time = true; - pmem_memcpy_bench.clos = pmem_memcpy_clo; - pmem_memcpy_bench.nclos = ARRAY_SIZE(pmem_memcpy_clo); - pmem_memcpy_bench.opts_size = sizeof(struct pmem_args); - pmem_memcpy_bench.rm_file = true; - pmem_memcpy_bench.allow_poolset = false; - pmem_memcpy_bench.print_bandwidth = true; - REGISTER_BENCHMARK(pmem_memcpy_bench); -}; diff --git a/src/benchmarks/pmem_memset.cpp b/src/benchmarks/pmem_memset.cpp deleted file mode 100644 index 44bc64dcea..0000000000 --- a/src/benchmarks/pmem_memset.cpp +++ /dev/null @@ -1,452 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ -/* - * pmem_memset.cpp -- benchmark for pmem_memset function - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "os.h" - -#define MAX_OFFSET 63 -#define CONST_B 0xFF - -struct memset_bench; - -typedef int (*operation_fn)(void *dest, int c, size_t len); - -/* - * memset_args -- benchmark specific command line options - */ -struct memset_args { - char *mode; /* operation mode: stat, seq, rand */ - bool memset; /* use libc memset function */ - bool persist; /* perform persist operation */ - bool msync; /* perform msync operation */ - bool no_warmup; /* do not do warmup */ - size_t chunk_size; /* elementary chunk size */ - size_t dest_off; /* destination address offset */ - unsigned seed; /* seed for random numbers */ -}; - -/* - * memset_bench -- benchmark context - */ -struct memset_bench { - struct memset_args *pargs; /* benchmark specific arguments */ - uint64_t *offsets; /* random/sequential address offsets */ - size_t n_offsets; /* number of random elements */ - int const_b; /* memset() value */ - size_t fsize; /* file size */ - void *pmem_addr; /* mapped file address */ - operation_fn func_op; /* operation function */ -}; - -/* - * operation_mode -- mode of operation of memset() - */ -enum operation_mode { - OP_MODE_UNKNOWN, - OP_MODE_STAT, /* always use the same chunk */ - OP_MODE_SEQ, /* use consecutive chunks */ - OP_MODE_RAND /* use random chunks */ -}; - -/* - * parse_op_mode -- parse operation mode from string - */ -static enum operation_mode -parse_op_mode(const char *arg) -{ - if (strcmp(arg, "stat") == 0) - return OP_MODE_STAT; - else if (strcmp(arg, "seq") == 0) - return OP_MODE_SEQ; - else if (strcmp(arg, "rand") == 0) - return OP_MODE_RAND; - else - return OP_MODE_UNKNOWN; -} - -/* - * init_offsets -- initialize offsets[] array depending on the selected mode - */ -static int -init_offsets(struct benchmark_args *args, struct memset_bench *mb, - enum operation_mode op_mode) -{ - unsigned n_threads = args->n_threads; - size_t n_ops = args->n_ops_per_thread; - - mb->n_offsets = n_ops * n_threads; - assert(mb->n_offsets != 0); - mb->offsets = (uint64_t *)malloc(mb->n_offsets * sizeof(*mb->offsets)); - if (!mb->offsets) { - perror("malloc"); - return -1; - } - - rng_t rng; - randomize_r(&rng, mb->pargs->seed); - - for (unsigned i = 0; i < n_threads; i++) { - for (size_t j = 0; j < n_ops; j++) { - size_t o; - switch (op_mode) { - case OP_MODE_STAT: - o = i; - break; - case OP_MODE_SEQ: - o = i * n_ops + j; - break; - case OP_MODE_RAND: - o = i * n_ops + rnd64_r(&rng) % n_ops; - break; - default: - assert(0); - return -1; - } - mb->offsets[i * n_ops + j] = o * mb->pargs->chunk_size; - } - } - - return 0; -} - -/* - * libpmem_memset_persist -- perform operation using libpmem - * pmem_memset_persist(). - */ -static int -libpmem_memset_persist(void *dest, int c, size_t len) -{ - pmem_memset_persist(dest, c, len); - - return 0; -} - -/* - * libpmem_memset_nodrain -- perform operation using libpmem - * pmem_memset_nodrain(). - */ -static int -libpmem_memset_nodrain(void *dest, int c, size_t len) -{ - pmem_memset_nodrain(dest, c, len); - - return 0; -} - -/* - * libc_memset_persist -- perform operation using libc memset() function - * followed by pmem_persist(). - */ -static int -libc_memset_persist(void *dest, int c, size_t len) -{ - memset(dest, c, len); - - pmem_persist(dest, len); - - return 0; -} - -/* - * libc_memset_msync -- perform operation using libc memset() function - * followed by pmem_msync(). - */ -static int -libc_memset_msync(void *dest, int c, size_t len) -{ - memset(dest, c, len); - - return pmem_msync(dest, len); -} - -/* - * libc_memset -- perform operation using libc memset() function - * followed by pmem_flush(). - */ -static int -libc_memset(void *dest, int c, size_t len) -{ - memset(dest, c, len); - - pmem_flush(dest, len); - - return 0; -} - -/* - * warmup_persist -- does the warmup by writing the whole pool area - */ -static int -warmup_persist(struct memset_bench *mb) -{ - void *dest = mb->pmem_addr; - int c = mb->const_b; - size_t len = mb->fsize; - - pmem_memset_persist(dest, c, len); - - return 0; -} - -/* - * warmup_msync -- does the warmup by writing the whole pool area - */ -static int -warmup_msync(struct memset_bench *mb) -{ - void *dest = mb->pmem_addr; - int c = mb->const_b; - size_t len = mb->fsize; - - return libc_memset_msync(dest, c, len); -} - -/* - * memset_op -- actual benchmark operation. It can have one of the four - * functions assigned: - * libc_memset, - * libc_memset_persist, - * libpmem_memset_nodrain, - * libpmem_memset_persist. - */ -static int -memset_op(struct benchmark *bench, struct operation_info *info) -{ - auto *mb = (struct memset_bench *)pmembench_get_priv(bench); - - assert(info->index < mb->n_offsets); - - size_t idx = info->worker->index * info->args->n_ops_per_thread + - info->index; - void *dest = - (char *)mb->pmem_addr + mb->offsets[idx] + mb->pargs->dest_off; - int c = mb->const_b; - size_t len = mb->pargs->chunk_size; - - mb->func_op(dest, c, len); - - return 0; -} - -/* - * memset_init -- initialization function - */ -static int -memset_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - int ret = 0; - size_t size; - size_t large; - size_t little; - size_t file_size = 0; - int flags = 0; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - int (*warmup_func)(struct memset_bench *) = warmup_persist; - auto *mb = (struct memset_bench *)malloc(sizeof(struct memset_bench)); - if (!mb) { - perror("malloc"); - return -1; - } - - mb->pargs = (struct memset_args *)args->opts; - mb->pargs->chunk_size = args->dsize; - - enum operation_mode op_mode = parse_op_mode(mb->pargs->mode); - if (op_mode == OP_MODE_UNKNOWN) { - fprintf(stderr, "Invalid operation mode argument '%s'\n", - mb->pargs->mode); - ret = -1; - goto err_free_mb; - } - - size = MAX_OFFSET + mb->pargs->chunk_size; - large = size * args->n_ops_per_thread * args->n_threads; - little = size * args->n_threads; - - mb->fsize = (op_mode == OP_MODE_STAT) ? little : large; - - /* initialize offsets[] array depending on benchmark args */ - if (init_offsets(args, mb, op_mode) < 0) { - ret = -1; - goto err_free_mb; - } - - /* initialize memset() value */ - mb->const_b = CONST_B; - - if (type != TYPE_DEVDAX) { - file_size = mb->fsize; - flags = PMEM_FILE_CREATE | PMEM_FILE_EXCL; - } - - /* create a pmem file and memory map it */ - if ((mb->pmem_addr = pmem_map_file(args->fname, file_size, flags, - args->fmode, nullptr, nullptr)) == - nullptr) { - perror(args->fname); - ret = -1; - goto err_free_offsets; - } - - if (mb->pargs->memset) { - if (mb->pargs->persist && mb->pargs->msync) { - fprintf(stderr, - "Invalid benchmark parameters: persist and msync cannot be specified together\n"); - ret = -1; - goto err_free_offsets; - } - - if (mb->pargs->persist) { - mb->func_op = libc_memset_persist; - } else if (mb->pargs->msync) { - mb->func_op = libc_memset_msync; - warmup_func = warmup_msync; - } else { - mb->func_op = libc_memset; - } - } else { - mb->func_op = (mb->pargs->persist) ? libpmem_memset_persist - : libpmem_memset_nodrain; - } - - if (!mb->pargs->no_warmup && type != TYPE_DEVDAX) { - ret = warmup_func(mb); - if (ret) { - perror("Pool warmup failed"); - goto err_free_offsets; - } - } - - pmembench_set_priv(bench, mb); - - return ret; - -err_free_offsets: - free(mb->offsets); -err_free_mb: - free(mb); - - return ret; -} - -/* - * memset_exit -- benchmark cleanup function - */ -static int -memset_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *mb = (struct memset_bench *)pmembench_get_priv(bench); - pmem_unmap(mb->pmem_addr, mb->fsize); - free(mb->offsets); - free(mb); - return 0; -} - -static struct benchmark_clo memset_clo[7]; -/* Stores information about benchmark. */ -static struct benchmark_info memset_info; -CONSTRUCTOR(pmem_memset_constructor) -void -pmem_memset_constructor(void) -{ - memset_clo[0].opt_short = 'M'; - memset_clo[0].opt_long = "mem-mode"; - memset_clo[0].descr = "Memory writing mode - " - "stat, seq, rand"; - memset_clo[0].def = "seq"; - memset_clo[0].off = clo_field_offset(struct memset_args, mode); - memset_clo[0].type = CLO_TYPE_STR; - - memset_clo[1].opt_short = 'm'; - memset_clo[1].opt_long = "memset"; - memset_clo[1].descr = "Use libc memset()"; - memset_clo[1].def = "false"; - memset_clo[1].off = clo_field_offset(struct memset_args, memset); - memset_clo[1].type = CLO_TYPE_FLAG; - - memset_clo[2].opt_short = 'p'; - memset_clo[2].opt_long = "persist"; - memset_clo[2].descr = "Use pmem_persist()"; - memset_clo[2].def = "true"; - memset_clo[2].off = clo_field_offset(struct memset_args, persist); - memset_clo[2].type = CLO_TYPE_FLAG; - - memset_clo[3].opt_short = 'D'; - memset_clo[3].opt_long = "dest-offset"; - memset_clo[3].descr = "Destination cache line alignment " - "offset"; - memset_clo[3].def = "0"; - memset_clo[3].off = clo_field_offset(struct memset_args, dest_off); - memset_clo[3].type = CLO_TYPE_UINT; - memset_clo[3].type_uint.size = - clo_field_size(struct memset_args, dest_off); - memset_clo[3].type_uint.base = CLO_INT_BASE_DEC; - memset_clo[3].type_uint.min = 0; - memset_clo[3].type_uint.max = MAX_OFFSET; - - memset_clo[4].opt_short = 'w'; - memset_clo[4].opt_long = "no-warmup"; - memset_clo[4].descr = "Don't do warmup"; - memset_clo[4].def = "false"; - memset_clo[4].type = CLO_TYPE_FLAG; - memset_clo[4].off = clo_field_offset(struct memset_args, no_warmup); - - memset_clo[5].opt_short = 'S'; - memset_clo[5].opt_long = "seed"; - memset_clo[5].descr = "seed for random numbers"; - memset_clo[5].def = "1"; - memset_clo[5].off = clo_field_offset(struct memset_args, seed); - memset_clo[5].type = CLO_TYPE_UINT; - memset_clo[5].type_uint.size = clo_field_size(struct memset_args, seed); - memset_clo[5].type_uint.base = CLO_INT_BASE_DEC; - memset_clo[5].type_uint.min = 1; - memset_clo[5].type_uint.max = UINT_MAX; - - memset_clo[6].opt_short = 's'; - memset_clo[6].opt_long = "msync"; - memset_clo[6].descr = "Use pmem_msync()"; - memset_clo[6].def = "false"; - memset_clo[6].off = clo_field_offset(struct memset_args, msync); - memset_clo[6].type = CLO_TYPE_FLAG; - - memset_info.name = "pmem_memset"; - memset_info.brief = "Benchmark for pmem_memset_persist() " - "and pmem_memset_nodrain() operations"; - memset_info.init = memset_init; - memset_info.exit = memset_exit; - memset_info.multithread = true; - memset_info.multiops = true; - memset_info.operation = memset_op; - memset_info.measure_time = true; - memset_info.clos = memset_clo; - memset_info.nclos = ARRAY_SIZE(memset_clo); - memset_info.opts_size = sizeof(struct memset_args); - memset_info.rm_file = true; - memset_info.allow_poolset = false; - memset_info.print_bandwidth = true; - REGISTER_BENCHMARK(memset_info); -}; diff --git a/src/benchmarks/pmembench.cpp b/src/benchmarks/pmembench.cpp deleted file mode 100644 index 0f73242ff8..0000000000 --- a/src/benchmarks/pmembench.cpp +++ /dev/null @@ -1,1623 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2023, Intel Corporation */ - -/* - * pmembench.cpp -- main source file for benchmark framework - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "benchmark_worker.hpp" -#include "clo.hpp" -#include "clo_vec.hpp" -#include "config_reader.hpp" -#include "file.h" -#include "libpmempool.h" -#include "mmap.h" -#include "os.h" -#include "os_thread.h" -#include "queue.h" -#include "scenario.hpp" -#include "set.h" -#include "util.h" - -/* average time required to get a current time from the system */ -unsigned long long Get_time_avg; - -#define MIN_EXE_TIME_E 0.5 - -/* - * struct pmembench -- main context - */ -struct pmembench { - int argc; - char **argv; - struct scenario *scenario; - struct clo_vec *clovec; - bool override_clos; -}; - -/* - * struct benchmark -- benchmark's context - */ -struct benchmark { - PMDK_LIST_ENTRY(benchmark) next; - struct benchmark_info *info; - void *priv; - struct benchmark_clo *clos; - size_t nclos; - size_t args_size; -}; - -/* - * struct bench_list -- list of available benchmarks - */ -struct bench_list { - PMDK_LIST_HEAD(benchmarks_head, benchmark) head; - bool initialized; -}; - -/* - * struct benchmark_opts -- arguments for pmembench - */ -struct benchmark_opts { - bool help; - bool version; - const char *file_name; -}; - -static struct version_s { - unsigned major; - unsigned minor; -} version = {1, 0}; - -/* benchmarks list initialization */ -static struct bench_list benchmarks; - -/* common arguments for benchmarks */ -static struct benchmark_clo pmembench_clos[13]; - -/* list of arguments for pmembench */ -static struct benchmark_clo pmembench_opts[2]; -CONSTRUCTOR(pmembench_constructor) -void -pmembench_constructor(void) -{ - pmembench_opts[0].opt_short = 'h'; - pmembench_opts[0].opt_long = "help"; - pmembench_opts[0].descr = "Print help"; - pmembench_opts[0].type = CLO_TYPE_FLAG; - pmembench_opts[0].off = clo_field_offset(struct benchmark_opts, help); - pmembench_opts[0].ignore_in_res = true; - - pmembench_opts[1].opt_short = 'v'; - pmembench_opts[1].opt_long = "version"; - pmembench_opts[1].descr = "Print version"; - pmembench_opts[1].type = CLO_TYPE_FLAG; - pmembench_opts[1].off = - clo_field_offset(struct benchmark_opts, version); - pmembench_opts[1].ignore_in_res = true; - - pmembench_clos[0].opt_short = 'h'; - pmembench_clos[0].opt_long = "help"; - pmembench_clos[0].descr = "Print help for single benchmark"; - pmembench_clos[0].type = CLO_TYPE_FLAG; - pmembench_clos[0].off = clo_field_offset(struct benchmark_args, help); - pmembench_clos[0].ignore_in_res = true; - - pmembench_clos[1].opt_short = 't'; - pmembench_clos[1].opt_long = "threads"; - pmembench_clos[1].type = CLO_TYPE_UINT; - pmembench_clos[1].descr = "Number of working threads"; - pmembench_clos[1].off = - clo_field_offset(struct benchmark_args, n_threads); - pmembench_clos[1].def = "1"; - pmembench_clos[1].type_uint.size = - clo_field_size(struct benchmark_args, n_threads); - pmembench_clos[1].type_uint.base = CLO_INT_BASE_DEC; - pmembench_clos[1].type_uint.min = 1; - pmembench_clos[1].type_uint.max = UINT_MAX; - - pmembench_clos[2].opt_short = 'n'; - pmembench_clos[2].opt_long = "ops-per-thread"; - pmembench_clos[2].type = CLO_TYPE_UINT; - pmembench_clos[2].descr = "Number of operations per thread"; - pmembench_clos[2].off = - clo_field_offset(struct benchmark_args, n_ops_per_thread); - pmembench_clos[2].def = "1"; - pmembench_clos[2].type_uint.size = - clo_field_size(struct benchmark_args, n_ops_per_thread); - pmembench_clos[2].type_uint.base = CLO_INT_BASE_DEC; - pmembench_clos[2].type_uint.min = 1; - pmembench_clos[2].type_uint.max = ULLONG_MAX; - - pmembench_clos[3].opt_short = 'd'; - pmembench_clos[3].opt_long = "data-size"; - pmembench_clos[3].type = CLO_TYPE_UINT; - pmembench_clos[3].descr = "IO data size"; - pmembench_clos[3].off = clo_field_offset(struct benchmark_args, dsize); - pmembench_clos[3].def = "1"; - - pmembench_clos[3].type_uint.size = - clo_field_size(struct benchmark_args, dsize); - pmembench_clos[3].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - pmembench_clos[3].type_uint.min = 1; - pmembench_clos[3].type_uint.max = ULONG_MAX; - - pmembench_clos[4].opt_short = 'f'; - pmembench_clos[4].opt_long = "file"; - pmembench_clos[4].type = CLO_TYPE_STR; - pmembench_clos[4].descr = "File name"; - pmembench_clos[4].off = clo_field_offset(struct benchmark_args, fname); - pmembench_clos[4].def = "/mnt/pmem/testfile"; - pmembench_clos[4].ignore_in_res = true; - - pmembench_clos[5].opt_short = 'm'; - pmembench_clos[5].opt_long = "fmode"; - pmembench_clos[5].type = CLO_TYPE_UINT; - pmembench_clos[5].descr = "File mode"; - pmembench_clos[5].off = clo_field_offset(struct benchmark_args, fmode); - pmembench_clos[5].def = "0666"; - pmembench_clos[5].ignore_in_res = true; - pmembench_clos[5].type_uint.size = - clo_field_size(struct benchmark_args, fmode); - pmembench_clos[5].type_uint.base = CLO_INT_BASE_OCT; - pmembench_clos[5].type_uint.min = 0; - pmembench_clos[5].type_uint.max = ULONG_MAX; - - pmembench_clos[6].opt_short = 's'; - pmembench_clos[6].opt_long = "seed"; - pmembench_clos[6].type = CLO_TYPE_UINT; - pmembench_clos[6].descr = "PRNG seed"; - pmembench_clos[6].off = clo_field_offset(struct benchmark_args, seed); - pmembench_clos[6].def = "0"; - pmembench_clos[6].type_uint.size = - clo_field_size(struct benchmark_args, seed); - pmembench_clos[6].type_uint.base = CLO_INT_BASE_DEC; - pmembench_clos[6].type_uint.min = 0; - pmembench_clos[6].type_uint.max = ~0; - - pmembench_clos[7].opt_short = 'r'; - pmembench_clos[7].opt_long = "repeats"; - pmembench_clos[7].type = CLO_TYPE_UINT; - pmembench_clos[7].descr = "Number of repeats of scenario"; - pmembench_clos[7].off = - clo_field_offset(struct benchmark_args, repeats); - pmembench_clos[7].def = "1"; - pmembench_clos[7].type_uint.size = - clo_field_size(struct benchmark_args, repeats); - pmembench_clos[7].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - pmembench_clos[7].type_uint.min = 1; - pmembench_clos[7].type_uint.max = ULONG_MAX; - - pmembench_clos[8].opt_short = 'F'; - pmembench_clos[8].opt_long = "thread-affinity"; - pmembench_clos[8].descr = "Set worker threads CPU affinity mask"; - pmembench_clos[8].type = CLO_TYPE_FLAG; - pmembench_clos[8].off = - clo_field_offset(struct benchmark_args, thread_affinity); - pmembench_clos[8].def = "false"; - - /* - * XXX: add link to blog post about optimal affinity - * when it will be done - */ - pmembench_clos[9].opt_short = 'I'; - pmembench_clos[9].opt_long = "affinity-list"; - pmembench_clos[9].descr = - "Set affinity mask as a list of CPUs separated by semicolon"; - pmembench_clos[9].type = CLO_TYPE_STR; - pmembench_clos[9].off = - clo_field_offset(struct benchmark_args, affinity_list); - pmembench_clos[9].def = ""; - pmembench_clos[9].ignore_in_res = true; - - pmembench_clos[10].opt_long = "main-affinity"; - pmembench_clos[10].descr = "Set affinity for main thread"; - pmembench_clos[10].type = CLO_TYPE_INT; - pmembench_clos[10].off = - clo_field_offset(struct benchmark_args, main_affinity); - pmembench_clos[10].def = "-1"; - pmembench_clos[10].ignore_in_res = false; - pmembench_clos[10].type_int.size = - clo_field_size(struct benchmark_args, main_affinity); - pmembench_clos[10].type_int.base = CLO_INT_BASE_DEC; - pmembench_clos[10].type_int.min = (-1); - pmembench_clos[10].type_int.max = LONG_MAX; - - pmembench_clos[11].opt_short = 'e'; - pmembench_clos[11].opt_long = "min-exe-time"; - pmembench_clos[11].type = CLO_TYPE_UINT; - pmembench_clos[11].descr = "Minimal execution time in seconds"; - pmembench_clos[11].off = - clo_field_offset(struct benchmark_args, min_exe_time); - pmembench_clos[11].def = "0"; - pmembench_clos[11].type_uint.size = - clo_field_size(struct benchmark_args, min_exe_time); - pmembench_clos[11].type_uint.base = CLO_INT_BASE_DEC; - pmembench_clos[11].type_uint.min = 0; - pmembench_clos[11].type_uint.max = ULONG_MAX; - - pmembench_clos[12].opt_short = 'p'; - pmembench_clos[12].opt_long = "dynamic-poolset"; - pmembench_clos[12].type = CLO_TYPE_FLAG; - pmembench_clos[12].descr = - "Allow benchmark to create poolset and reuse files"; - pmembench_clos[12].off = - clo_field_offset(struct benchmark_args, is_dynamic_poolset); - pmembench_clos[12].ignore_in_res = true; -} - -/* - * pmembench_get_priv -- return private structure of benchmark - */ -void * -pmembench_get_priv(struct benchmark *bench) -{ - return bench->priv; -} - -/* - * pmembench_set_priv -- set private structure of benchmark - */ -void -pmembench_set_priv(struct benchmark *bench, void *priv) -{ - bench->priv = priv; -} - -/* - * pmembench_register -- register benchmark - */ -int -pmembench_register(struct benchmark_info *bench_info) -{ - assert(bench_info->name && bench_info->brief); - - struct benchmark *bench = (struct benchmark *)calloc(1, sizeof(*bench)); - assert(bench != nullptr); - - bench->info = bench_info; - - if (!benchmarks.initialized) { - PMDK_LIST_INIT(&benchmarks.head); - benchmarks.initialized = true; - } - - PMDK_LIST_INSERT_HEAD(&benchmarks.head, bench, next); - - return 0; -} - -/* - * pmembench_get_info -- return structure with information about benchmark - */ -struct benchmark_info * -pmembench_get_info(struct benchmark *bench) -{ - return bench->info; -} - -/* - * pmembench_release_clos -- release CLO structure - */ -static void -pmembench_release_clos(struct benchmark *bench) -{ - free(bench->clos); -} - -/* - * pmembench_merge_clos -- merge benchmark's CLOs with common CLOs - */ -static void -pmembench_merge_clos(struct benchmark *bench) -{ - size_t size = sizeof(struct benchmark_args); - size_t pb_nclos = ARRAY_SIZE(pmembench_clos); - size_t nclos = pb_nclos; - size_t i; - - if (bench->info->clos) { - size += bench->info->opts_size; - nclos += bench->info->nclos; - } - - auto *clos = (struct benchmark_clo *)calloc( - nclos, sizeof(struct benchmark_clo)); - assert(clos != nullptr); - - memcpy(clos, pmembench_clos, pb_nclos * sizeof(struct benchmark_clo)); - - if (bench->info->clos) { - memcpy(&clos[pb_nclos], bench->info->clos, - bench->info->nclos * sizeof(struct benchmark_clo)); - - for (i = 0; i < bench->info->nclos; i++) { - clos[pb_nclos + i].off += sizeof(struct benchmark_args); - } - } - - bench->clos = clos; - bench->nclos = nclos; - bench->args_size = size; -} - -/* - * pmembench_run_worker -- run worker with benchmark operation - */ -static int -pmembench_run_worker(struct benchmark *bench, struct worker_info *winfo) -{ - benchmark_time_get(&winfo->beg); - for (size_t i = 0; i < winfo->nops; i++) { - if (bench->info->operation(bench, &winfo->opinfo[i])) - return -1; - benchmark_time_get(&winfo->opinfo[i].end); - } - benchmark_time_get(&winfo->end); - - return 0; -} - -/* - * pmembench_print_header -- print header of benchmark's results - */ -static void -pmembench_print_header(struct pmembench *pb, struct benchmark *bench, - struct clo_vec *clovec) -{ - if (pb->scenario) { - printf("%s: %s [%" PRIu64 "]%s%s%s\n", pb->scenario->name, - bench->info->name, clovec->nargs, - pb->scenario->group ? " [group: " : "", - pb->scenario->group ? pb->scenario->group : "", - pb->scenario->group ? "]" : ""); - } else { - printf("%s [%" PRIu64 "]\n", bench->info->name, clovec->nargs); - } - printf("total-avg[sec];" - "ops-per-second[1/sec];" - "total-max[sec];" - "total-min[sec];" - "total-median[sec];" - "total-std-dev[sec];" - "latency-avg[nsec];" - "latency-min[nsec];" - "latency-max[nsec];" - "latency-std-dev[nsec];" - "latency-pctl-50.0%%[nsec];" - "latency-pctl-99.0%%[nsec];" - "latency-pctl-99.9%%[nsec]"); - size_t i; - for (i = 0; i < bench->nclos; i++) { - if (!bench->clos[i].ignore_in_res) { - printf(";%s", bench->clos[i].opt_long); - } - } - - if (bench->info->print_bandwidth) - printf(";bandwidth[MiB/s]"); - - if (bench->info->print_extra_headers) - bench->info->print_extra_headers(); - printf("\n"); -} - -/* - * pmembench_print_results -- print benchmark's results - */ -static void -pmembench_print_results(struct benchmark *bench, struct benchmark_args *args, - struct total_results *res) -{ - printf("%f;%f;%f;%f;%f;%f;%" PRIu64 ";%" PRIu64 ";%" PRIu64 - ";%f;%" PRIu64 ";%" PRIu64 ";%" PRIu64, - res->total.avg, res->nopsps, res->total.max, res->total.min, - res->total.med, res->total.std_dev, res->latency.avg, - res->latency.min, res->latency.max, res->latency.std_dev, - res->latency.pctl50_0p, res->latency.pctl99_0p, - res->latency.pctl99_9p); - - size_t i; - for (i = 0; i < bench->nclos; i++) { - if (!bench->clos[i].ignore_in_res) - printf(";%s", - benchmark_clo_str(&bench->clos[i], args, - bench->args_size)); - } - - if (bench->info->print_bandwidth) - printf(";%f", res->nopsps * args->dsize / 1024 / 1024); - - if (bench->info->print_extra_values) - bench->info->print_extra_values(bench, args, res); - printf("\n"); -} - -/* - * pmembench_parse_clos -- parse command line arguments for benchmark - */ -static int -pmembench_parse_clo(struct pmembench *pb, struct benchmark *bench, - struct clo_vec *clovec) -{ - if (!pb->scenario) { - return benchmark_clo_parse(pb->argc, pb->argv, bench->clos, - bench->nclos, clovec); - } - - if (pb->override_clos) { - /* - * Use only ARRAY_SIZE(pmembench_clos) clos - these are the - * general clos and are placed at the beginning of the - * clos array. - */ - int ret = benchmark_override_clos_in_scenario( - pb->scenario, pb->argc, pb->argv, bench->clos, - ARRAY_SIZE(pmembench_clos)); - /* reset for the next benchmark in the config file */ - optind = 1; - - if (ret) - return ret; - } - return benchmark_clo_parse_scenario(pb->scenario, bench->clos, - bench->nclos, clovec); -} - -/* - * pmembench_parse_affinity -- parse affinity list - */ -static int -pmembench_parse_affinity(const char *list, char **saveptr) -{ - char *str = nullptr; - char *end; - int cpu = 0; - - if (*saveptr) { - str = strtok(nullptr, ";"); - if (str == nullptr) { - /* end of list - we have to start over */ - free(*saveptr); - *saveptr = nullptr; - } - } - - if (!*saveptr) { - *saveptr = strdup(list); - if (*saveptr == nullptr) { - perror("strdup"); - return -1; - } - - str = strtok(*saveptr, ";"); - if (str == nullptr) - goto err; - } - - if ((str == nullptr) || (*str == '\0')) - goto err; - - cpu = strtol(str, &end, 10); - - if (*end != '\0') - goto err; - - return cpu; -err: - errno = EINVAL; - perror("pmembench_parse_affinity"); - free(*saveptr); - *saveptr = nullptr; - return -1; -} - -/* - * pmembench_init_workers -- init benchmark's workers - */ -static int -pmembench_init_workers(struct benchmark_worker **workers, - struct benchmark *bench, struct benchmark_args *args) -{ - unsigned i; - int ncpus = 0; - char *saveptr = nullptr; - int ret = 0; - - if (args->thread_affinity) { - ncpus = sysconf(_SC_NPROCESSORS_ONLN); - if (ncpus <= 0) - return -1; - } - - for (i = 0; i < args->n_threads; i++) { - workers[i] = benchmark_worker_alloc(); - - if (args->thread_affinity) { - int cpu; - os_cpu_set_t cpuset; - - if (args->affinity_list && - *args->affinity_list != '\0') { - cpu = pmembench_parse_affinity( - args->affinity_list, &saveptr); - if (cpu == -1) { - ret = -1; - goto end; - } - } else { - cpu = (int)i; - } - - assert(ncpus > 0); - cpu %= ncpus; - os_cpu_zero(&cpuset); - os_cpu_set(cpu, &cpuset); - errno = os_thread_setaffinity_np(&workers[i]->thread, - sizeof(os_cpu_set_t), - &cpuset); - if (errno) { - perror("os_thread_setaffinity_np"); - ret = -1; - goto end; - } - } - - workers[i]->info.index = i; - workers[i]->info.nops = args->n_ops_per_thread; - workers[i]->info.opinfo = (struct operation_info *)calloc( - args->n_ops_per_thread, sizeof(struct operation_info)); - size_t j; - for (j = 0; j < args->n_ops_per_thread; j++) { - workers[i]->info.opinfo[j].worker = &workers[i]->info; - workers[i]->info.opinfo[j].args = args; - workers[i]->info.opinfo[j].index = j; - } - workers[i]->bench = bench; - workers[i]->args = args; - workers[i]->func = pmembench_run_worker; - workers[i]->init = bench->info->init_worker; - workers[i]->exit = bench->info->free_worker; - if (benchmark_worker_init(workers[i])) { - fprintf(stderr, - "thread number %u initialization failed\n", i); - ret = -1; - goto end; - } - } - -end: - free(saveptr); - return ret; -} - -/* - * results_store -- store results of a single repeat - */ -static void -results_store(struct bench_results *res, struct benchmark_worker **workers, - unsigned nthreads, size_t nops) -{ - for (unsigned i = 0; i < nthreads; i++) { - res->thres[i]->beg = workers[i]->info.beg; - res->thres[i]->end = workers[i]->info.end; - for (size_t j = 0; j < nops; j++) { - res->thres[i]->end_op[j] = - workers[i]->info.opinfo[j].end; - } - } -} - -/* - * compare_time -- compare time values - */ -static int -compare_time(const void *p1, const void *p2) -{ - const auto *t1 = (const benchmark_time_t *)p1; - const auto *t2 = (const benchmark_time_t *)p2; - - return benchmark_time_compare(t1, t2); -} - -/* - * compare_doubles -- comparing function used for sorting - */ -static int -compare_doubles(const void *a1, const void *b1) -{ - const auto *a = (const double *)a1; - const auto *b = (const double *)b1; - return (*a > *b) - (*a < *b); -} - -/* - * compare_uint64t -- comparing function used for sorting - */ -static int -compare_uint64t(const void *a1, const void *b1) -{ - const auto *a = (const uint64_t *)a1; - const auto *b = (const uint64_t *)b1; - return (*a > *b) - (*a < *b); -} - -/* - * results_alloc -- prepare structure to store all benchmark results - */ -static struct total_results * -results_alloc(struct benchmark_args *args) -{ - struct total_results *total = - (struct total_results *)malloc(sizeof(*total)); - assert(total != nullptr); - total->nrepeats = args->repeats; - total->nthreads = args->n_threads; - total->nops = args->n_ops_per_thread; - total->res = (struct bench_results *)malloc(args->repeats * - sizeof(*total->res)); - assert(total->res != nullptr); - - for (size_t i = 0; i < args->repeats; i++) { - struct bench_results *res = &total->res[i]; - assert(args->n_threads != 0); - res->thres = (struct thread_results **)malloc( - args->n_threads * sizeof(*res->thres)); - assert(res->thres != nullptr); - for (size_t j = 0; j < args->n_threads; j++) { - res->thres[j] = (struct thread_results *)malloc( - sizeof(*res->thres[j]) + - args->n_ops_per_thread * - sizeof(benchmark_time_t)); - assert(res->thres[j] != nullptr); - } - } - - return total; -} - -/* - * results_free -- release results structure - */ -static void -results_free(struct total_results *total) -{ - for (size_t i = 0; i < total->nrepeats; i++) { - for (size_t j = 0; j < total->nthreads; j++) - free(total->res[i].thres[j]); - free(total->res[i].thres); - } - free(total->res); - free(total); -} - -/* - * get_total_results -- return results of all repeats of scenario - */ -static void -get_total_results(struct total_results *tres) -{ - assert(tres->nrepeats != 0); - assert(tres->nthreads != 0); - assert(tres->nops != 0); - - /* reset results */ - memset(&tres->total, 0, sizeof(tres->total)); - memset(&tres->latency, 0, sizeof(tres->latency)); - - tres->total.min = DBL_MAX; - tres->total.max = DBL_MIN; - tres->latency.min = UINT64_MAX; - tres->latency.max = 0; - - /* allocate helper arrays */ - benchmark_time_t *tbeg = - (benchmark_time_t *)malloc(tres->nthreads * sizeof(*tbeg)); - assert(tbeg != nullptr); - benchmark_time_t *tend = - (benchmark_time_t *)malloc(tres->nthreads * sizeof(*tend)); - assert(tend != nullptr); - auto *totals = (double *)malloc(tres->nrepeats * sizeof(double)); - assert(totals != nullptr); - - /* estimate total penalty of getting time from the system */ - benchmark_time_t Tget; - unsigned long long nsecs = tres->nops * Get_time_avg; - benchmark_time_set(&Tget, nsecs); - - for (size_t i = 0; i < tres->nrepeats; i++) { - struct bench_results *res = &tres->res[i]; - - /* get start and end timestamps of each worker */ - for (size_t j = 0; j < tres->nthreads; j++) { - tbeg[j] = res->thres[j]->beg; - tend[j] = res->thres[j]->end; - } - - /* sort start and end timestamps */ - qsort(tbeg, tres->nthreads, sizeof(benchmark_time_t), - compare_time); - qsort(tend, tres->nthreads, sizeof(benchmark_time_t), - compare_time); - - /* calculating time interval between start and end time */ - benchmark_time_t Tbeg = tbeg[0]; - benchmark_time_t Tend = tend[tres->nthreads - 1]; - benchmark_time_t Ttot_ove; - benchmark_time_diff(&Ttot_ove, &Tbeg, &Tend); - /* - * subtract time used for getting the current time from the - * system - */ - benchmark_time_t Ttot; - benchmark_time_diff(&Ttot, &Tget, &Ttot_ove); - - double Stot = benchmark_time_get_secs(&Ttot); - - if (Stot > tres->total.max) - tres->total.max = Stot; - if (Stot < tres->total.min) - tres->total.min = Stot; - - tres->total.avg += Stot; - totals[i] = Stot; - } - - /* median */ - qsort(totals, tres->nrepeats, sizeof(double), compare_doubles); - if (tres->nrepeats % 2) { - tres->total.med = totals[tres->nrepeats / 2]; - } else { - double m1 = totals[tres->nrepeats / 2]; - double m2 = totals[tres->nrepeats / 2 - 1]; - tres->total.med = (m1 + m2) / 2.0; - } - - /* total average time */ - tres->total.avg /= (double)tres->nrepeats; - - /* number of operations per second */ - tres->nopsps = - (double)tres->nops * (double)tres->nthreads / tres->total.avg; - - /* std deviation of total time */ - for (size_t i = 0; i < tres->nrepeats; i++) { - double dev = (totals[i] - tres->total.avg); - dev *= dev; - - tres->total.std_dev += dev; - } - - tres->total.std_dev = sqrt(tres->total.std_dev / tres->nrepeats); - - /* latency */ - for (size_t i = 0; i < tres->nrepeats; i++) { - struct bench_results *res = &tres->res[i]; - for (size_t j = 0; j < tres->nthreads; j++) { - struct thread_results *thres = res->thres[j]; - benchmark_time_t *beg = &thres->beg; - for (size_t o = 0; o < tres->nops; o++) { - benchmark_time_t lat; - benchmark_time_diff(&lat, beg, - &thres->end_op[o]); - uint64_t nsecs = benchmark_time_get_nsecs(&lat); - - /* min, max latency */ - if (nsecs > tres->latency.max) - tres->latency.max = nsecs; - if (nsecs < tres->latency.min) - tres->latency.min = nsecs; - - tres->latency.avg += nsecs; - - beg = &thres->end_op[o]; - } - } - } - - /* average latency */ - size_t count = tres->nrepeats * tres->nthreads * tres->nops; - assert(count > 0); - tres->latency.avg /= count; - - auto *ntotals = (uint64_t *)calloc(count, sizeof(uint64_t)); - assert(ntotals != nullptr); - count = 0; - - /* std deviation of latency and percentiles */ - for (size_t i = 0; i < tres->nrepeats; i++) { - struct bench_results *res = &tres->res[i]; - for (size_t j = 0; j < tres->nthreads; j++) { - struct thread_results *thres = res->thres[j]; - benchmark_time_t *beg = &thres->beg; - for (size_t o = 0; o < tres->nops; o++) { - benchmark_time_t lat; - benchmark_time_diff(&lat, beg, - &thres->end_op[o]); - uint64_t nsecs = benchmark_time_get_nsecs(&lat); - - uint64_t dev = (nsecs - tres->latency.avg); - dev *= dev; - - tres->latency.std_dev += dev; - - beg = &thres->end_op[o]; - - ntotals[count] = nsecs; - ++count; - } - } - } - - tres->latency.std_dev = sqrt(tres->latency.std_dev / count); - - /* find 50%, 99.0% and 99.9% percentiles */ - qsort(ntotals, count, sizeof(uint64_t), compare_uint64t); - uint64_t p50_0 = count * 50 / 100; - uint64_t p99_0 = count * 99 / 100; - uint64_t p99_9 = count * 999 / 1000; - tres->latency.pctl50_0p = ntotals[p50_0]; - tres->latency.pctl99_0p = ntotals[p99_0]; - tres->latency.pctl99_9p = ntotals[p99_9]; - free(ntotals); - - free(totals); - free(tend); - free(tbeg); -} - -/* - * pmembench_print_args -- print arguments for one benchmark - */ -static void -pmembench_print_args(struct benchmark_clo *clos, size_t nclos) -{ - struct benchmark_clo clo; - for (size_t i = 0; i < nclos; i++) { - clo = clos[i]; - if (clo.opt_short != 0) - printf("\t-%c,", clo.opt_short); - else - printf("\t"); - printf("\t--%-15s\t\t%s", clo.opt_long, clo.descr); - if (clo.type != CLO_TYPE_FLAG) - printf(" [default: %s]", clo.def); - - if (clo.type == CLO_TYPE_INT) { - if (clo.type_int.min != LONG_MIN) - printf(" [min: %" PRId64 "]", clo.type_int.min); - if (clo.type_int.max != LONG_MAX) - printf(" [max: %" PRId64 "]", clo.type_int.max); - } else if (clo.type == CLO_TYPE_UINT) { - if (clo.type_uint.min != 0) - printf(" [min: %" PRIu64 "]", - clo.type_uint.min); - if (clo.type_uint.max != ULONG_MAX) - printf(" [max: %" PRIu64 "]", - clo.type_uint.max); - } - printf("\n"); - } -} - -/* - * pmembench_print_help_single -- prints help for single benchmark - */ -static void -pmembench_print_help_single(struct benchmark *bench) -{ - struct benchmark_info *info = bench->info; - printf("%s\n%s\n", info->name, info->brief); - printf("\nArguments:\n"); - size_t nclos = sizeof(pmembench_clos) / sizeof(struct benchmark_clo); - pmembench_print_args(pmembench_clos, nclos); - if (info->clos == nullptr) - return; - pmembench_print_args(info->clos, info->nclos); -} - -/* - * pmembench_print_usage -- print usage of framework - */ -static void -pmembench_print_usage() -{ - printf("Usage: $ pmembench [-h|--help] [-v|--version]" - "\t[[]]\n"); - printf("\t\t\t\t\t\t[[]]\n"); - printf("\t\t\t\t\t\t[[[]]]\n"); -} - -/* - * pmembench_print_version -- print version of framework - */ -static void -pmembench_print_version() -{ - printf("Benchmark framework - version %u.%u\n", version.major, - version.minor); -} - -/* - * pmembench_print_examples() -- print examples of using framework - */ -static void -pmembench_print_examples() -{ - printf("\nExamples:\n"); - printf("$ pmembench \n"); - printf(" # runs benchmark of name with arguments \n"); - printf("or\n"); - printf("$ pmembench \n"); - printf(" # runs all scenarios from config file\n"); - printf("or\n"); - printf("$ pmembench [] [-h|--help [-v|--version]\n"); - printf(" # prints help\n"); - printf("or\n"); - printf("$ pmembench \n"); - printf(" # runs the specified scenario from config file\n"); - printf("$ pmembench " - " \n"); - printf(" # runs the specified scenarios from config file and overwrites" - " the given common_args from the config file\n"); -} - -/* - * pmembench_print_help -- print help for framework - */ -static void -pmembench_print_help() -{ - pmembench_print_version(); - pmembench_print_usage(); - printf("\nCommon arguments:\n"); - size_t nclos = sizeof(pmembench_opts) / sizeof(struct benchmark_clo); - pmembench_print_args(pmembench_opts, nclos); - - printf("\nAvaliable benchmarks:\n"); - struct benchmark *bench = nullptr; - PMDK_LIST_FOREACH(bench, &benchmarks.head, next) - printf("\t%-20s\t\t%s\n", bench->info->name, bench->info->brief); - printf("\n$ pmembench --help to print detailed information" - " about benchmark arguments\n"); - pmembench_print_examples(); -} - -/* - * pmembench_get_bench -- searching benchmarks by name - */ -static struct benchmark * -pmembench_get_bench(const char *name) -{ - struct benchmark *bench; - PMDK_LIST_FOREACH(bench, &benchmarks.head, next) - { - if (strcmp(name, bench->info->name) == 0) - return bench; - } - - return nullptr; -} - -/* - * pmembench_parse_opts -- parse arguments for framework - */ -static int -pmembench_parse_opts(struct pmembench *pb) -{ - int ret = 0; - int argc = ++pb->argc; - char **argv = --pb->argv; - struct benchmark_opts *opts = nullptr; - struct clo_vec *clovec; - size_t size, n_clos; - size = sizeof(struct benchmark_opts); - n_clos = ARRAY_SIZE(pmembench_opts); - clovec = clo_vec_alloc(size); - assert(clovec != nullptr); - - if (benchmark_clo_parse(argc, argv, pmembench_opts, n_clos, clovec)) { - ret = -1; - goto out; - } - - opts = (struct benchmark_opts *)clo_vec_get_args(clovec, 0); - if (opts == nullptr) { - ret = -1; - goto out; - } - - if (opts->help) - pmembench_print_help(); - if (opts->version) - pmembench_print_version(); - -out: - clo_vec_free(clovec); - return ret; -} - -/* - * pmembench_remove_file -- remove file or directory if exists - */ -static int -pmembench_remove_file(const char *path) -{ - int ret = 0; - os_stat_t status; - char *tmp; - - int exists = util_file_exists(path); - if (exists < 0) - return -1; - - if (!exists) - return 0; - - if (os_stat(path, &status) != 0) - return 0; - - if (!(status.st_mode & S_IFDIR)) - return pmempool_rm(path, 0); - - struct dir_handle it; - struct file_info info; - - if (util_file_dir_open(&it, path)) { - return -1; - } - - while (util_file_dir_next(&it, &info) == 0) { - if (strcmp(info.filename, ".") == 0 || - strcmp(info.filename, "..") == 0) - continue; - tmp = (char *)malloc(strlen(path) + strlen(info.filename) + 2); - if (tmp == nullptr) - return -1; - sprintf(tmp, "%s" OS_DIR_SEP_STR "%s", path, info.filename); - ret = info.is_dir ? pmembench_remove_file(tmp) - : util_unlink(tmp); - free(tmp); - if (ret != 0) { - util_file_dir_close(&it); - return ret; - } - } - - util_file_dir_close(&it); - - return util_file_dir_remove(path); -} - -/* - * pmembench_single_repeat -- runs benchmark ones - */ -static int -pmembench_single_repeat(struct benchmark *bench, struct benchmark_args *args, - struct bench_results *res) -{ - int ret = 0; - - if (args->main_affinity != -1) { - os_cpu_set_t cpuset; - os_cpu_zero(&cpuset); - os_thread_t self; - os_thread_self(&self); - os_cpu_set(args->main_affinity, &cpuset); - errno = os_thread_setaffinity_np(&self, sizeof(os_cpu_set_t), - &cpuset); - if (errno) { - perror("os_thread_setaffinity_np"); - return -1; - } - sched_yield(); - } - - if (bench->info->rm_file && !args->is_dynamic_poolset) { - ret = pmembench_remove_file(args->fname); - if (ret != 0 && errno != ENOENT) { - perror("removing file failed"); - - return ret; - } - } - - if (bench->info->init) { - if (bench->info->init(bench, args)) { - warn("%s: initialization failed", bench->info->name); - return -1; - } - } - - assert(bench->info->operation != nullptr); - assert(args->n_threads != 0); - - struct benchmark_worker **workers; - workers = (struct benchmark_worker **)malloc( - args->n_threads * sizeof(struct benchmark_worker *)); - assert(workers != nullptr); - - if ((ret = pmembench_init_workers(workers, bench, args)) != 0) { - goto out; - } - - unsigned j; - for (j = 0; j < args->n_threads; j++) { - benchmark_worker_run(workers[j]); - } - - for (j = 0; j < args->n_threads; j++) { - benchmark_worker_join(workers[j]); - if (workers[j]->ret != 0) { - ret = workers[j]->ret; - fprintf(stderr, "thread number %u failed\n", j); - } - } - - results_store(res, workers, args->n_threads, args->n_ops_per_thread); - - for (j = 0; j < args->n_threads; j++) { - benchmark_worker_exit(workers[j]); - - free(workers[j]->info.opinfo); - benchmark_worker_free(workers[j]); - } - -out: - free(workers); - - if (bench->info->exit) - bench->info->exit(bench, args); - - return ret; -} - -/* - * scale_up_min_exe_time -- scale up the number of operations to obtain an - * execution time not smaller than the assumed minimal execution time - */ -int -scale_up_min_exe_time(struct benchmark *bench, struct benchmark_args *args, - struct total_results **total_results) -{ - const double min_exe_time = args->min_exe_time; - struct total_results *total_res = *total_results; - total_res->nrepeats = 1; - do { - /* - * run single benchmark repeat to probe execution time - */ - int ret = pmembench_single_repeat(bench, args, - &total_res->res[0]); - if (ret != 0) - return 1; - get_total_results(total_res); - if (min_exe_time < total_res->total.min + MIN_EXE_TIME_E) - break; - - /* - * scale up number of operations to get assumed minimal - * execution time - */ - args->n_ops_per_thread = - (size_t)((double)args->n_ops_per_thread * - (min_exe_time + MIN_EXE_TIME_E) / - total_res->total.min); - - results_free(total_res); - *total_results = results_alloc(args); - assert(*total_results != nullptr); - total_res = *total_results; - total_res->nrepeats = 1; - } while (1); - total_res->nrepeats = args->repeats; - return 0; -} - -/* - * is_absolute_path_to_directory -- checks if passed argument is absolute - * path to directory - */ -static bool -is_absolute_path_to_directory(const char *path) -{ - os_stat_t sb; - - return util_is_absolute_path(path) && os_stat(path, &sb) == 0 && - S_ISDIR(sb.st_mode); -} - -/* - * pmembench_run -- runs one benchmark. Parses arguments and performs - * specific functions. - */ -static int -pmembench_run(struct pmembench *pb, struct benchmark *bench) -{ - enum file_type type; - char old_wd[PATH_MAX]; - int ret = 0; - - struct benchmark_args *args = nullptr; - struct total_results *total_res = nullptr; - struct latency *stats = nullptr; - double *workers_times = nullptr; - - struct clo_vec *clovec = nullptr; - - assert(bench->info != nullptr); - pmembench_merge_clos(bench); - - /* - * Check if PMEMBENCH_DIR env var is set and change - * the working directory accordingly. - */ - char *wd = os_getenv("PMEMBENCH_DIR"); - if (wd != nullptr) { - /* get current dir name */ - if (getcwd(old_wd, PATH_MAX) == nullptr) { - perror("getcwd"); - ret = -1; - goto out_release_clos; - } - os_stat_t stat_buf; - if (os_stat(wd, &stat_buf) != 0) { - perror("os_stat"); - ret = -1; - goto out_release_clos; - } - if (!S_ISDIR(stat_buf.st_mode)) { - warn("PMEMBENCH_DIR is not a directory: %s", wd); - ret = -1; - goto out_release_clos; - } - if (chdir(wd)) { - perror("chdir(wd)"); - ret = -1; - goto out_release_clos; - } - } - - if (bench->info->pre_init) { - if (bench->info->pre_init(bench)) { - warn("%s: pre-init failed", bench->info->name); - ret = -1; - goto out_old_wd; - } - } - - clovec = clo_vec_alloc(bench->args_size); - assert(clovec != nullptr); - - if (pmembench_parse_clo(pb, bench, clovec)) { - warn("%s: parsing command line arguments failed", - bench->info->name); - ret = -1; - goto out_release_args; - } - - args = (struct benchmark_args *)clo_vec_get_args(clovec, 0); - if (args == nullptr) { - warn("%s: parsing command line arguments failed", - bench->info->name); - ret = -1; - goto out_release_args; - } - - if (args->help) { - pmembench_print_help_single(bench); - goto out; - } - - if (strlen(args->fname) > PATH_MAX) { - warn("Filename too long"); - ret = -1; - goto out; - } - - type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - pmembench_print_header(pb, bench, clovec); - - size_t args_i; - for (args_i = 0; args_i < clovec->nargs; args_i++) { - - args = (struct benchmark_args *)clo_vec_get_args(clovec, - args_i); - if (args == nullptr) { - warn("%s: parsing command line arguments failed", - bench->info->name); - ret = -1; - goto out; - } - - args->opts = (void *)((uintptr_t)args + - sizeof(struct benchmark_args)); - - if (args->is_dynamic_poolset) { - if (!bench->info->allow_poolset) { - fprintf(stderr, - "dynamic poolset not supported\n"); - goto out; - } - - if (!is_absolute_path_to_directory(args->fname)) { - fprintf(stderr, - "path must be absolute and point to a directory\n"); - goto out; - } - } else { - args->is_poolset = - util_is_poolset_file(args->fname) == 1; - if (args->is_poolset) { - if (!bench->info->allow_poolset) { - fprintf(stderr, - "poolset files not supported\n"); - goto out; - } - args->fsize = util_poolset_size(args->fname); - if (!args->fsize) { - fprintf(stderr, - "invalid size of poolset\n"); - goto out; - } - } else if (type == TYPE_DEVDAX) { - args->fsize = util_file_get_size(args->fname); - - if (!args->fsize) { - fprintf(stderr, - "invalid size of device dax\n"); - goto out; - } - } - } - - unsigned n_threads_copy = args->n_threads; - args->n_threads = - !bench->info->multithread ? 1 : args->n_threads; - size_t n_ops_per_thread_copy = args->n_ops_per_thread; - args->n_ops_per_thread = - !bench->info->multiops ? 1 : args->n_ops_per_thread; - - stats = (struct latency *)calloc(args->repeats, - sizeof(struct latency)); - assert(stats != nullptr); - workers_times = (double *)calloc( - args->n_threads * args->repeats, sizeof(double)); - assert(workers_times != nullptr); - total_res = results_alloc(args); - assert(total_res != nullptr); - - unsigned i = 0; - if (args->min_exe_time != 0 && bench->info->multiops) { - ret = scale_up_min_exe_time(bench, args, &total_res); - if (ret != 0) - goto out; - i = 1; - } - - for (; i < args->repeats; i++) { - ret = pmembench_single_repeat(bench, args, - &total_res->res[i]); - if (ret != 0) - goto out; - } - - get_total_results(total_res); - pmembench_print_results(bench, args, total_res); - - args->n_ops_per_thread = n_ops_per_thread_copy; - args->n_threads = n_threads_copy; - - results_free(total_res); - free(stats); - free(workers_times); - total_res = nullptr; - stats = nullptr; - workers_times = nullptr; - } -out: - if (total_res) - results_free(total_res); - if (stats) - free(stats); - if (workers_times) - free(workers_times); -out_release_args: - clo_vec_free(clovec); - -out_old_wd: - /* restore the original working directory */ - if (wd != nullptr) { /* Only if PMEMBENCH_DIR env var was defined */ - if (chdir(old_wd)) { - perror("chdir(old_wd)"); - ret = -1; - } - } - -out_release_clos: - pmembench_release_clos(bench); - return ret; -} - -/* - * pmembench_free_benchmarks -- release all benchmarks - */ -static void __attribute__((destructor)) pmembench_free_benchmarks(void) -{ - while (!PMDK_LIST_EMPTY(&benchmarks.head)) { - struct benchmark *bench = PMDK_LIST_FIRST(&benchmarks.head); - PMDK_LIST_REMOVE(bench, next); - free(bench); - } -} - -/* - * pmembench_run_scenario -- run single benchmark's scenario - */ -static int -pmembench_run_scenario(struct pmembench *pb, struct scenario *scenario) -{ - struct benchmark *bench = pmembench_get_bench(scenario->benchmark); - if (nullptr == bench) { - fprintf(stderr, "unknown benchmark: %s\n", scenario->benchmark); - return -1; - } - pb->scenario = scenario; - return pmembench_run(pb, bench); -} - -/* - * pmembench_run_scenarios -- run all scenarios - */ -static int -pmembench_run_scenarios(struct pmembench *pb, struct scenarios *ss) -{ - struct scenario *scenario; - FOREACH_SCENARIO(scenario, ss) - { - if (pmembench_run_scenario(pb, scenario) != 0) - return -1; - } - return 0; -} - -/* - * pmembench_run_config -- run one or all scenarios from config file - */ -static int -pmembench_run_config(struct pmembench *pb, const char *config) -{ - struct scenarios *ss = nullptr; - struct config_reader *cr = config_reader_alloc(); - assert(cr != nullptr); - - int ret = 0; - - if ((ret = config_reader_read(cr, config))) - goto out; - - if ((ret = config_reader_get_scenarios(cr, &ss))) - goto out; - - assert(ss != nullptr); - - if (pb->argc == 1) { - if ((ret = pmembench_run_scenarios(pb, ss)) != 0) - goto out_scenarios; - } else { - /* Skip the config file name in cmd line params */ - int tmp_argc = pb->argc - 1; - char **tmp_argv = pb->argv + 1; - - if (!contains_scenarios(tmp_argc, tmp_argv, ss)) { - /* no scenarios in cmd line arguments - parse params */ - pb->override_clos = true; - if ((ret = pmembench_run_scenarios(pb, ss)) != 0) - goto out_scenarios; - } else { /* scenarios in cmd line */ - struct scenarios *cmd_ss = scenarios_alloc(); - assert(cmd_ss != nullptr); - - int parsed_scenarios = clo_get_scenarios( - tmp_argc, tmp_argv, ss, cmd_ss); - if (parsed_scenarios < 0) - goto out_cmd; - - /* - * If there are any cmd line args left, treat - * them as config file params override. - */ - if (tmp_argc - parsed_scenarios) - pb->override_clos = true; - - /* - * Skip the scenarios in the cmd line, - * pmembench_run_scenarios does not expect them and will - * fail otherwise. - */ - pb->argc -= parsed_scenarios; - pb->argv += parsed_scenarios; - ret = pmembench_run_scenarios(pb, cmd_ss); - - out_cmd: - scenarios_free(cmd_ss); - } - } - -out_scenarios: - scenarios_free(ss); -out: - config_reader_free(cr); - return ret; -} - -int -main(int argc, char *argv[]) -{ - util_init(); - util_mmap_init(); - - /* - * Parse common command line arguments and - * benchmark's specific ones. - */ - if (argc < 2) { - pmembench_print_usage(); - exit(EXIT_FAILURE); - } - - int ret = 0; - int fexists; - struct benchmark *bench; - struct pmembench *pb = (struct pmembench *)calloc(1, sizeof(*pb)); - assert(pb != nullptr); - Get_time_avg = benchmark_get_avg_get_time(); - - pb->argc = --argc; - pb->argv = ++argv; - - char *bench_name = pb->argv[0]; - if (nullptr == bench_name) { - ret = -1; - goto out; - } - - fexists = os_access(bench_name, R_OK) == 0; - bench = pmembench_get_bench(bench_name); - if (nullptr != bench) - ret = pmembench_run(pb, bench); - else if (fexists) - ret = pmembench_run_config(pb, bench_name); - else if ((ret = pmembench_parse_opts(pb)) != 0) { - pmembench_print_usage(); - goto out; - } - -out: - free(pb); - - util_mmap_fini(); - return ret; -} diff --git a/src/benchmarks/pmembench_atomic_lists.cfg b/src/benchmarks/pmembench_atomic_lists.cfg deleted file mode 100644 index daaf1c8f32..0000000000 --- a/src/benchmarks/pmembench_atomic_lists.cfg +++ /dev/null @@ -1,256 +0,0 @@ -# This is an example config file for pmembench - -# Global parameters -[global] -group = pmemobj -file = testfile.list -ops-per-thread = 10000 - -# obj_insert benchmark -# variable number of threads -# random type number, position and allocation size -[obj_list_insert_threads] -bench = obj_insert -threads = 1:+1:10 -data-size = 512 -position = rand -type-number = rand -min-size = 1 - -# obj_insert benchmark -# use circle queue from queue.h -# variable number of threads -# random type number, position and allocation size -[queue_list_insert_threads] -bench = obj_insert -threads = 1:+1:10 -data-size = 512 -position = rand -min-size = 1 -queue = true - -# obj_insert benchmark -# variable allocation size -# insert tail -# one type number per thread -[obj_list_insert_data_size] -bench = obj_insert -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread - -# obj_insert benchmark -# use circle queue from queue.h -# variable allocation size -# insert tail -# one type number per thread -[queue_list_insert_data_size] -bench = obj_insert -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread -queue = true - -# obj_insert benchmark -# variable number of threads -# insert int the middle -# one type-number -[obj_list_insert_list_len] -bench = obj_insert -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 - -# obj_insert benchmark -# use circle queue from queue.h -# variable number of threads -# insert int the middle -# one type-number -[queue_list_insert_list_len] -bench = obj_insert -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 -queue = true - -# obj_insert_new benchmark -# variable number of threads -# random type number, position and allocation size -[obj_list_insert_new_threads] -bench = obj_insert_new -threads = 1:+1:10 -data-size = 512 -position = rand -type-number = rand -min-size = 1 - -# obj_insert_new benchmark -# variable allocation size -# insert tail -# one type number per thread -[obj_list_insert_new_data_size] -bench = obj_insert_new -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread - -# obj_insert_new benchmark -# variable number of threads -# insert int the middle -# one type-number -[obj_list_insert_new_list_len] -bench = obj_insert_new -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 - -# obj_remove benchmark -# variable number of threads -# random type number, position and allocation size -[obj_list_remove_threads] -bench = obj_remove -threads = 1:+1:10 -data-size = 512 -position = rand -type-number = rand -min-size = 1 - -# obj_remove benchmark -# use circle queue from queue.h -# variable number of threads -# random type number, position and allocation size -[queue_list_remove_threads] -bench = obj_remove -threads = 1:+1:10 -data-size = 512 -position = rand -type-number = rand -min-size = 1 -queue = true - -# obj_remove benchmark -# variable allocation size -# insert tail -# one type number per thread -[obj_list_remove_data_size] -bench = obj_remove -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread - -# obj_remove benchmark -# use circle queue from queue.h -# variable allocation size -# insert tail -# one type number per thread -[queue_list_remove_data_size] -bench = obj_remove -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread -queue = true - -# obj_remove benchmark -# variable number of threads -# insert int the middle -# one type-number -[obj_list_remove_list_len] -bench = obj_remove -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 - -# obj_remove benchmark -# use circle queue from queue.h -# variable number of threads -# insert int the middle -# one type-number -[queue_list_remove_list_len] -bench = obj_remove -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 -queue = true - -# obj_remove_free benchmark -# variable number of threads -# random type number, position and allocation size -[obj_list_remove_free_threads] -bench = obj_remove_free -threads = 1:+1:10 -data-size = 512 -position = rand -type-number = rand -min-size = 1 - -# obj_remove_free benchmark -# variable allocation size -# insert tail -# one type number per thread -[obj_list_remove_free_data_size] -bench = obj_remove_free -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread - -# obj_remove_free benchmark -# variable number of threads -# insert int the middle -# one type-number -[obj_list_remove_free_list_len] -bench = obj_remove_free -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 - -# obj_move benchmark -# variable number of threads -# random type number, position and allocation size -[obj_list_move_threads] -bench = obj_move -threads = 1:+1:10 -data-size = 512 -position = rand -type-number = rand -min-size = 1 - -# obj_move benchmark -# variable allocation size -# insert tail -# one type number per thread -[obj_list_move_data_size] -bench = obj_move -threads = 1 -data-size = 2:*2:8192 -position = tail -type-number = per-thread - -# obj_move benchmark -# variable number of threads -# insert int the middle -# one type-number -[obj_list_move_list_len] -bench = obj_move -threads = 1:+1:10 -data-size = 512 -position = middle -type-number = one -list-len = 1000 diff --git a/src/benchmarks/pmembench_flush.cfg b/src/benchmarks/pmembench_flush.cfg deleted file mode 100644 index 6434c63453..0000000000 --- a/src/benchmarks/pmembench_flush.cfg +++ /dev/null @@ -1,63 +0,0 @@ -# -# pmembench_flush.cfg -- this is an example config file for pmembench -# with scenarios for pmem_persist & pmem_msync benchmark -# - -# Global parameters -[global] -group = pmem -file = testfile.flush -ops-per-thread = 100000 -repeats = 3 -threads = 1:*2:16 -data-size = 64:*2:8192 -mode = rand -no-warmup = false - -[flush_noop] -bench = pmem_flush -operation = noop - -[flush_persist] -bench = pmem_flush -operation = persist - -[flush_persist_4K] -bench = pmem_flush -operation = persist_4K - -[flush_persist_2M] -bench = pmem_flush -operation = persist_2M - -[flush_persist_4K_msync_0] -bench = pmem_flush -operation = persist_4K_msync_0 - -[flush_persist_2M_msync_0] -bench = pmem_flush -operation = persist_2M_msync_0 - -[flush_msync] -bench = pmem_flush -operation = msync - -[flush_msync_0] -bench = pmem_flush -operation = msync_0 - -[flush_msync_async] -bench = pmem_flush -operation = msync_async - -[flush_msync_err] -bench = pmem_flush -operation = msync_err - -[flush_msync_invalid] -bench = pmem_flush -operation = msync_invalid - -[flush_msync_nodirty] -bench = pmem_flush -operation = msync_nodirty diff --git a/src/benchmarks/pmembench_map.cfg b/src/benchmarks/pmembench_map.cfg deleted file mode 100644 index bc591cc3c9..0000000000 --- a/src/benchmarks/pmembench_map.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[global] -group = pmemobj -file = testfile.map -ops-per-thread=1000000 -threads=1 -type = ctree,btree,rtree,rbtree,hashmap_atomic,hashmap_tx,hashmap_rp - -[map_insert] -bench = map_insert - -[map_remove] -bench = map_remove - -[map_get] -bench = map_get diff --git a/src/benchmarks/pmembench_memcpy.cfg b/src/benchmarks/pmembench_memcpy.cfg deleted file mode 100644 index bcd07293b8..0000000000 --- a/src/benchmarks/pmembench_memcpy.cfg +++ /dev/null @@ -1,73 +0,0 @@ -# Global parameters -[global] -group = pmem -file = testfile.memcpy -ops-per-thread=50000 - -# pmem_memcpy benchmark with variable chunk sizes -# from 64 to 8k bytes -[pmcpy_chunk_sizes_aligned] -bench = pmem_memcpy -threads = 1 -data-size = 64:*2:8192 - -# pmem_memcpy benchmark -# with variable destination address offsets -[pmcpy_destination_offsets] -bench = pmem_memcpy -threads = 1 -data-size = 512 -src-offset = 0 -dest-offset = 1:+1:63 - -# pmem_memcpy pmem_memcpy_persist -# copy mode: random -# from 64 to 8k bytes -[pmcpy_chunk_sizes_rand] -bench = pmem_memcpy -threads = 1 -data-size = 64:*2:8192 -src-mode = rand -dest-mode = rand - -# pmem_memcpy pmem_memcpy_persist() -# copy mode: sequential -# from 64 to 8k bytes -[pmcpy_pmem_memcpy_persist] -bench = pmem_memcpy -threads = 1 -data-size = 64:*2:8192 -libc-memcpy = false -persist = true - -# pmem_memcpy pmem_memcpy_nodrain() -# copy mode: sequential -# from 64 to 8k bytes -[pmcpy_pmem_memcpy_nodrain] -bench = pmem_memcpy -threads = 1 -data-size = 64:*2:8192 -libc-memcpy = false -persist = false - -# pmem_memcpy standard memcpy() -# followed by pmem_persist() -# copy mode: sequential -# from 64 to 8k bytes -[pmcpy_libc_memcpy_persist] -bench = pmem_memcpy -threads = 1 -data-size = 64:*2:8192 -libc-memcpy = true -persist = true - -# pmem_memcpy standard memcpy() -# followed by pmem_flush() -# copy mode: sequential -# from 64 to 8k bytes -[pmcpy_libc_memcpy_flush] -bench = pmem_memcpy -threads = 1 -data-size = 64:*2:8192 -libc-memcpy = true -persist = false diff --git a/src/benchmarks/pmembench_memset.cfg b/src/benchmarks/pmembench_memset.cfg deleted file mode 100644 index 8330edc602..0000000000 --- a/src/benchmarks/pmembench_memset.cfg +++ /dev/null @@ -1,96 +0,0 @@ -# -# pmembench_memset.cfg -- this is an example config file for pmembench -# with scenarios for pmem_memset benchmark -# - -# Global parameters -[global] -group = pmem -file = testfile.memset -ops-per-thread = 10000 - -# memset benchmark with variable data sizes -# from 1 to 32 bytes -[pmem_memset_data_sizes_small] -bench = pmem_memset -threads = 1 -data-size = 1:+1:32 - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# mode random -[pmem_memset_data_sizes_rand] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -mem-mode = rand - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# offset 10 -[pmem_memset_data_sizes_offset] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -dest-offset = 10 - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# mode sequential -# pmem_memset_persist() -[pmem_memset_pmem_memset_persist] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -memset = false -persist = true -mem-mode = seq - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# mode sequential -# pmem_memset_nodrain() -[pmem_memset_pmem_memset_nodrain] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -memset = false -persist = false -mem-mode = seq - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# mode sequential -# memset followed by pmem_persist() -[pmem_memset_libc_memset_persist] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -memset = true -persist = true -mem-mode = seq - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# mode sequential -# memset followed by pmem_flush() -[pmem_memset_libc_memset_flush] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -memset = true -persist = false -mem-mode = seq - -# memset benchmark with variable data sizes -# from 64 to 8k bytes -# mode sequential -# memset followed by pmem_msync() -[pmem_memset_libc_memset_msync] -bench = pmem_memset -threads = 1 -data-size = 64:*2:8192 -memset = true -persist = false -msync = true -mem-mode = seq diff --git a/src/benchmarks/pmembench_obj_gen.cfg b/src/benchmarks/pmembench_obj_gen.cfg deleted file mode 100644 index ecf523e3f1..0000000000 --- a/src/benchmarks/pmembench_obj_gen.cfg +++ /dev/null @@ -1,58 +0,0 @@ -# This is an example config file for pmembench - -# Global parameters -[global] -group = pmemobj -file = testfile.obj -ops-per-thread = 100 - -[obj_open_sizes] -bench = obj_open -data-size = 2:*2:1024 -min-size = 1 -objects = 10000 -type-number = rand - -[obj_open_objects] -bench = obj_open -data-size = 1024 -objects = 1:*10:100000 -type-number = rand - -[obj_open_threads] -bench = obj_open -threads = 1:+1:10 -data-size = 1024 -min-size = 1 -objects = 1000 -type-number = rand - -[obj_direct_threads_one_pool] -bench = obj_direct -threads = 1:+1:10 -data-size = 1025 -min-size = 1024 -type-number = rand -one-pool = true - -[obj_direct_threads_many_pools] -bench = obj_direct -threads = 1:+1:10 -data-size = 1025 -min-size = 1024 -type-number = rand - -[obj_direct_data_one_pool_one_obj] -bench = obj_direct -data-size = 2:*2:8192 -type-number = rand -one-pool = true -one-object = true -ops-per-thread = 10000 - -[obj_direct_threads_many_pools_one_obj] -bench = obj_direct -data-size = 2:*2:8192 -type-number = rand -one-object = true -ops-per-thread = 10000 diff --git a/src/benchmarks/pmembench_obj_lanes.cfg b/src/benchmarks/pmembench_obj_lanes.cfg deleted file mode 100644 index dd228f90f2..0000000000 --- a/src/benchmarks/pmembench_obj_lanes.cfg +++ /dev/null @@ -1,9 +0,0 @@ -# Global parameters -[global] -group = pmemobj -file = ./testfile.lane -ops-per-thread = 100000 -threads = 1:*2:32 - -[lanes] -bench = obj_lanes diff --git a/src/benchmarks/pmembench_obj_locks.cfg b/src/benchmarks/pmembench_obj_locks.cfg deleted file mode 100644 index adbfbe8c19..0000000000 --- a/src/benchmarks/pmembench_obj_locks.cfg +++ /dev/null @@ -1,239 +0,0 @@ -# Global parameters -[global] -group = pmemobj -file = ./testfile.locks -ops-per-thread = 1000000:*10:10000000 - -# Single mutex benchmarks -[single_pmem_locks] -bench = obj_locks - -[single_pmem_locks_uninitialized] -bench = obj_locks -run_id = true -run_id_init_val = 4 - -[single_system_mutex] -bench = obj_locks -use_system_threads = true - -# Multiple mutex benchmarks - 1by1 -[multiple_pmem_locks_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 - -[multiple_pmem_locks_uninitialized_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -run_id_init_val = 4 - -[multiple_system_mutex_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -use_system_threads = true -numlocks = 1000000:*10:10000000 - -[multiple_pmem_locks_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 - -[multiple_pmem_locks_uninitialized_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -run_id = true -run_id_init_val = 4 - -[multiple_system_mutex_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -use_system_threads = true - -# Multiple mutex benchmarks - all-lock -[multiple_pmem_locks_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -mode = all-lock - -[multiple_pmem_locks_uninitialized_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -mode = all-lock -run_id = true -run_id_init_val = 4 - -[multiple_system_mutex_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -use_system_threads = true -mode = all-lock - -[multiple_pmem_locks_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -mode = all-lock - -[multiple_pmem_locks_uninitialized_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -run_id = true -run_id_init_val = 4 -mode = all-lock - -[multiple_system_mutex_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -use_system_threads = true -mode = all-lock - -#rwlock benchmarks -[single_pmem_wrlock] -bench = obj_locks -bench_type = rwlock - -[single_pmem_rdlock] -bench = obj_locks -bench_type = rwlock -rdlock = true - -[single_system_wrlock] -bench = obj_locks -bench_type = rwlock -use_system_threads = true - -[single_system_rdlock] -bench = obj_locks -bench_type = rwlock -rdlock = true -use_system_threads = true - -[multiple_pmem_wrlock_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -bench_type = rwlock - -[multiple_pmem_wrlock_uninitialized_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -run_id_init_val = 4 -bench_type = rwlock - -[multiple_system_wrlock_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -use_system_threads = true -numlocks = 1000000:*10:10000000 -bench_type = rwlock - -[multiple_pmem_wrlock_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -bench_type = rwlock - -[multiple_pmem_wrlock_uninitialized_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -run_id = true -run_id_init_val = 4 -bench_type = rwlock - -[multiple_system_wrlock_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -use_system_threads = true -bench_type = rwlock - -[multiple_pmem_wrlock_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -bench_type = rwlock -mode = all-lock - -[multiple_pmem_wrlock_uninitialized_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -run_id_init_val = 4 -bench_type = rwlock -mode = all-lock - -[multiple_system_wrlock_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -use_system_threads = true -numlocks = 1000000:*10:10000000 -bench_type = rwlock -mode = all-lock - -[multiple_pmem_wrlock_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -bench_type = rwlock -mode = all-lock - -[multiple_pmem_wrlock_uninitialized_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -run_id = true -run_id_init_val = 4 -bench_type = rwlock -mode = all-lock - -[multiple_system_wrlock_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -use_system_threads = true -bench_type = rwlock -mode = all-lock - -# volatile mutex - only for testing -# it is an alternate implementation of PMEMmutex, which keeps -# the system mutex in RAM -[single_volatile_mutex] -bench = obj_locks -bench_type = volatile-mutex - -[multiple_volatile_mutex_locked_once_1by1] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -bench_type = volatile-mutex - -[multiple_volatile_mutex_1by1] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -bench_type = volatile-mutex - -[multiple_volatile_mutex_locked_once_alllock] -bench = obj_locks -ops-per-thread = 1 -numlocks = 1000000:*10:10000000 -mode = all-lock -bench_type = volatile-mutex - -[multiple_volatile_mutex_alllock] -bench = obj_locks -numlocks = 10000:*10:100000 -ops-per-thread = 10000:/10:100 -mode = all-lock -bench_type = volatile-mutex diff --git a/src/benchmarks/pmembench_obj_persist.cfg b/src/benchmarks/pmembench_obj_persist.cfg deleted file mode 100644 index 701548b283..0000000000 --- a/src/benchmarks/pmembench_obj_persist.cfg +++ /dev/null @@ -1,25 +0,0 @@ -# -# pmembench_obj_persist.cfg -- this is an example config file for pmembench -# with scenarios for pmemobj_persist() benchmark -# - -# Global parameters -[global] -group = obj_persist -file = testfile.obj_persist -ops-per-thread = 10000 - -[pmemobj_persist_DS8] -bench = pmemobj_persist -threads = 1:+1:32 -data-size = 8 - -[pmemobj_persist_DS512] -bench = pmemobj_persist -threads = 1:+1:32 -data-size = 512 - -[pmemobj_persist_DS1024] -bench = pmemobj_persist -threads = 1:+1:32 -data-size = 1024 diff --git a/src/benchmarks/pmembench_obj_pmalloc.cfg b/src/benchmarks/pmembench_obj_pmalloc.cfg deleted file mode 100644 index 83fcb35218..0000000000 --- a/src/benchmarks/pmembench_obj_pmalloc.cfg +++ /dev/null @@ -1,33 +0,0 @@ -# Global parameters -[global] -group = pmemobj -file = ./testfile.pmalloc -ops-per-thread = 1000 -data-size = 4096 -threads = 1 - -#Single thread benchmarks -[pmalloc_single_thread_size] -bench = pmalloc -data-size = 64:*2:262144 - -[pmalloc_single_thread_ops] -bench = pmalloc -ops-per-thread = 10:*10:100000 - -[pfree_single_thread_size] -bench = pfree -data-size = 64:*2:262144 - -[pfree_single_thread_ops] -bench = pfree -ops-per-thread = 10:*10:100000 - -#Multithreaded benchmarks -[pmalloc_multi_thread] -bench = pmalloc -threads = 2:*2:32 - -[pfree_multi_thread] -bench = pfree -threads = 2:*2:32 diff --git a/src/benchmarks/pmembench_tx.cfg b/src/benchmarks/pmembench_tx.cfg deleted file mode 100644 index 0233f3fe3e..0000000000 --- a/src/benchmarks/pmembench_tx.cfg +++ /dev/null @@ -1,379 +0,0 @@ -# This is an example config file for pmembench - -# Global parameters -[global] -file = /dev/shm/testfile.tx -group = pmemobj -ops-per-thread = 100 - -# obj_tx_alloc benchmark -# variable threads number -# one type-number -[obj_tx_alloc_thread_one_type_num] -bench = obj_tx_alloc -threads = 1:+1:5 -data-size = 512 - -# obj_tx_alloc benchmark -# variable threads number -# one type-number per thread -[obj_tx_alloc_thread_per_thread_type_num] -bench = obj_tx_alloc -threads = 1:+1:5 -data-size = 512 -type-number = per-thread - -# obj_tx_alloc benchmark -# variable allocation size -# abort every nested transaction -# rand type-number -[obj_tx_alloc_sizes_abort_nested] -bench = obj_tx_alloc -data-size = 8:*2:16384 -operation = abort-nested -nestings = 100 -type-number = rand - -# obj_tx_alloc benchmark -# variable allocation size -# use file io instead pmem -# rand type-number -[obj_tx_alloc_sizes_file_io] -bench = obj_tx_alloc -data-size = 8:*2:16384 -nestings = 100 -lib = dram -type-number = rand - -# obj_tx_alloc benchmark -# variable allocation size -# pmem without transactions -# rand type-number -[obj_tx_alloc_sizes_atomic] -bench = obj_tx_alloc -data-size = 8:*2:16384 -nestings = 100 -lib = pmem -type-number = rand - -# obj_tx_alloc benchmark -# variable number of nested transactions -# abort every nested transaction -# rand type-number -[obj_tx_alloc_nestings_abort_nested] -bench = obj_tx_alloc -data-size = 512 -min-size = 1 -operation = abort-nested -nestings = 1:*10:10000 -type-number = rand - -# obj_tx_alloc benchmark -# variable number of nested transactions -# use file io instead pmem -# rand type-number -[obj_tx_alloc_nestings_file_io] -bench = obj_tx_alloc -data-size = 512 -min-size = 1 -nestings = 1:*10:10000 -lib = dram -type-number = rand - -# obj_tx_alloc benchmark -# variable number of nested transactions -# pmem without transactions -# rand type-number -[obj_tx_alloc_nestings_atomic] -bench = obj_tx_alloc -data-size = 512 -min-size = 1 -nestings = 1:*10:10000 -lib = pmem -type-number = rand - -# obj_tx_free benchmark -# variable allocation size -# abort every nested transaction -# rand type-number -[obj_tx_free_sizes_abort_nested] -bench = obj_tx_free -data-size = 8:*2:8192 -operation = abort-nested -nestings = 100 -type-number = rand - -# obj_tx_free benchmark -# variable allocation size -# use file io instead pmem -# rand type-number -[obj_tx_free_sizes_file_io] -bench = obj_tx_free -data-size = 8:*2:8192 -nestings = 100 -lib = dram -type-number = rand - -# obj_tx_free benchmark -# variable allocation size -# pmem without transactions -# rand type-number -[obj_tx_free_sizes_atomic] -bench = obj_tx_free -data-size = 8:*2:8192 -nestings = 100 -lib = pmem -type-number = rand - -# obj_tx_free benchmark -# variable number of nested transactions -# abort every nested transaction -# rand type-number -[obj_tx_free_nestings_abort_nested] -bench = obj_tx_free -data-size = 512 -min-size = 1 -operation = abort-nested -nestings = 1:*10:10000 -type-number = rand - -# obj_tx_free benchmark -# variable number of nested transactions -# use file io instead pmem -# rand type-number -[obj_tx_free_nestings_file_io] -bench = obj_tx_free -data-size = 512 -min-size = 1 -nestings = 1:*10:10000 -lib = dram -type-number = rand - -# obj_tx_free benchmark -# variable number of nested transactions -# pmem without transactions -# rand type-number -[obj_tx_free_nestings_atomic] -bench = obj_tx_free -data-size = 512 -min-size = 1 -nestings = 1:*10:10000 -lib = pmem -type-number = rand - -# obj_tx_realloc benchmark -# variable allocation size -# abort every nested transaction -# rand type-number -[obj_tx_realloc_data_sizes_abort] -bench = obj_tx_realloc -data-size = 8:*2:8192 -realloc-size = 64 -min-rsize = 1 -operation = abort -nestings = 100 -type-number = rand - -# obj_tx_realloc benchmark -# variable allocation size -# use file io instead pmem -# rand type-number -[obj_tx_realloc_data_sizes_file_io] -bench = obj_tx_realloc -data-size = 8:*2:8192 -realloc-size = 64 -min-rsize = 1 -nestings = 100 -lib = dram -type-number = rand - -# obj_tx_realloc benchmark -# variable allocation size -# pmem without transactions -# rand type-number -[obj_tx_realloc_data_sizes_atomic] -bench = obj_tx_realloc -data-size = 8:*2:8192 -realloc-size = 64 -min-rsize = 1 -nestings = 100 -lib = pmem -type-number = rand - -# obj_tx_realloc benchmark -# variable reallocation size -# abort every nested transaction -# rand type-number -# another type number in realloc than in alloc -[obj_tx_realloc_sizes_abort] -bench = obj_tx_realloc -data-size = 4 -min-size = 1 -realloc-size = 256:*2:16384 -operation = abort -changed-type = true -type-number = rand - -# obj_tx_realloc benchmark -# variable reallocation size -# use file io instead pmem -# rand type-number -[obj_tx_realloc_sizes_file_io] -bench = obj_tx_realloc -data-size = 4 -min-size = 1 -realloc-size = 256:*2:16384 -lib = dram -type-number = rand - -# obj_tx_realloc benchmark -# variable reallocation size -# abort every nested transaction -# rand type-number -# another type number in realloc than in alloc -[obj_tx_realloc_sizes_atomic] -bench = obj_tx_realloc -data-size = 4 -min-size = 1 -realloc-size = 256:*2:16384 -lib = pmem -changed-type = true -type-number = rand - -# obj_tx_add_range benchmark -# variable allocation size -# allocate different objects -# in one transaction -# rand type-number -[obj_tx_add_sizes_all_obj] -bench = obj_tx_add_range -data-size = 128:*2:16384 -operation = all-obj -type-number = rand - -# obj_tx_add_range benchmark -# variable operations number -# allocate different objects -# in one transaction -# rand type-number -[obj_tx_add_ops_all_obj] -bench = obj_tx_add_range -data-size = 512 -operation = all-obj -ops-per-thread = 1:*5:625 -type-number = rand - -# obj_tx_add_range benchmark -# variable allocation size -# allocate one object -# in one transaction -# rand type-number -[obj_tx_add_sizes_one_obj] -bench = obj_tx_add_range -data-size = 128:*2:16384 -operation = basic -type-number = rand - -# obj_tx_add_range benchmark -# variable operations number -# allocate one object -# in one transaction -# rand type-number -[obj_tx_add_ops_one_obj] -bench = obj_tx_add_range -data-size = 10000 -operation = basic -ops-per-thread = 1:*5:78125 -type-number = rand - -# obj_tx_add_range benchmark -# variable allocation size -# allocate parts of one object -# in one transaction -# rand type-number -[obj_tx_add_sizes_range] -bench = obj_tx_add_range -data-size = 128:*2:16384 -operation = range -type-number = rand - -# obj_tx_add_range benchmark -# variable operations number -# allocate parts of one object -# in one transaction -# rand type-number -[obj_tx_add_ops_range] -bench = obj_tx_add_range -data-size = 10000 -operation = range -ops-per-thread = 1:*5:625 -type-number = rand - -# obj_tx_add_range benchmark -# variable allocation size -# allocate all objects -# in many nested transactions -# rand type-number -[obj_tx_add_sizes_all_obj_nested] -bench = obj_tx_add_range -data-size = 128:*2:16384 -operation = all-obj-nested -type-number = rand - -# obj_tx_add_range benchmark -# variable operations number -# allocate all objects -# in many nested transactions -# rand type-number -[obj_tx_add_ops_all_obj_nested] -bench = obj_tx_add_range -data-size = 10000 -operation = all-obj-nested -ops-per-thread = 1:*5:625 -type-number = rand - -# obj_tx_add_range benchmark -# variable allocation size -# allocate one object -# in many nested transactions -# rand type-number -[obj_tx_add_sizes_one_obj_nested] -bench = obj_tx_add_range -data-size = 128:*2:16384 -operation = one-obj-nested -type-number = rand - -# obj_tx_add_range benchmark -# variable operations number -# allocate one object -# in many nested transactions -# rand type-number -[obj_tx_add_ops_one_obj_nested] -bench = obj_tx_add_range -data-size = 10000 -operation = one-obj-nested -ops-per-thread = 1:*5:625 -type-number = rand - -# obj_tx_add_range benchmark -# variable allocation size -# allocate parts of one object -# in many nested transactions -# rand type-number -[obj_tx_add_sizes_range_nested] -bench = obj_tx_add_range -data-size = 128:*2:16384 -operation = range-nested -type-number = rand - -# obj_tx_add_range benchmark -# variable operations number -# allocate parts of one objects -# in many nested transactions -# rand type-number -[obj_tx_add_ops_range_nested] -bench = obj_tx_add_range -data-size = 10000 -operation = range-nested -ops-per-thread = 1:*5:625 -type-number = rand diff --git a/src/benchmarks/pmembench_tx_add_range.cfg b/src/benchmarks/pmembench_tx_add_range.cfg deleted file mode 100644 index 344ac17f7b..0000000000 --- a/src/benchmarks/pmembench_tx_add_range.cfg +++ /dev/null @@ -1,26 +0,0 @@ -# -# pmembench_tx_add_range.cfg -- this is an example config file for pmembench -# with scenarios for pmemobj_tx_add_range benchmark -# - -# Global parameters -[global] -group = obj_tx_add_range -file = testfile.obj_persist -ops-per-thread = 10000 - -[pmemobj_tx_add_range_sizes] -bench = pmemobj_tx_add_range -threads = 1 -data-size = 128:*2:16384 -num-of-ranges = 1000 -shuffle = true -seed = 10 - -[pmemobj_tx_add_range_threads] -bench = pmemobj_tx_add_range -threads = 1:*2:32 -data-size = 512 -num-of-ranges = 1000 -shuffle = true -seed = 10 diff --git a/src/benchmarks/pmemobj_atomic_lists.cpp b/src/benchmarks/pmemobj_atomic_lists.cpp deleted file mode 100644 index 33fead9a54..0000000000 --- a/src/benchmarks/pmemobj_atomic_lists.cpp +++ /dev/null @@ -1,1094 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ - -/* - * pmemobj_atomic_lists.cpp -- benchmark for pmemobj atomic list API - */ - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" -#include "queue.h" -#include -#include -#include -#include -#include -#include -#include - -#define FACTOR 8 -#define LAYOUT_NAME "benchmark" - -struct obj_bench; -struct obj_worker; -struct element; - -TOID_DECLARE(struct item, 0); -TOID_DECLARE(struct list, 1); - -typedef size_t (*fn_type_num_t)(size_t worker_idx, size_t op_idx); - -typedef struct element (*fn_position_t)(struct obj_worker *obj_worker, - size_t op_idx); - -typedef int (*fn_init_t)(struct worker_info *worker, size_t n_elm, - size_t list_len); -/* - * args -- stores command line parsed arguments. - */ -struct obj_list_args { - char *type_num; /* type_number mode - one, per-thread, rand */ - char *position; /* position - head, tail, middle, rand */ - unsigned list_len; /* initial list length */ - bool queue; /* use circle queue from */ - bool range; /* use random allocation size */ - unsigned min_size; /* minimum random allocation size */ - unsigned seed; /* seed value */ -}; - -/* - * obj_bench -- stores variables used in benchmark, passed within functions. - */ -static struct obj_bench { - - /* handle to persistent pool */ - PMEMobjpool *pop; - - /* pointer to benchmark specific arguments */ - struct obj_list_args *args; - - /* array to store random type_number values */ - size_t *random_types; - - /* - * fn_rpositions array stores random functions returning proper element - * from list, if position where operation is performed is random. - * Possible function which can be in array are: - * - position_head, - * - position_tail, - * - position_middle. - */ - size_t *alloc_sizes; /* array to store random sizes of each object */ - size_t max_len; /* maximum list length */ - size_t min_len; /* initial list length */ - int type_mode; /* type_number mode */ - int position_mode; /* list destination mode */ - - /* - * fn_type_num gets proper function assigned, depending on the - * value of the type_mode argument, which returns proper type number for - * each persistent object. Possible functions are: - * - type_mode_one, - * - type_mode_per_thread, - * - type_mode_rand. - */ - fn_type_num_t fn_type_num; - - /* - * fn_position gets proper function assigned, depending on the value - * of the position argument, which returns handle to proper element on - * the list. Possible functions are: - * - position_head, - * - position_tail, - * - position_middle, - * - position_rand. - */ - fn_position_t fn_position; - - /* - * fn_init gets proper function assigned, depending on the file_io - * flag, which allocates objects and initializes proper list. Possible - * functions are: - * - obj_init_list, - * - queue_init_list. - */ - fn_init_t fn_init; -} obj_bench; - -/* - * item -- structure used to connect elements in lists. - */ -struct item { - POBJ_LIST_ENTRY(struct item) field; - PMDK_CIRCLEQ_ENTRY(item) fieldq; -}; - -/* - * element -- struct contains one item from list with proper type. - */ -struct element { - struct item *itemq; - TOID(struct item) itemp; - bool before; -}; - -/* - * obj_worker -- stores variables used by one thread, concerning one list. - */ -struct obj_worker { - - /* head of the pmemobj list */ - POBJ_LIST_HEAD(plist, struct item) head; - - /* head of the circular queue */ - PMDK_CIRCLEQ_HEAD(qlist, item) headq; - TOID(struct item) * oids; /* persistent pmemobj list elements */ - struct item **items; /* volatile elements */ - size_t n_elm; /* number of elements in array */ - fn_position_t *fn_positions; /* element access functions */ - struct element elm; /* pointer to current element */ - /* - * list_move is a pointer to structure storing variables used by - * second list (used only for obj_move benchmark). - */ - struct obj_worker *list_move; -}; - -/* - * position_mode -- list destination type - */ -enum position_mode { - /* object inserted/removed/moved to/from head of list */ - POSITION_MODE_HEAD, - - /* object inserted/removed/moved to/from tail of list */ - POSITION_MODE_TAIL, - - /* - * object inserted/removed/moved to/from second element of the list - * or to/from head if list length equal to one - */ - POSITION_MODE_MIDDLE, - - /* object inserted/removed/moved to/from head, tail or middle */ - POSITION_MODE_RAND, - POSITION_MODE_UNKNOWN, -}; - -/* - * type_mode -- type number type - */ -enum type_mode { - TYPE_MODE_ONE, /* one type number for all of objects */ - - /* one type number for objects allocated by the same thread */ - TYPE_MODE_PER_THREAD, - TYPE_MODE_RAND, /* random type number for each object */ - TYPE_MODE_UNKNOWN, -}; - -/* - * position_head -- returns head of the persistent list or volatile queue. - */ -static struct element -position_head(struct obj_worker *obj_worker, size_t op_idx) -{ - struct element head = {nullptr, OID_NULL, false}; - head.before = true; - if (!obj_bench.args->queue) - head.itemp = POBJ_LIST_FIRST(&obj_worker->head); - else - head.itemq = PMDK_CIRCLEQ_FIRST(&obj_worker->headq); - return head; -} - -/* - * position_tail -- returns tail of the persistent list or volatile queue. - */ -static struct element -position_tail(struct obj_worker *obj_worker, size_t op_idx) -{ - struct element tail = {nullptr, OID_NULL, false}; - tail.before = false; - if (!obj_bench.args->queue) - tail.itemp = POBJ_LIST_LAST(&obj_worker->head, field); - else - tail.itemq = PMDK_CIRCLEQ_LAST(&obj_worker->headq); - return tail; -} - -/* - * position_middle -- returns second or first element from the persistent list - * or volatile queue. - */ -static struct element -position_middle(struct obj_worker *obj_worker, size_t op_idx) -{ - struct element elm = position_head(obj_worker, op_idx); - elm.before = true; - if (!obj_bench.args->queue) - elm.itemp = POBJ_LIST_NEXT(elm.itemp, field); - else - elm.itemq = PMDK_CIRCLEQ_NEXT(elm.itemq, fieldq); - return elm; -} - -/* - * position_rand -- returns first, second or last element from the persistent - * list or volatile queue based on r_positions array. - */ -static struct element -position_rand(struct obj_worker *obj_worker, size_t op_idx) -{ - struct element elm; - elm = obj_worker->fn_positions[op_idx](obj_worker, op_idx); - elm.before = true; - return elm; -} - -/* - * type_mode_one -- always returns 0, as in the mode TYPE_MODE_ONE - * all of the persistent objects have the same type_number value. - */ -static size_t -type_mode_one(size_t worker_idx, size_t op_idx) -{ - return 0; -} - -/* - * type_mode_per_thread -- always returns the index of the worker, - * as in the TYPE_MODE_PER_THREAD the value of the persistent object - * type_number is specific to the thread. - */ -static size_t -type_mode_per_thread(size_t worker_idx, size_t op_idx) -{ - return worker_idx; -} - -/* - * type_mode_rand -- returns the value from the random_types array assigned - * for the specific operation in a specific thread. - */ -static size_t -type_mode_rand(size_t worker_idx, size_t op_idx) -{ - return obj_bench.random_types[op_idx]; -} - -const char *type_num_names[] = {"one", "per-thread", "rand"}; -const char *position_names[] = {"head", "tail", "middle", "rand"}; -static fn_type_num_t type_num_modes[] = {type_mode_one, type_mode_per_thread, - type_mode_rand}; -static fn_position_t positions[] = {position_head, position_tail, - position_middle, position_rand}; - -/* function pointers randomly picked when using rand mode */ -static fn_position_t rand_positions[] = {position_head, position_tail, - position_middle}; - -/* - * get_item -- common part of initial operation of the all benchmarks. - * It gets pointer to element on the list where object will - * be inserted/removed/moved to/from. - */ -static void -get_item(struct benchmark *bench, struct operation_info *info) -{ - auto *obj_worker = (struct obj_worker *)info->worker->priv; - obj_worker->elm = obj_bench.fn_position(obj_worker, info->index); -} - -/* - * get_move_item -- special part of initial operation of the obj_move - * benchmarks. It gets pointer to element on the list where object will be - * inserted/removed/moved to/from. - */ -static void -get_move_item(struct benchmark *bench, struct operation_info *info) -{ - auto *obj_worker = (struct obj_worker *)info->worker->priv; - obj_worker->list_move->elm = - obj_bench.fn_position(obj_worker->list_move, info->index); - - get_item(bench, info); -} - -/* - * parse_args -- parse command line string argument - */ -static int -parse_args(char *arg, int max, const char **names) -{ - int i = 0; - for (; i < max && strcmp(names[i], arg) != 0; i++) - ; - if (i == max) - fprintf(stderr, "Invalid argument\n"); - return i; -} - -/* - * obj_init_list -- special part of worker initialization, performed only if - * queue flag set false. Allocates proper number of items, and inserts proper - * part of them to the pmemobj list. - */ -static int -obj_init_list(struct worker_info *worker, size_t n_oids, size_t list_len) -{ - size_t i; - auto *obj_worker = (struct obj_worker *)worker->priv; - obj_worker->oids = - (TOID(struct item) *)calloc(n_oids, sizeof(TOID(struct item))); - if (obj_worker->oids == nullptr) { - perror("calloc"); - return -1; - } - for (i = 0; i < n_oids; i++) { - size_t type_num = obj_bench.fn_type_num(worker->index, i); - size_t size = obj_bench.alloc_sizes[i]; - auto *tmp = (PMEMoid *)&obj_worker->oids[i]; - if (pmemobj_alloc(obj_bench.pop, tmp, size, type_num, nullptr, - nullptr) != 0) - goto err_oids; - } - for (i = 0; i < list_len; i++) - POBJ_LIST_INSERT_TAIL(obj_bench.pop, &obj_worker->head, - obj_worker->oids[i], field); - return 0; -err_oids: - for (; i > 0; i--) - POBJ_FREE(&obj_worker->oids[i - 1]); - free(obj_worker->oids); - return -1; -} - -/* - * queue_init_list -- special part of worker initialization, performed only if - * queue flag set. Initiates circle queue, allocates proper number of items and - * inserts proper part of them to the queue. - */ -static int -queue_init_list(struct worker_info *worker, size_t n_items, size_t list_len) -{ - size_t i; - auto *obj_worker = (struct obj_worker *)worker->priv; - PMDK_CIRCLEQ_INIT(&obj_worker->headq); - obj_worker->items = - (struct item **)malloc(n_items * sizeof(struct item *)); - if (obj_worker->items == nullptr) { - perror("malloc"); - return -1; - } - - for (i = 0; i < n_items; i++) { - size_t size = obj_bench.alloc_sizes[i]; - obj_worker->items[i] = (struct item *)calloc(1, size); - if (obj_worker->items[i] == nullptr) { - perror("calloc"); - goto err; - } - } - - for (i = 0; i < list_len; i++) - PMDK_CIRCLEQ_INSERT_TAIL(&obj_worker->headq, - obj_worker->items[i], fieldq); - - return 0; -err: - for (; i > 0; i--) - free(obj_worker->items[i - 1]); - free(obj_worker->items); - return -1; -} - -/* - * queue_free_worker_list -- special part for the worker de-initialization when - * queue flag is true. Releases items directly from atomic list. - */ -static void -queue_free_worker_list(struct obj_worker *obj_worker) -{ - while (!PMDK_CIRCLEQ_EMPTY(&obj_worker->headq)) { - struct item *tmp = PMDK_CIRCLEQ_LAST(&obj_worker->headq); - PMDK_CIRCLEQ_REMOVE(&obj_worker->headq, tmp, fieldq); - free(tmp); - } - free(obj_worker->items); -} - -/* - * obj_free_worker_list -- special part for the worker de-initialization when - * queue flag is false. Releases items directly from atomic list. - */ -static void -obj_free_worker_list(struct obj_worker *obj_worker) -{ - while (!POBJ_LIST_EMPTY(&obj_worker->head)) { - TOID(struct item) tmp = POBJ_LIST_FIRST(&obj_worker->head); - POBJ_LIST_REMOVE_FREE(obj_bench.pop, &obj_worker->head, tmp, - field); - } - free(obj_worker->oids); -} - -/* - * obj_free_worker_items -- special part for the worker de-initialization when - * queue flag is false. Releases items used for create pmemobj list. - */ -static void -obj_free_worker_items(struct obj_worker *obj_worker) -{ - for (size_t i = 0; i < obj_worker->n_elm; i++) - POBJ_FREE(&obj_worker->oids[i]); - free(obj_worker->oids); -} - -/* - * queue_free_worker_items -- special part for the worker de-initialization - * when queue flag set. Releases used for create circle queue. - */ -static void -queue_free_worker_items(struct obj_worker *obj_worker) -{ - for (size_t i = 0; i < obj_worker->n_elm; i++) - free(obj_worker->items[i]); - free(obj_worker->items); -} - -/* - * random_positions -- allocates array and calculates random values for - * defining positions where each operation will be performed. Used only - * in POSITION_MODE_RAND - */ -static fn_position_t * -random_positions(void) -{ - auto *positions = (fn_position_t *)calloc(obj_bench.max_len, - sizeof(fn_position_t)); - if (positions == nullptr) { - perror("calloc"); - return nullptr; - } - - if (obj_bench.args->seed != 0) - srand(obj_bench.args->seed); - - size_t rmax = ARRAY_SIZE(rand_positions); - for (size_t i = 0; i < obj_bench.max_len; i++) { - size_t id = RRAND(rmax, 0); - positions[i] = rand_positions[id]; - } - - return positions; -} - -/* - * rand_values -- allocates array and if range mode calculates random - * values as allocation sizes for each object otherwise populates whole array - * with max value. Used only when range flag set. - */ -static size_t * -random_values(size_t min, size_t max, size_t n_ops, size_t min_range) -{ - auto *randoms = (size_t *)calloc(n_ops, sizeof(size_t)); - if (randoms == nullptr) { - perror("calloc"); - return nullptr; - } - for (size_t i = 0; i < n_ops; i++) - randoms[i] = max; - if (min > min_range) { - if (min > max) { - fprintf(stderr, "Invalid size\n"); - free(randoms); - return nullptr; - } - for (size_t i = 0; i < n_ops; i++) - randoms[i] = RRAND(max, min); - } - return randoms; -} -/* - * queue_insert_op -- main operations of the obj_insert benchmark when queue - * flag set to true. - */ -static int -queue_insert_op(struct operation_info *info) -{ - auto *obj_worker = (struct obj_worker *)info->worker->priv; - PMDK_CIRCLEQ_INSERT_AFTER( - &obj_worker->headq, obj_worker->elm.itemq, - obj_worker->items[info->index + obj_bench.min_len], fieldq); - return 0; -} - -/* - * obj_insert_op -- main operations of the obj_insert benchmark when queue flag - * set to false. - */ -static int -obj_insert_op(struct operation_info *info) -{ - auto *obj_worker = (struct obj_worker *)info->worker->priv; - POBJ_LIST_INSERT_AFTER( - obj_bench.pop, &obj_worker->head, obj_worker->elm.itemp, - obj_worker->oids[info->index + obj_bench.min_len], field); - return 0; -} - -/* - * queue_remove_op -- main operations of the obj_remove benchmark when queue - * flag set to true. - */ -static int -queue_remove_op(struct operation_info *info) -{ - auto *obj_worker = (struct obj_worker *)info->worker->priv; - PMDK_CIRCLEQ_REMOVE(&obj_worker->headq, obj_worker->elm.itemq, fieldq); - return 0; -} - -/* - * obj_remove_op -- main operations of the obj_remove benchmark when queue flag - * set to false. - */ -static int -obj_remove_op(struct operation_info *info) -{ - auto *obj_worker = (struct obj_worker *)info->worker->priv; - POBJ_LIST_REMOVE(obj_bench.pop, &obj_worker->head, - obj_worker->elm.itemp, field); - return 0; -} - -/* - * insert_op -- main operations of the obj_insert benchmark. - */ -static int -insert_op(struct benchmark *bench, struct operation_info *info) -{ - get_item(bench, info); - - return obj_bench.args->queue ? queue_insert_op(info) - : obj_insert_op(info); -} - -/* - * obj_insert_new_op -- main operations of the obj_insert_new benchmark. - */ -static int -obj_insert_new_op(struct benchmark *bench, struct operation_info *info) -{ - get_item(bench, info); - - auto *obj_worker = (struct obj_worker *)info->worker->priv; - PMEMoid tmp; - size_t size = obj_bench.alloc_sizes[info->index]; - size_t type_num = - obj_bench.fn_type_num(info->worker->index, info->index); - tmp = pmemobj_list_insert_new( - obj_bench.pop, offsetof(struct item, field), &obj_worker->head, - obj_worker->elm.itemp.oid, obj_worker->elm.before, size, - type_num, nullptr, nullptr); - - if (OID_IS_NULL(tmp)) { - perror("pmemobj_list_insert_new"); - return -1; - } - - return 0; -} - -/* - * remove_op -- main operations of the obj_remove benchmark. - */ -static int -remove_op(struct benchmark *bench, struct operation_info *info) -{ - get_item(bench, info); - - return obj_bench.args->queue ? queue_remove_op(info) - : obj_remove_op(info); -} - -/* - * obj_remove_free_op -- main operation of the obj_remove_free benchmark. - */ -static int -obj_remove_free_op(struct benchmark *bench, struct operation_info *info) -{ - get_item(bench, info); - - auto *obj_worker = (struct obj_worker *)info->worker->priv; - POBJ_LIST_REMOVE_FREE(obj_bench.pop, &obj_worker->head, - obj_worker->elm.itemp, field); - return 0; -} - -/* - * obj_move_op -- main operation of the obj_move benchmark. - */ -static int -obj_move_op(struct benchmark *bench, struct operation_info *info) -{ - get_move_item(bench, info); - - auto *obj_worker = (struct obj_worker *)info->worker->priv; - POBJ_LIST_MOVE_ELEMENT_BEFORE(obj_bench.pop, &obj_worker->head, - &obj_worker->list_move->head, - obj_worker->list_move->elm.itemp, - obj_worker->elm.itemp, field, field); - return 0; -} - -/* - * free_worker -- free common worker state - */ -static void -free_worker(struct obj_worker *obj_worker) -{ - if (obj_bench.position_mode == POSITION_MODE_RAND) - free(obj_worker->fn_positions); - free(obj_worker); -} - -/* - * free_worker_list -- worker de-initialization function for: obj_insert_new, - * obj_remove_free, obj_move. Requires releasing objects directly from list. - */ -static void -free_worker_list(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *obj_worker = (struct obj_worker *)worker->priv; - obj_bench.args->queue ? queue_free_worker_list(obj_worker) - : obj_free_worker_list(obj_worker); - free_worker(obj_worker); -} - -/* - * obj_free_worker_items -- worker de-initialization function of obj_insert and - * obj_remove benchmarks, where deallocation can't be performed directly on the - * list and where is possibility of using queue flag. - */ -static void -free_worker_items(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *obj_worker = (struct obj_worker *)worker->priv; - auto *obj_args = (struct obj_list_args *)args->opts; - obj_args->queue ? queue_free_worker_items(obj_worker) - : obj_free_worker_items(obj_worker); - free_worker(obj_worker); -} - -/* - * obj_move_free_worker -- special part for the worker de-initialization - * function of obj_move benchmarks. - */ -static void -obj_move_free_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *obj_worker = (struct obj_worker *)worker->priv; - while (!POBJ_LIST_EMPTY(&obj_worker->list_move->head)) - POBJ_LIST_REMOVE_FREE( - obj_bench.pop, &obj_worker->list_move->head, - POBJ_LIST_LAST(&obj_worker->list_move->head, field), - field); - - if (obj_bench.position_mode == POSITION_MODE_RAND) - free(obj_worker->list_move->fn_positions); - free(obj_worker->list_move); - free_worker_list(bench, args, worker); -} - -/* - * obj_init_worker -- common part for the worker initialization for: - * obj_insert, obj_insert_new, obj_remove obj_remove_free and obj_move. - */ -static int -obj_init_worker(struct worker_info *worker, size_t n_elm, size_t list_len) -{ - auto *obj_worker = - (struct obj_worker *)calloc(1, sizeof(struct obj_worker)); - if (obj_worker == nullptr) { - perror("calloc"); - return -1; - } - - worker->priv = obj_worker; - obj_worker->n_elm = obj_bench.max_len; - obj_worker->list_move = nullptr; - if (obj_bench.position_mode == POSITION_MODE_RAND) { - obj_worker->fn_positions = random_positions(); - if (obj_worker->fn_positions == nullptr) - goto err; - } - if (obj_bench.fn_init(worker, n_elm, list_len) != 0) - goto err_positions; - - return 0; -err_positions: - free(obj_worker->fn_positions); -err: - free(obj_worker); - return -1; -} - -/* - * obj_insert_init_worker -- worker initialization functions of the obj_insert - * benchmark. - */ -static int -obj_insert_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - return obj_init_worker(worker, obj_bench.max_len, obj_bench.min_len); -} - -/* - * obj_insert_new_init_worker -- worker initialization functions of the - * obj_insert_new benchmark. - */ -static int -obj_insert_new_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - return obj_init_worker(worker, obj_bench.min_len, obj_bench.min_len); -} - -/* - * obj_remove_init_worker -- worker initialization functions of the obj_remove - * and obj_remove_free benchmarks. - */ -static int -obj_remove_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - return obj_init_worker(worker, obj_bench.max_len, obj_bench.max_len); -} - -/* - * obj_move_init_worker -- worker initialization functions of the obj_move - * benchmark. - */ -static int -obj_move_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - if (obj_init_worker(worker, obj_bench.max_len, obj_bench.max_len) != 0) - return -1; - - auto *obj_worker = (struct obj_worker *)worker->priv; - obj_worker->list_move = - (struct obj_worker *)calloc(1, sizeof(struct obj_worker)); - if (obj_worker->list_move == nullptr) { - perror("calloc"); - goto free; - } - size_t i; - if (obj_bench.position_mode == POSITION_MODE_RAND) { - obj_worker->list_move->fn_positions = random_positions(); - if (obj_worker->list_move->fn_positions == nullptr) - goto free_list_move; - } - for (i = 0; i < obj_bench.min_len; i++) { - size_t size = obj_bench.alloc_sizes[i]; - POBJ_LIST_INSERT_NEW_TAIL(obj_bench.pop, - &obj_worker->list_move->head, field, - size, nullptr, nullptr); - if (TOID_IS_NULL(POBJ_LIST_LAST(&obj_worker->list_move->head, - field))) { - perror("pmemobj_list_insert_new"); - goto free_all; - } - } - return 0; -free_all: - for (; i > 0; i--) { - POBJ_LIST_REMOVE_FREE( - obj_bench.pop, &obj_worker->list_move->head, - POBJ_LIST_LAST(&obj_worker->list_move->head, field), - field); - } - free(obj_worker->list_move->fn_positions); -free_list_move: - free(obj_worker->list_move); -free: - free_worker_list(bench, args, worker); - return -1; -} - -/* - * obj_init - common part of the benchmark initialization for: obj_insert, - * obj_insert_new, obj_remove, obj_remove_free and obj_move used in their init - * functions. Parses command line arguments, sets variables and - * creates persistent pool. - */ -static int -obj_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - obj_bench.args = (struct obj_list_args *)args->opts; - obj_bench.min_len = obj_bench.args->list_len + 1; - obj_bench.max_len = args->n_ops_per_thread + obj_bench.min_len; - - obj_bench.fn_init = - obj_bench.args->queue ? queue_init_list : obj_init_list; - /* Decide if use random or state allocation sizes */ - size_t obj_size = args->dsize < sizeof(struct item) - ? sizeof(struct item) - : args->dsize; - size_t min_size = obj_bench.args->min_size < sizeof(struct item) - ? sizeof(struct item) - : obj_bench.args->min_size; - obj_bench.alloc_sizes = random_values( - min_size, obj_size, obj_bench.max_len, sizeof(struct item)); - if (obj_bench.alloc_sizes == nullptr) - goto free_random_types; - - /* Decide where operations will be performed */ - obj_bench.position_mode = - parse_args(obj_bench.args->position, POSITION_MODE_UNKNOWN, - position_names); - if (obj_bench.position_mode == POSITION_MODE_UNKNOWN) - goto free_all; - - obj_bench.fn_position = positions[obj_bench.position_mode]; - if (!obj_bench.args->queue) { - /* Decide what type number will be used */ - obj_bench.type_mode = - parse_args(obj_bench.args->type_num, TYPE_MODE_UNKNOWN, - type_num_names); - if (obj_bench.type_mode == TYPE_MODE_UNKNOWN) - return -1; - - obj_bench.fn_type_num = type_num_modes[obj_bench.type_mode]; - if (obj_bench.type_mode == TYPE_MODE_RAND) { - obj_bench.random_types = random_values( - 1, UINT32_MAX, obj_bench.max_len, 0); - if (obj_bench.random_types == nullptr) - return -1; - } - /* - * Multiplication by FACTOR prevents from out of memory error - * as the actual size of the allocated persistent objects - * is always larger than requested. - */ - size_t psize = - (args->n_ops_per_thread + obj_bench.min_len + 1) * - obj_size * args->n_threads * FACTOR; - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < psize) { - fprintf(stderr, "file size too large\n"); - goto free_all; - } - - psize = 0; - } else if (psize < PMEMOBJ_MIN_POOL) { - psize = PMEMOBJ_MIN_POOL; - } - - /* Create pmemobj pool. */ - if ((obj_bench.pop = pmemobj_create(args->fname, LAYOUT_NAME, - psize, args->fmode)) == - nullptr) { - perror(pmemobj_errormsg()); - goto free_all; - } - } - return 0; -free_all: - free(obj_bench.alloc_sizes); -free_random_types: - if (obj_bench.type_mode == TYPE_MODE_RAND) - free(obj_bench.random_types); - return -1; -} - -/* - * obj_exit -- common part for the exit function for: obj_insert, - * obj_insert_new, obj_remove, obj_remove_free and obj_move used in their exit - * functions. - */ -static int -obj_exit(struct benchmark *bench, struct benchmark_args *args) -{ - if (!obj_bench.args->queue) { - pmemobj_close(obj_bench.pop); - if (obj_bench.type_mode == TYPE_MODE_RAND) - free(obj_bench.random_types); - } - free(obj_bench.alloc_sizes); - return 0; -} - -/* obj_list_clo -- array defining common command line arguments. */ -static struct benchmark_clo obj_list_clo[6]; - -static struct benchmark_info obj_insert; -static struct benchmark_info obj_remove; -static struct benchmark_info obj_insert_new; -static struct benchmark_info obj_remove_free; -static struct benchmark_info obj_move; - -CONSTRUCTOR(pmem_atomic_list_constructor) -void -pmem_atomic_list_constructor(void) -{ - obj_list_clo[0].opt_short = 'T'; - obj_list_clo[0].opt_long = "type-number"; - obj_list_clo[0].descr = "Type number mode - one, per-thread, " - "rand"; - obj_list_clo[0].def = "one"; - obj_list_clo[0].off = clo_field_offset(struct obj_list_args, type_num); - obj_list_clo[0].type = CLO_TYPE_STR; - - obj_list_clo[1].opt_short = 'P'; - obj_list_clo[1].opt_long = "position"; - obj_list_clo[1].descr = "Place where operation will be " - "performed - head, tail, rand, middle"; - obj_list_clo[1].def = "middle"; - obj_list_clo[1].off = clo_field_offset(struct obj_list_args, position); - obj_list_clo[1].type = CLO_TYPE_STR; - - obj_list_clo[2].opt_short = 'l'; - obj_list_clo[2].opt_long = "list-len"; - obj_list_clo[2].type = CLO_TYPE_UINT; - obj_list_clo[2].descr = "Initial list len"; - obj_list_clo[2].off = clo_field_offset(struct obj_list_args, list_len); - obj_list_clo[2].def = "1"; - obj_list_clo[2].type_uint.size = - clo_field_size(struct obj_list_args, list_len); - obj_list_clo[2].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - obj_list_clo[2].type_uint.min = 1; - obj_list_clo[2].type_uint.max = ULONG_MAX; - - obj_list_clo[3].opt_short = 'm'; - obj_list_clo[3].opt_long = "min-size"; - obj_list_clo[3].type = CLO_TYPE_UINT; - obj_list_clo[3].descr = "Min allocation size"; - obj_list_clo[3].off = clo_field_offset(struct obj_list_args, min_size); - obj_list_clo[3].def = "0"; - obj_list_clo[3].type_uint.size = - clo_field_size(struct obj_list_args, min_size); - obj_list_clo[3].type_uint.base = CLO_INT_BASE_DEC; - obj_list_clo[3].type_uint.min = 0; - obj_list_clo[3].type_uint.max = UINT_MAX; - - obj_list_clo[4].opt_short = 's'; - obj_list_clo[4].type_uint.max = INT_MAX; - obj_list_clo[4].opt_long = "seed"; - obj_list_clo[4].type = CLO_TYPE_UINT; - obj_list_clo[4].descr = "Seed value"; - obj_list_clo[4].off = clo_field_offset(struct obj_list_args, seed); - obj_list_clo[4].def = "0"; - obj_list_clo[4].type_uint.size = - clo_field_size(struct obj_list_args, seed); - obj_list_clo[4].type_uint.base = CLO_INT_BASE_DEC; - obj_list_clo[4].type_uint.min = 0; - - /* - * nclos field in benchmark_info structures is decremented to make - * queue option available only for obj_isert, obj_remove - */ - obj_list_clo[5].opt_short = 'q'; - obj_list_clo[5].opt_long = "queue"; - obj_list_clo[5].descr = "Use circleq from queue.h instead " - "pmemobj"; - obj_list_clo[5].type = CLO_TYPE_FLAG; - obj_list_clo[5].off = clo_field_offset(struct obj_list_args, queue); - - obj_insert.name = "obj_insert"; - obj_insert.brief = "pmemobj_list_insert() benchmark"; - obj_insert.init = obj_init; - obj_insert.exit = obj_exit; - obj_insert.multithread = true; - obj_insert.multiops = true; - obj_insert.init_worker = obj_insert_init_worker; - obj_insert.free_worker = free_worker_items; - obj_insert.operation = insert_op; - obj_insert.measure_time = true; - obj_insert.clos = obj_list_clo; - obj_insert.nclos = ARRAY_SIZE(obj_list_clo); - obj_insert.opts_size = sizeof(struct obj_list_args); - obj_insert.rm_file = true; - obj_insert.allow_poolset = true; - - REGISTER_BENCHMARK(obj_insert); - - obj_remove.name = "obj_remove"; - obj_remove.brief = "pmemobj_list_remove() benchmark " - "without freeing element"; - obj_remove.init = obj_init; - obj_remove.exit = obj_exit; - obj_remove.multithread = true; - obj_remove.multiops = true; - obj_remove.init_worker = obj_remove_init_worker; - obj_remove.free_worker = free_worker_items; - obj_remove.operation = remove_op; - obj_remove.measure_time = true; - obj_remove.clos = obj_list_clo; - obj_remove.nclos = ARRAY_SIZE(obj_list_clo); - obj_remove.opts_size = sizeof(struct obj_list_args); - obj_remove.rm_file = true; - obj_remove.allow_poolset = true; - - REGISTER_BENCHMARK(obj_remove); - - obj_insert_new.name = "obj_insert_new"; - obj_insert_new.brief = "pmemobj_list_insert_new() benchmark"; - obj_insert_new.init = obj_init; - obj_insert_new.exit = obj_exit; - obj_insert_new.multithread = true; - obj_insert_new.multiops = true; - obj_insert_new.init_worker = obj_insert_new_init_worker; - obj_insert_new.free_worker = free_worker_list; - obj_insert_new.operation = obj_insert_new_op; - obj_insert_new.measure_time = true; - obj_insert_new.clos = obj_list_clo; - obj_insert_new.nclos = ARRAY_SIZE(obj_list_clo) - 1; - obj_insert_new.opts_size = sizeof(struct obj_list_args); - obj_insert_new.rm_file = true; - obj_insert_new.allow_poolset = true; - REGISTER_BENCHMARK(obj_insert_new); - - obj_remove_free.name = "obj_remove_free"; - obj_remove_free.brief = "pmemobj_list_remove() benchmark " - "with freeing element"; - obj_remove_free.init = obj_init; - obj_remove_free.exit = obj_exit; - obj_remove_free.multithread = true; - obj_remove_free.multiops = true; - obj_remove_free.init_worker = obj_remove_init_worker; - obj_remove_free.free_worker = free_worker_list; - obj_remove_free.operation = obj_remove_free_op; - obj_remove_free.measure_time = true; - obj_remove_free.clos = obj_list_clo; - obj_remove_free.nclos = ARRAY_SIZE(obj_list_clo) - 1; - obj_remove_free.opts_size = sizeof(struct obj_list_args); - obj_remove_free.rm_file = true; - obj_remove_free.allow_poolset = true; - REGISTER_BENCHMARK(obj_remove_free); - - obj_move.name = "obj_move"; - obj_move.brief = "pmemobj_list_move() benchmark"; - obj_move.init = obj_init; - obj_move.exit = obj_exit; - obj_move.multithread = true; - obj_move.multiops = true; - obj_move.init_worker = obj_move_init_worker; - obj_move.free_worker = obj_move_free_worker; - obj_move.operation = obj_move_op; - obj_move.measure_time = true; - obj_move.clos = obj_list_clo; - obj_move.nclos = ARRAY_SIZE(obj_list_clo) - 1; - obj_move.opts_size = sizeof(struct obj_list_args); - obj_move.rm_file = true; - obj_move.allow_poolset = true; - REGISTER_BENCHMARK(obj_move); -} diff --git a/src/benchmarks/pmemobj_gen.cpp b/src/benchmarks/pmemobj_gen.cpp deleted file mode 100644 index 4ac2eb8216..0000000000 --- a/src/benchmarks/pmemobj_gen.cpp +++ /dev/null @@ -1,671 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ - -/* - * pmemobj_gen.cpp -- benchmark for pmemobj_direct() - * and pmemobj_open() functions. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "libpmemobj.h" - -#define LAYOUT_NAME "benchmark" -#define FACTOR 4 -#define DIR_MODE 0700 -#define FILE_MODE 0666 -#define PART_NAME "/part" -#define MAX_DIGITS 2 - -struct pobj_bench; -struct pobj_worker; - -typedef size_t (*fn_type_num_t)(struct pobj_bench *ob, size_t worker_idx, - size_t op_idx); - -typedef size_t (*fn_size_t)(struct pobj_bench *ob, size_t idx); - -typedef size_t (*fn_num_t)(size_t idx); - -/* - * Enumeration used to determine the mode of the assigning type_number - * value to the persistent objects. - */ -enum type_mode { - TYPE_MODE_ONE, - TYPE_MODE_PER_THREAD, - TYPE_MODE_RAND, - MAX_TYPE_MODE, -}; - -/* - * pobj_args - Stores command line parsed arguments. - * - * rand_type : Use random type number for every new allocated object. - * Default, there is one type number for all objects. - * - * range : Use random allocation size. - * - * min_size : Minimum allocation size. - * - * n_objs : Number of objects allocated per thread - * - * one_pool : Use one common pool for all thread - * - * one_obj : Create and use one object per thread - * - * obj_size : Size of each allocated object - * - * n_ops : Number of operations - */ -struct pobj_args { - char *type_num; - bool range; - unsigned min_size; - size_t n_objs; - bool one_pool; - bool one_obj; - size_t obj_size; - size_t n_ops; -}; - -/* - * pobj_bench - Stores variables used in benchmark, passed within functions. - * - * pop : Pointer to the persistent pool. - * - * pa : Stores pobj_args structure. - * - * sets : Stores files names using to create pool per thread - * - * random_types : Random type numbers for persistent objects. - * - * rand_sizes : random values with allocation sizes. - * - * n_pools : Number of created pools. - * - * n_objs : Number of object created per thread. - * - * type_mode : Type_mode enum value - * - * fn_type_num : Function returning proper type number for each object. - * - * fn_size : Function returning proper size of allocation. - * - * pool : Functions returning number of thread if - * one pool per thread created or index 0 if not. - * - * obj : Function returning number of operation if flag set - * to false or index 0 if set to true. - */ -struct pobj_bench { - PMEMobjpool **pop; - struct pobj_args *args_priv; - const char **sets; - size_t *random_types; - size_t *rand_sizes; - size_t n_pools; - int type_mode; - fn_type_num_t fn_type_num; - fn_size_t fn_size; - fn_num_t pool; - fn_num_t obj; -}; - -/* - * pobj_worker - Stores variables used by one thread. - */ -struct pobj_worker { - PMEMoid *oids; -}; - -/* - * type_mode_one -- always returns 0, as in the mode TYPE_MODE_ONE - * all of the persistent objects have the same type_number value. - */ -static size_t -type_mode_one(struct pobj_bench *bench_priv, size_t worker_idx, size_t op_idx) -{ - return 0; -} - -/* - * type_mode_per_thread -- always returns worker index, as in the mode - * TYPE_MODE_PER_THREAD all persistent object allocated by the same thread - * have the same type_number value. - */ -static size_t -type_mode_per_thread(struct pobj_bench *bench_priv, size_t worker_idx, - size_t op_idx) -{ - return worker_idx; -} - -/* - * type_mode_rand -- returns the value from the random_types array assigned - * for the specific operation in a specific thread. - */ -static size_t -type_mode_rand(struct pobj_bench *bench_priv, size_t worker_idx, size_t op_idx) -{ - return bench_priv->random_types[op_idx]; -} - -/* - * range_size -- returns size of object allocation from rand_sizes array. - */ -static size_t -range_size(struct pobj_bench *bench_priv, size_t idx) -{ - return bench_priv->rand_sizes[idx]; -} - -/* - * static_size -- returns always the same size of object allocation. - */ -static size_t -static_size(struct pobj_bench *bench_priv, size_t idx) -{ - return bench_priv->args_priv->obj_size; -} - -/* - * diff_num -- returns given index - */ -static size_t -diff_num(size_t idx) -{ - return idx; -} - -/* - * one_num -- returns always the same index. - */ -static size_t -one_num(size_t idx) -{ - return 0; -} - -static fn_type_num_t type_mode_func[MAX_TYPE_MODE] = { - type_mode_one, type_mode_per_thread, type_mode_rand}; - -const char *type_mode_names[MAX_TYPE_MODE] = {"one", "per-thread", "rand"}; - -/* - * parse_type_mode -- parses command line "--type-number" argument - * and returns proper type_mode enum value. - */ -static enum type_mode -parse_type_mode(const char *arg) -{ - enum type_mode i = TYPE_MODE_ONE; - for (; i < MAX_TYPE_MODE && strcmp(arg, type_mode_names[i]) != 0; - i = (enum type_mode)(i + 1)) - ; - return i; -} - -/* - * rand_sizes -- allocates array and calculates random values as allocation - * sizes for each object. Used only when range flag set. - */ -static size_t * -rand_sizes(size_t min, size_t max, size_t n_ops) -{ - assert(n_ops != 0); - auto *rand_sizes = (size_t *)malloc(n_ops * sizeof(size_t)); - if (rand_sizes == nullptr) { - perror("malloc"); - return nullptr; - } - for (size_t i = 0; i < n_ops; i++) { - rand_sizes[i] = RRAND(max, min); - } - return rand_sizes; -} - -/* - * random_types -- allocates array and calculates random values to assign - * type_number for each object. - */ -static int -random_types(struct pobj_bench *bench_priv, struct benchmark_args *args) -{ - assert(bench_priv->args_priv->n_objs != 0); - bench_priv->random_types = (size_t *)malloc( - bench_priv->args_priv->n_objs * sizeof(size_t)); - if (bench_priv->random_types == nullptr) { - perror("malloc"); - return -1; - } - for (size_t i = 0; i < bench_priv->args_priv->n_objs; i++) - bench_priv->random_types[i] = rand() % UINT32_MAX; - return 0; -} - -/* - * pobj_init - common part of the benchmark initialization functions. - * Parses command line arguments, set variables and creates persistent pools. - */ -static int -pobj_init(struct benchmark *bench, struct benchmark_args *args) -{ - unsigned i = 0; - size_t psize; - size_t n_objs; - - assert(bench != nullptr); - assert(args != nullptr); - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - auto *bench_priv = - (struct pobj_bench *)malloc(sizeof(struct pobj_bench)); - if (bench_priv == nullptr) { - perror("malloc"); - return -1; - } - assert(args->opts != nullptr); - - bench_priv->args_priv = (struct pobj_args *)args->opts; - bench_priv->args_priv->obj_size = args->dsize; - bench_priv->args_priv->range = - bench_priv->args_priv->min_size > 0 ? true : false; - bench_priv->n_pools = - !bench_priv->args_priv->one_pool ? args->n_threads : 1; - bench_priv->pool = bench_priv->n_pools > 1 ? diff_num : one_num; - bench_priv->obj = !bench_priv->args_priv->one_obj ? diff_num : one_num; - - if ((args->is_poolset || type == TYPE_DEVDAX) && - bench_priv->n_pools > 1) { - fprintf(stderr, - "cannot use poolset nor device dax for multiple pools," - " please use -P|--one-pool option instead"); - goto free_bench_priv; - } - /* - * Multiplication by FACTOR prevents from out of memory error - * as the actual size of the allocated persistent objects - * is always larger than requested. - */ - n_objs = bench_priv->args_priv->n_objs; - if (bench_priv->n_pools == 1) - n_objs *= args->n_threads; - psize = PMEMOBJ_MIN_POOL + - n_objs * args->dsize * args->n_threads * FACTOR; - - /* assign type_number determining function */ - bench_priv->type_mode = - parse_type_mode(bench_priv->args_priv->type_num); - switch (bench_priv->type_mode) { - case MAX_TYPE_MODE: - fprintf(stderr, "unknown type mode"); - goto free_bench_priv; - case TYPE_MODE_RAND: - if (random_types(bench_priv, args)) - goto free_bench_priv; - break; - default: - bench_priv->random_types = nullptr; - } - bench_priv->fn_type_num = type_mode_func[bench_priv->type_mode]; - - /* assign size determining function */ - bench_priv->fn_size = - bench_priv->args_priv->range ? range_size : static_size; - bench_priv->rand_sizes = nullptr; - if (bench_priv->args_priv->range) { - if (bench_priv->args_priv->min_size > args->dsize) { - fprintf(stderr, "Invalid allocation size"); - goto free_random_types; - } - bench_priv->rand_sizes = - rand_sizes(bench_priv->args_priv->min_size, - bench_priv->args_priv->obj_size, - bench_priv->args_priv->n_objs); - if (bench_priv->rand_sizes == nullptr) - goto free_random_types; - } - - assert(bench_priv->n_pools > 0); - bench_priv->pop = (PMEMobjpool **)calloc(bench_priv->n_pools, - sizeof(PMEMobjpool *)); - if (bench_priv->pop == nullptr) { - perror("calloc"); - goto free_random_sizes; - } - - bench_priv->sets = (const char **)calloc(bench_priv->n_pools, - sizeof(const char *)); - if (bench_priv->sets == nullptr) { - perror("calloc"); - goto free_pop; - } - if (bench_priv->n_pools > 1) { - assert(!args->is_poolset); - if (util_file_mkdir(args->fname, DIR_MODE) != 0) { - fprintf(stderr, "cannot create directory\n"); - goto free_sets; - } - size_t path_len = (strlen(PART_NAME) + strlen(args->fname)) + - MAX_DIGITS + 1; - for (i = 0; i < bench_priv->n_pools; i++) { - bench_priv->sets[i] = - (char *)malloc(path_len * sizeof(char)); - if (bench_priv->sets[i] == nullptr) { - perror("malloc"); - goto free_sets; - } - int ret = util_snprintf((char *)bench_priv->sets[i], - path_len, "%s%s%02x", - args->fname, PART_NAME, i); - if (ret < 0) { - perror("snprintf"); - goto free_sets; - } - bench_priv->pop[i] = - pmemobj_create(bench_priv->sets[i], LAYOUT_NAME, - psize, FILE_MODE); - if (bench_priv->pop[i] == nullptr) { - perror(pmemobj_errormsg()); - goto free_sets; - } - } - } else { - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < psize) { - fprintf(stderr, "file size too large\n"); - goto free_pools; - } - psize = 0; - } - bench_priv->sets[0] = args->fname; - bench_priv->pop[0] = pmemobj_create( - bench_priv->sets[0], LAYOUT_NAME, psize, FILE_MODE); - if (bench_priv->pop[0] == nullptr) { - perror(pmemobj_errormsg()); - goto free_pools; - } - } - pmembench_set_priv(bench, bench_priv); - - return 0; -free_sets: - for (; i > 0; i--) { - pmemobj_close(bench_priv->pop[i - 1]); - free((char *)bench_priv->sets[i - 1]); - } -free_pools: - free(bench_priv->sets); -free_pop: - free(bench_priv->pop); -free_random_sizes: - free(bench_priv->rand_sizes); -free_random_types: - free(bench_priv->random_types); -free_bench_priv: - free(bench_priv); - - return -1; -} - -/* - * pobj_direct_init -- special part of pobj_direct benchmark initialization. - */ -static int -pobj_direct_init(struct benchmark *bench, struct benchmark_args *args) -{ - auto *pa = (struct pobj_args *)args->opts; - pa->n_objs = pa->one_obj ? 1 : args->n_ops_per_thread; - if (pobj_init(bench, args) != 0) - return -1; - return 0; -} - -/* - * pobj_exit -- common part for the benchmarks exit functions - */ -static int -pobj_exit(struct benchmark *bench, struct benchmark_args *args) -{ - size_t i; - auto *bench_priv = (struct pobj_bench *)pmembench_get_priv(bench); - if (bench_priv->n_pools > 1) { - for (i = 0; i < bench_priv->n_pools; i++) { - pmemobj_close(bench_priv->pop[i]); - free((char *)bench_priv->sets[i]); - } - } else { - pmemobj_close(bench_priv->pop[0]); - } - free(bench_priv->sets); - free(bench_priv->pop); - free(bench_priv->rand_sizes); - free(bench_priv->random_types); - free(bench_priv); - return 0; -} - -/* - * pobj_init_worker -- worker initialization - */ -static int -pobj_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - size_t i, idx = worker->index; - auto *bench_priv = (struct pobj_bench *)pmembench_get_priv(bench); - auto *pw = (struct pobj_worker *)calloc(1, sizeof(struct pobj_worker)); - if (pw == nullptr) { - perror("calloc"); - return -1; - } - - worker->priv = pw; - pw->oids = (PMEMoid *)calloc(bench_priv->args_priv->n_objs, - sizeof(PMEMoid)); - if (pw->oids == nullptr) { - free(pw); - perror("calloc"); - return -1; - } - - PMEMobjpool *pop = bench_priv->pop[bench_priv->pool(idx)]; - for (i = 0; i < bench_priv->args_priv->n_objs; i++) { - size_t size = bench_priv->fn_size(bench_priv, i); - size_t type = bench_priv->fn_type_num(bench_priv, idx, i); - if (pmemobj_alloc(pop, &pw->oids[i], size, type, nullptr, - nullptr) != 0) { - perror("pmemobj_alloc"); - goto out; - } - } - return 0; -out: - for (; i > 0; i--) - pmemobj_free(&pw->oids[i - 1]); - free(pw->oids); - free(pw); - return -1; -} - -/* - * pobj_direct_op -- main operations of the obj_direct benchmark. - */ -static int -pobj_direct_op(struct benchmark *bench, struct operation_info *info) -{ - auto *bench_priv = (struct pobj_bench *)pmembench_get_priv(bench); - auto *pw = (struct pobj_worker *)info->worker->priv; - size_t idx = bench_priv->obj(info->index); - /* Query an invalid uuid:off pair to invalidate the cache. */ - PMEMoid bad = {1, 1}; -#define OBJ_DIRECT_NITER 1024 - /* - * As we measure a very fast operation, we need a loop inside the - * test harness. - */ - for (int i = 0; i < OBJ_DIRECT_NITER; i++) { - if (pmemobj_direct(pw->oids[idx]) == nullptr) - return -1; - if (pmemobj_direct(bad) != nullptr) - return -1; - } - return 0; -#undef OBJ_DIRECT_NITER -} - -/* - * pobj_open_op -- main operations of the obj_open benchmark. - */ -static int -pobj_open_op(struct benchmark *bench, struct operation_info *info) -{ - auto *bench_priv = (struct pobj_bench *)pmembench_get_priv(bench); - size_t idx = bench_priv->pool(info->worker->index); - pmemobj_close(bench_priv->pop[idx]); - bench_priv->pop[idx] = pmemobj_open(bench_priv->sets[idx], LAYOUT_NAME); - if (bench_priv->pop[idx] == nullptr) - return -1; - return 0; -} - -/* - * pobj_free_worker -- worker exit function - */ -static void -pobj_free_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *pw = (struct pobj_worker *)worker->priv; - auto *bench_priv = (struct pobj_bench *)pmembench_get_priv(bench); - for (size_t i = 0; i < bench_priv->args_priv->n_objs; i++) - pmemobj_free(&pw->oids[i]); - free(pw->oids); - free(pw); -} - -static struct benchmark_info obj_open; -static struct benchmark_info obj_direct; - -/* Array defining common command line arguments. */ -static struct benchmark_clo pobj_direct_clo[4]; - -static struct benchmark_clo pobj_open_clo[3]; - -CONSTRUCTOR(pmemobj_gen_constructor) -void -pmemobj_gen_constructor(void) -{ - pobj_direct_clo[0].opt_short = 'T'; - pobj_direct_clo[0].opt_long = "type-number"; - pobj_direct_clo[0].descr = "Type number mode - one, per-thread, " - "rand"; - pobj_direct_clo[0].def = "one"; - pobj_direct_clo[0].off = clo_field_offset(struct pobj_args, type_num); - pobj_direct_clo[0].type = CLO_TYPE_STR; - pobj_direct_clo[1].opt_short = 'm'; - pobj_direct_clo[1].opt_long = "min-size"; - pobj_direct_clo[1].type = CLO_TYPE_UINT; - pobj_direct_clo[1].descr = "Minimum allocation size"; - pobj_direct_clo[1].off = clo_field_offset(struct pobj_args, min_size); - pobj_direct_clo[1].def = "0"; - pobj_direct_clo[1].type_uint.size = - clo_field_size(struct pobj_args, min_size); - pobj_direct_clo[1].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - pobj_direct_clo[1].type_uint.min = 0; - pobj_direct_clo[1].type_uint.max = UINT_MAX; - - pobj_direct_clo[2].opt_short = 'P'; - pobj_direct_clo[2].opt_long = "one-pool"; - pobj_direct_clo[2].descr = "Create one pool for all threads"; - pobj_direct_clo[2].type = CLO_TYPE_FLAG; - pobj_direct_clo[2].off = clo_field_offset(struct pobj_args, one_pool); - - pobj_direct_clo[3].opt_short = 'O'; - pobj_direct_clo[3].opt_long = "one-object"; - pobj_direct_clo[3].descr = "Use only one object per thread"; - pobj_direct_clo[3].type = CLO_TYPE_FLAG; - pobj_direct_clo[3].off = clo_field_offset(struct pobj_args, one_obj); - - pobj_open_clo[0].opt_short = 'T', - pobj_open_clo[0].opt_long = "type-number", - pobj_open_clo[0].descr = "Type number mode - one, " - "per-thread, rand", - pobj_open_clo[0].def = "one", - pobj_open_clo[0].off = clo_field_offset(struct pobj_args, type_num), - pobj_open_clo[0].type = CLO_TYPE_STR, - - pobj_open_clo[1].opt_short = 'm', - pobj_open_clo[1].opt_long = "min-size", - pobj_open_clo[1].type = CLO_TYPE_UINT, - pobj_open_clo[1].descr = "Minimum allocation size", - pobj_open_clo[1].off = clo_field_offset(struct pobj_args, min_size), - pobj_open_clo[1].def = "0", - pobj_open_clo[1].type_uint.size = - clo_field_size(struct pobj_args, min_size), - pobj_open_clo[1].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX, - pobj_open_clo[1].type_uint.min = 0, - pobj_open_clo[1].type_uint.max = UINT_MAX, - - pobj_open_clo[2].opt_short = 'o'; - pobj_open_clo[2].opt_long = "objects"; - pobj_open_clo[2].type = CLO_TYPE_UINT; - pobj_open_clo[2].descr = "Number of objects in each pool"; - pobj_open_clo[2].off = clo_field_offset(struct pobj_args, n_objs); - pobj_open_clo[2].def = "1"; - pobj_open_clo[2].type_uint.size = - clo_field_size(struct pobj_args, n_objs); - pobj_open_clo[2].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - pobj_open_clo[2].type_uint.min = 1; - pobj_open_clo[2].type_uint.max = UINT_MAX; - - obj_open.name = "obj_open"; - obj_open.brief = "pmemobj_open() benchmark"; - obj_open.init = pobj_init; - obj_open.exit = pobj_exit; - obj_open.multithread = true; - obj_open.multiops = true; - obj_open.init_worker = pobj_init_worker; - obj_open.free_worker = pobj_free_worker; - obj_open.operation = pobj_open_op; - obj_open.measure_time = true; - obj_open.clos = pobj_open_clo; - obj_open.nclos = ARRAY_SIZE(pobj_open_clo); - obj_open.opts_size = sizeof(struct pobj_args); - obj_open.rm_file = true; - obj_open.allow_poolset = true; - REGISTER_BENCHMARK(obj_open); - - obj_direct.name = "obj_direct"; - obj_direct.brief = "pmemobj_direct() benchmark"; - obj_direct.init = pobj_direct_init; - obj_direct.exit = pobj_exit; - obj_direct.multithread = true; - obj_direct.multiops = true; - obj_direct.init_worker = pobj_init_worker; - obj_direct.free_worker = pobj_free_worker; - obj_direct.operation = pobj_direct_op; - obj_direct.measure_time = true; - obj_direct.clos = pobj_direct_clo; - obj_direct.nclos = ARRAY_SIZE(pobj_direct_clo); - obj_direct.opts_size = sizeof(struct pobj_args); - obj_direct.rm_file = true; - obj_direct.allow_poolset = true; - REGISTER_BENCHMARK(obj_direct); -}; diff --git a/src/benchmarks/pmemobj_persist.cpp b/src/benchmarks/pmemobj_persist.cpp deleted file mode 100644 index 6e8a347012..0000000000 --- a/src/benchmarks/pmemobj_persist.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2020, Intel Corporation */ - -/* - * pmemobj_persist.cpp -- pmemobj persist benchmarks definition - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" -#include "util.h" - -/* - * The factor used for PMEM pool size calculation, accounts for metadata, - * fragmentation and etc. - */ -#define FACTOR 3 - -/* The minimum allocation size that pmalloc can perform */ -#define ALLOC_MIN_SIZE 64 - -/* OOB and allocation header size */ -#define OOB_HEADER_SIZE 64 - -#define CONST_B 0xFF - -/* - * prog_args -- benchmark specific command line options - */ -struct prog_args { - size_t minsize; /* minimum size for random allocation size */ - bool use_random_size; /* if set, use random size allocations */ - bool no_warmup; /* do not do warmup */ - unsigned seed; /* seed for random numbers */ -}; - -/* - * obj_bench -- benchmark context - */ -struct obj_bench { - PMEMobjpool *pop; /* persistent pool handle */ - struct prog_args *pa; /* prog_args structure */ - PMEMoid *oids; /* vector of allocated objects */ - void **ptrs; /* pointers to allocated objects */ - uint64_t nobjs; /* number of allocated objects */ - size_t obj_size; /* size of each allocated objects */ - int const_b; /* memset() value */ -}; - -/* - * init_objects -- allocate persistent objects and obtain direct pointers - */ -static int -init_objects(struct obj_bench *ob) -{ - assert(ob->nobjs != 0); - ob->oids = (PMEMoid *)malloc(ob->nobjs * sizeof(*ob->oids)); - if (!ob->oids) { - perror("malloc"); - return -1; - } - - ob->ptrs = (void **)malloc(ob->nobjs * sizeof(*ob->ptrs)); - if (!ob->ptrs) { - perror("malloc"); - goto err_malloc; - } - - for (uint64_t i = 0; i < ob->nobjs; i++) { - PMEMoid oid; - void *ptr; - if (pmemobj_alloc(ob->pop, &oid, ob->obj_size, 0, nullptr, - nullptr)) { - perror("pmemobj_alloc"); - goto err_palloc; - } - ptr = pmemobj_direct(oid); - if (!ptr) { - perror("pmemobj_direct"); - goto err_palloc; - } - ob->oids[i] = oid; - ob->ptrs[i] = ptr; - } - - return 0; - -err_palloc: - free(ob->ptrs); -err_malloc: - free(ob->oids); - return -1; -} - -/* - * do_warmup -- does the warmup by writing the whole pool area - */ -static void -do_warmup(struct obj_bench *ob) -{ - for (uint64_t i = 0; i < ob->nobjs; ++i) { - memset(ob->ptrs[i], 0, ob->obj_size); - pmemobj_persist(ob->pop, ob->ptrs[i], ob->obj_size); - } -} - -/* - * obj_persist_op -- actual benchmark operation - */ -static int -obj_persist_op(struct benchmark *bench, struct operation_info *info) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - uint64_t idx = info->worker->index * info->args->n_ops_per_thread + - info->index; - - assert(idx < ob->nobjs); - - void *ptr = ob->ptrs[idx]; - memset(ptr, ob->const_b, ob->obj_size); - pmemobj_persist(ob->pop, ptr, ob->obj_size); - - return 0; -} - -/* - * obj_persist_init -- initialization function - */ -static int -obj_persist_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - auto *pa = (struct prog_args *)args->opts; - size_t poolsize; - if (pa->minsize >= args->dsize) { - fprintf(stderr, "Wrong params - allocation size\n"); - return -1; - } - - auto *ob = (struct obj_bench *)malloc(sizeof(struct obj_bench)); - if (ob == nullptr) { - perror("malloc"); - return -1; - } - pmembench_set_priv(bench, ob); - - ob->pa = pa; - - /* initialize memset() value */ - ob->const_b = CONST_B; - - ob->nobjs = args->n_ops_per_thread * args->n_threads; - - /* Create pmemobj pool. */ - ob->obj_size = args->dsize; - if (ob->obj_size < ALLOC_MIN_SIZE) - ob->obj_size = ALLOC_MIN_SIZE; - - /* For data objects */ - poolsize = ob->nobjs * (ob->obj_size + OOB_HEADER_SIZE); - - /* multiply by FACTOR for metadata, fragmentation, etc. */ - poolsize = poolsize * FACTOR; - - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < poolsize) { - fprintf(stderr, "file size too large\n"); - goto free_ob; - } - poolsize = 0; - } else if (poolsize < PMEMOBJ_MIN_POOL) { - poolsize = PMEMOBJ_MIN_POOL; - } - - poolsize = PAGE_ALIGNED_UP_SIZE(poolsize); - - ob->pop = pmemobj_create(args->fname, nullptr, poolsize, args->fmode); - if (ob->pop == nullptr) { - fprintf(stderr, "%s\n", pmemobj_errormsg()); - goto free_ob; - } - - if (init_objects(ob)) { - goto free_pop; - } - - if (!ob->pa->no_warmup) { - do_warmup(ob); - } - - return 0; - -free_pop: - pmemobj_close(ob->pop); -free_ob: - free(ob); - return -1; -} - -/* - * obj_persist_exit -- benchmark cleanup function - */ -static int -obj_persist_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - for (uint64_t i = 0; i < ob->nobjs; ++i) { - pmemobj_free(&ob->oids[i]); - } - - pmemobj_close(ob->pop); - - free(ob->oids); - free(ob->ptrs); - free(ob); - return 0; -} - -static struct benchmark_clo obj_persist_clo[1]; - -/* Stores information about benchmark. */ -static struct benchmark_info obj_persist_info; -CONSTRUCTOR(pmemobj_persist_constructor) -void -pmemobj_persist_constructor(void) -{ - obj_persist_clo[0].opt_short = 'w'; - obj_persist_clo[0].opt_long = "no-warmup"; - obj_persist_clo[0].descr = "Don't do warmup"; - obj_persist_clo[0].def = "false"; - obj_persist_clo[0].type = CLO_TYPE_FLAG; - obj_persist_clo[0].off = clo_field_offset(struct prog_args, no_warmup); - - obj_persist_info.name = "pmemobj_persist"; - obj_persist_info.brief = "Benchmark for pmemobj_persist() " - "operation"; - obj_persist_info.init = obj_persist_init; - obj_persist_info.exit = obj_persist_exit; - obj_persist_info.multithread = true; - obj_persist_info.multiops = true; - obj_persist_info.operation = obj_persist_op; - obj_persist_info.measure_time = true; - obj_persist_info.clos = obj_persist_clo; - obj_persist_info.nclos = ARRAY_SIZE(obj_persist_clo); - obj_persist_info.opts_size = sizeof(struct prog_args); - obj_persist_info.rm_file = true; - obj_persist_info.allow_poolset = true; - REGISTER_BENCHMARK(obj_persist_info); -}; diff --git a/src/benchmarks/pmemobj_tx.cpp b/src/benchmarks/pmemobj_tx.cpp deleted file mode 100644 index 3c4ff0fbf3..0000000000 --- a/src/benchmarks/pmemobj_tx.cpp +++ /dev/null @@ -1,1230 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2024, Intel Corporation */ - -/* - * pmemobj_tx.cpp -- pmemobj_tx_alloc(), pmemobj_tx_free(), - * pmemobj_tx_realloc(), pmemobj_tx_add_range() benchmarks. - */ -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" -#include "poolset_util.hpp" - -#define LAYOUT_NAME "benchmark" -#define FACTOR 1.3f -#define ALLOC_OVERHEAD 64 -/* - * operations number is limited to prevent stack overflow during - * performing recursive functions. - */ -#define MAX_OPS 10000 - -TOID_DECLARE(struct item, 0); - -struct obj_tx_bench; -struct obj_tx_worker; - -int obj_tx_init(struct benchmark *bench, struct benchmark_args *args); -int obj_tx_exit(struct benchmark *bench, struct benchmark_args *args); - -/* - * type_num_mode -- type number mode - */ -enum type_num_mode { - NUM_MODE_ONE, - NUM_MODE_PER_THREAD, - NUM_MODE_RAND, - NUM_MODE_UNKNOWN -}; - -/* - * op_mode -- operation type - */ -enum op_mode { - OP_MODE_COMMIT, - OP_MODE_ABORT, - OP_MODE_ABORT_NESTED, - OP_MODE_ONE_OBJ, - OP_MODE_ONE_OBJ_NESTED, - OP_MODE_ONE_OBJ_RANGE, - OP_MODE_ONE_OBJ_NESTED_RANGE, - OP_MODE_ALL_OBJ, - OP_MODE_ALL_OBJ_NESTED, - OP_MODE_UNKNOWN -}; - -/* - * lib_mode -- operation type - */ -enum lib_mode { - LIB_MODE_DRAM, - LIB_MODE_OBJ_TX, - LIB_MODE_OBJ_ATOMIC, - LIB_MODE_NONE, -}; - -/* - * nesting_mode -- nesting type - */ -enum nesting_mode { - NESTING_MODE_SIM, - NESTING_MODE_TX, - NESTING_MODE_UNKNOWN, -}; - -/* - * add_range_mode -- operation type for obj_add_range benchmark - */ -enum add_range_mode { ADD_RANGE_MODE_ONE_TX, ADD_RANGE_MODE_NESTED_TX }; - -/* - * parse_mode -- parsing function type - */ -enum parse_mode { PARSE_OP_MODE, PARSE_OP_MODE_ADD_RANGE }; - -typedef size_t (*fn_type_num_t)(struct obj_tx_bench *obj_bench, - size_t worker_idx, size_t op_idx); - -typedef size_t (*fn_num_t)(size_t idx); - -typedef int (*fn_op_t)(struct obj_tx_bench *obj_bench, - struct worker_info *worker, size_t idx); - -typedef struct offset (*fn_os_off_t)(struct obj_tx_bench *obj_bench, - size_t idx); - -typedef enum op_mode (*fn_parse_t)(const char *arg); - -/* - * obj_tx_args -- stores command line parsed arguments. - */ -struct obj_tx_args { - - /* - * operation which will be performed when flag io set to false. - * modes for obj_tx_alloc, obj_tx_free and obj_tx_realloc: - * - basic - transaction will be committed - * - abort - 'external' transaction will be aborted. - * - abort-nested - all nested transactions will be - * aborted. - * - * modes for obj_tx_add_range benchmark: - * - basic - one object is added to undo log many times in - * one transaction. - * - range - fields of one object are added to undo - * log many times in one transaction. - * - all-obj - all objects are added to undo log in - * one transaction. - * - range-nested - fields of one object are added to undo - * log many times in many nested transactions. - * - one-obj-nested - one object is added to undo log many - * times in many nested transactions. - * - all-obj-nested - all objects are added to undo log in - * many separate, nested transactions. - */ - char *operation; - - /* - * type number for each persistent object. There are three modes: - * - one - all of objects have the same type number - * - per-thread - all of object allocated by the same - * thread have the same type number - * - rand - type numbers are assigned randomly for - * each persistent object - */ - char *type_num; - - /* - * define s which library will be used in main operations There are - * three modes in which benchmark can be run: - * - tx - uses PMEM transactions - * - pmem - uses PMEM without transactions - * - dram - does not use PMEM - */ - char *lib; - unsigned nested; /* number of nested transactions */ - unsigned min_size; /* minimum allocation size */ - unsigned min_rsize; /* minimum reallocation size */ - unsigned rsize; /* reallocation size */ - bool change_type; /* change type number in reallocation */ - size_t obj_size; /* size of each allocated object */ - size_t n_ops; /* number of operations */ - int parse_mode; /* type of parsing function */ -}; - -/* - * obj_tx_bench -- stores variables used in benchmark, passed within functions. - */ -static struct obj_tx_bench { - PMEMobjpool *pop; /* handle to persistent pool */ - struct obj_tx_args *obj_args; /* pointer to benchmark arguments */ - size_t *random_types; /* array to store random type numbers */ - size_t *sizes; /* array to store size of each allocation */ - size_t *resizes; /* array to store size of each reallocation */ - size_t n_objs; /* number of objects to allocate */ - int type_mode; /* type number mode */ - int op_mode; /* type of operation */ - int lib_mode; /* type of operation used in initialization */ - int lib_op; /* type of main operation */ - int lib_op_free; /* type of main operation */ - int nesting_mode; /* type of nesting in main operation */ - fn_num_t n_oid; /* returns object's number in array */ - fn_os_off_t fn_off; /* returns offset for proper operation */ - - /* - * fn_type_num gets proper function assigned, depending on the - * value of the type_mode argument, which returns proper type number for - * each persistent object. Possible functions are: - * - type_mode_one, - * - type_mode_rand. - */ - fn_type_num_t fn_type_num; - - /* - * fn_op gets proper array with functions pointer assigned, depending on - * function which is tested by benchmark. Possible arrays are: - * -alloc_op - * -free_op - * -realloc_op - */ - fn_op_t *fn_op; -} obj_bench; - -/* - * item -- TOID's structure - */ -struct item; - -/* - * obj_tx_worker - stores variables used by one thread. - */ -struct obj_tx_worker { - TOID(struct item) * oids; - char **items; - unsigned tx_level; - unsigned max_level; -}; - -/* - * offset - stores offset data used in pmemobj_tx_add_range() - */ -struct offset { - uint64_t off; - size_t size; -}; - -/* - * alloc_dram -- main operations for obj_tx_alloc benchmark in dram mode - */ -static int -alloc_dram(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - obj_worker->items[idx] = (char *)malloc(obj_bench->sizes[idx]); - if (obj_worker->items[idx] == nullptr) { - perror("malloc"); - return -1; - } - return 0; -} - -/* - * alloc_pmem -- main operations for obj_tx_alloc benchmark in pmem mode - */ -static int -alloc_pmem(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - size_t type_num = obj_bench->fn_type_num(obj_bench, worker->index, idx); - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - if (pmemobj_alloc(obj_bench->pop, &obj_worker->oids[idx].oid, - obj_bench->sizes[idx], type_num, nullptr, - nullptr) != 0) { - perror("pmemobj_alloc"); - return -1; - } - return 0; -} - -/* - * alloc_tx -- main operations for obj_tx_alloc benchmark in tx mode - */ -static int -alloc_tx(struct obj_tx_bench *obj_bench, struct worker_info *worker, size_t idx) -{ - size_t type_num = obj_bench->fn_type_num(obj_bench, worker->index, idx); - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - obj_worker->oids[idx].oid = pmemobj_tx_xalloc( - obj_bench->sizes[idx], type_num, POBJ_XALLOC_NO_FLUSH); - if (OID_IS_NULL(obj_worker->oids[idx].oid)) { - perror("pmemobj_tx_alloc"); - return -1; - } - return 0; -} - -/* - * free_dram -- main operations for obj_tx_free benchmark in dram mode - */ -static int -free_dram(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - free(obj_worker->items[idx]); - return 0; -} - -/* - * free_pmem -- main operations for obj_tx_free benchmark in pmem mode - */ -static int -free_pmem(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - POBJ_FREE(&obj_worker->oids[idx]); - return 0; -} - -/* - * free_tx -- main operations for obj_tx_free benchmark in tx mode - */ -static int -free_tx(struct obj_tx_bench *obj_bench, struct worker_info *worker, size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - TX_FREE(obj_worker->oids[idx]); - return 0; -} - -/* - * no_free -- exit operation for benchmarks obj_tx_alloc and obj_tx_free - * if there is no need to free memory - */ -static int -no_free(struct obj_tx_bench *obj_bench, struct worker_info *worker, size_t idx) -{ - return 0; -} - -/* - * realloc_dram -- main operations for obj_tx_realloc benchmark in dram mode - */ -static int -realloc_dram(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - auto *tmp = (char *)realloc(obj_worker->items[idx], - obj_bench->resizes[idx]); - if (tmp == nullptr) { - perror("realloc"); - return -1; - } - obj_worker->items[idx] = tmp; - return 0; -} - -/* - * realloc_pmem -- main operations for obj_tx_realloc benchmark in pmem mode - */ -static int -realloc_pmem(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - size_t type_num = obj_bench->fn_type_num(obj_bench, worker->index, idx); - if (obj_bench->obj_args->change_type) - type_num++; - if (pmemobj_realloc(obj_bench->pop, &obj_worker->oids[idx].oid, - obj_bench->resizes[idx], type_num) != 0) { - perror("pmemobj_realloc"); - return -1; - } - return 0; -} - -/* - * realloc_tx -- main operations for obj_tx_realloc benchmark in tx mode - */ -static int -realloc_tx(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - size_t type_num = obj_bench->fn_type_num(obj_bench, worker->index, idx); - if (obj_bench->obj_args->change_type) - type_num++; - PMEMoid oid = pmemobj_tx_realloc(obj_worker->oids[idx].oid, - obj_bench->sizes[idx], type_num); - if (OID_IS_NULL(oid)) { - perror("pmemobj_tx_realloc"); - return -1; - } - - /* - * If OP_MODE_ABORT is set, this TX will get aborted, meaning that the - * object allocated as part of the outer transaction will be freed once - * this operation finishes. - * To avoid a potential use-after-free, we either have to snapshot the - * oid pointer or skip this assignment when we know it will abort. - * For performance reason, this code does the latter. - */ - if (obj_bench->op_mode != OP_MODE_ABORT) - obj_worker->oids[idx].oid = oid; - - return 0; -} - -/* - * add_range_nested_tx -- main operations of the obj_tx_add_range with nesting. - */ -static int -add_range_nested_tx(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - int ret = 0; - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - TX_BEGIN(obj_bench->pop) - { - if (obj_bench->obj_args->n_ops != obj_worker->tx_level) { - size_t n_oid = obj_bench->n_oid(obj_worker->tx_level); - struct offset offset = obj_bench->fn_off( - obj_bench, obj_worker->tx_level); - pmemobj_tx_add_range(obj_worker->oids[n_oid].oid, - offset.off, offset.size); - obj_worker->tx_level++; - ret = add_range_nested_tx(obj_bench, worker, idx); - } - } - TX_ONABORT - { - fprintf(stderr, "transaction failed\n"); - ret = -1; - } - TX_END - return ret; -} - -/* - * add_range_tx -- main operations of the obj_tx_add_range without nesting. - */ -static int -add_range_tx(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - int ret = 0; - size_t i = 0; - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - TX_BEGIN(obj_bench->pop) - { - for (i = 0; i < obj_bench->obj_args->n_ops; i++) { - size_t n_oid = obj_bench->n_oid(i); - struct offset offset = obj_bench->fn_off(obj_bench, i); - ret = pmemobj_tx_add_range(obj_worker->oids[n_oid].oid, - offset.off, offset.size); - } - } - TX_ONABORT - { - fprintf(stderr, "transaction failed\n"); - ret = -1; - } - TX_END - return ret; -} - -/* - * obj_op_sim -- main function for benchmarks which simulates nested - * transactions on dram or pmemobj atomic API by calling function recursively. - */ -static int -obj_op_sim(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - int ret = 0; - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - if (obj_worker->max_level == obj_worker->tx_level) { - ret = obj_bench->fn_op[obj_bench->lib_op](obj_bench, worker, - idx); - } else { - obj_worker->tx_level++; - ret = obj_op_sim(obj_bench, worker, idx); - } - return ret; -} - -/* - * obj_op_tx -- main recursive function for transactional benchmarks - */ -static int -obj_op_tx(struct obj_tx_bench *obj_bench, struct worker_info *worker, - size_t idx) -{ - volatile int ret = 0; - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - TX_BEGIN(obj_bench->pop) - { - if (obj_worker->max_level == obj_worker->tx_level) { - ret = obj_bench->fn_op[obj_bench->lib_op](obj_bench, - worker, idx); - if (obj_bench->op_mode == OP_MODE_ABORT_NESTED) - pmemobj_tx_abort(-1); - } else { - obj_worker->tx_level++; - ret = obj_op_tx(obj_bench, worker, idx); - if (--obj_worker->tx_level == 0 && - obj_bench->op_mode == OP_MODE_ABORT) - pmemobj_tx_abort(-1); - } - } - TX_ONABORT - { - if (obj_bench->op_mode != OP_MODE_ABORT && - obj_bench->op_mode != OP_MODE_ABORT_NESTED) { - fprintf(stderr, "transaction failed\n"); - ret = -1; - } - } - TX_END - return ret; -} - -/* - * type_mode_one -- always returns 0, as in the mode NUM_MODE_ONE - * all of the persistent objects have the same type_number value. - */ -static size_t -type_mode_one(struct obj_tx_bench *obj_bench, size_t worker_idx, size_t op_idx) -{ - return 0; -} - -/* - * type_mode_per_thread -- always returns worker index to all of the persistent - * object allocated by the same thread have the same type number. - */ -static size_t -type_mode_per_thread(struct obj_tx_bench *obj_bench, size_t worker_idx, - size_t op_idx) -{ - return worker_idx; -} - -/* - * type_mode_rand -- returns the value from the random_types array assigned - * for the specific operation in a specific thread. - */ -static size_t -type_mode_rand(struct obj_tx_bench *obj_bench, size_t worker_idx, size_t op_idx) -{ - return obj_bench->random_types[op_idx]; -} - -/* - * parse_op_mode_add_range -- parses command line "--operation" argument - * and returns proper op_mode enum value for obj_tx_add_range. - */ -static enum op_mode -parse_op_mode_add_range(const char *arg) -{ - if (strcmp(arg, "basic") == 0) - return OP_MODE_ONE_OBJ; - else if (strcmp(arg, "one-obj-nested") == 0) - return OP_MODE_ONE_OBJ_NESTED; - else if (strcmp(arg, "range") == 0) - return OP_MODE_ONE_OBJ_RANGE; - else if (strcmp(arg, "range-nested") == 0) - return OP_MODE_ONE_OBJ_NESTED_RANGE; - else if (strcmp(arg, "all-obj") == 0) - return OP_MODE_ALL_OBJ; - else if (strcmp(arg, "all-obj-nested") == 0) - return OP_MODE_ALL_OBJ_NESTED; - else - return OP_MODE_UNKNOWN; -} - -/* - * parse_op_mode -- parses command line "--operation" argument - * and returns proper op_mode enum value. - */ -static enum op_mode -parse_op_mode(const char *arg) -{ - if (strcmp(arg, "basic") == 0) - return OP_MODE_COMMIT; - else if (strcmp(arg, "abort") == 0) - return OP_MODE_ABORT; - else if (strcmp(arg, "abort-nested") == 0) - return OP_MODE_ABORT_NESTED; - else - return OP_MODE_UNKNOWN; -} - -static fn_op_t alloc_op[] = {alloc_dram, alloc_tx, alloc_pmem}; - -static fn_op_t free_op[] = {free_dram, free_tx, free_pmem, no_free}; - -static fn_op_t realloc_op[] = {realloc_dram, realloc_tx, realloc_pmem}; - -static fn_op_t add_range_op[] = {add_range_tx, add_range_nested_tx}; - -static fn_parse_t parse_op[] = {parse_op_mode, parse_op_mode_add_range}; - -static fn_op_t nestings[] = {obj_op_sim, obj_op_tx}; - -/* - * parse_type_num_mode -- converts string to type_num_mode enum - */ -static enum type_num_mode -parse_type_num_mode(const char *arg) -{ - if (strcmp(arg, "one") == 0) - return NUM_MODE_ONE; - else if (strcmp(arg, "per-thread") == 0) - return NUM_MODE_PER_THREAD; - else if (strcmp(arg, "rand") == 0) - return NUM_MODE_RAND; - fprintf(stderr, "unknown type number\n"); - return NUM_MODE_UNKNOWN; -} - -/* - * parse_lib_mode -- converts string to type_num_mode enum - */ -static enum lib_mode -parse_lib_mode(const char *arg) -{ - if (strcmp(arg, "dram") == 0) - return LIB_MODE_DRAM; - else if (strcmp(arg, "pmem") == 0) - return LIB_MODE_OBJ_ATOMIC; - else if (strcmp(arg, "tx") == 0) - return LIB_MODE_OBJ_TX; - fprintf(stderr, "unknown lib mode\n"); - return LIB_MODE_NONE; -} - -static fn_type_num_t type_num_fn[] = {type_mode_one, type_mode_per_thread, - type_mode_rand, nullptr}; - -/* - * one_num -- returns always the same number. - */ -static size_t -one_num(size_t idx) -{ - return 0; -} - -/* - * diff_num -- returns number given as argument. - */ -static size_t -diff_num(size_t idx) -{ - return idx; -} - -/* - * off_entire -- returns zero offset. - */ -static struct offset -off_entire(struct obj_tx_bench *obj_bench, size_t idx) -{ - struct offset offset; - offset.off = 0; - offset.size = obj_bench->sizes[obj_bench->n_oid(idx)]; - return offset; -} - -/* - * off_range -- returns offset for range in object. - */ -static struct offset -off_range(struct obj_tx_bench *obj_bench, size_t idx) -{ - struct offset offset; - offset.size = obj_bench->sizes[0] / obj_bench->obj_args->n_ops; - offset.off = offset.size * idx; - return offset; -} - -/* - * rand_values -- allocates array and if range mode calculates random - * values as allocation sizes for each object otherwise populates whole array - * with max value. Used only when range flag set. - */ -static size_t * -rand_values(size_t min, size_t max, size_t n_ops) -{ - size_t size = max - min; - auto *sizes = (size_t *)calloc(n_ops, sizeof(size_t)); - if (sizes == nullptr) { - perror("calloc"); - return nullptr; - } - for (size_t i = 0; i < n_ops; i++) - sizes[i] = max; - if (min) { - if (min > max) { - fprintf(stderr, "Invalid size\n"); - free(sizes); - return nullptr; - } - for (size_t i = 0; i < n_ops; i++) - sizes[i] = (rand() % size) + min; - } - return sizes; -} - -/* - * obj_tx_add_range_op -- main operations of the obj_tx_add_range benchmark. - */ -static int -obj_tx_add_range_op(struct benchmark *bench, struct operation_info *info) -{ - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - auto *obj_worker = (struct obj_tx_worker *)info->worker->priv; - if (add_range_op[obj_bench->lib_op](obj_bench, info->worker, - info->index) != 0) - return -1; - obj_worker->tx_level = 0; - return 0; -} - -/* - * obj_tx_op -- main operation for obj_tx_alloc(), obj_tx_free() and - * obj_tx_realloc() benchmarks. - */ -static int -obj_tx_op(struct benchmark *bench, struct operation_info *info) -{ - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - auto *obj_worker = (struct obj_tx_worker *)info->worker->priv; - int ret = nestings[obj_bench->nesting_mode](obj_bench, info->worker, - info->index); - obj_worker->tx_level = 0; - return ret; -} - -/* - * obj_tx_init_worker -- common part for the worker initialization functions - * for transactional benchmarks. - */ -static int -obj_tx_init_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - auto *obj_worker = - (struct obj_tx_worker *)calloc(1, sizeof(struct obj_tx_worker)); - if (obj_worker == nullptr) { - perror("calloc"); - return -1; - } - worker->priv = obj_worker; - obj_worker->tx_level = 0; - obj_worker->max_level = obj_bench->obj_args->nested; - if (obj_bench->lib_mode != LIB_MODE_DRAM) - obj_worker->oids = (TOID(struct item) *)calloc( - obj_bench->n_objs, sizeof(TOID(struct item))); - else - obj_worker->items = - (char **)calloc(obj_bench->n_objs, sizeof(char *)); - if (obj_worker->oids == nullptr && obj_worker->items == nullptr) { - free(obj_worker); - perror("calloc"); - return -1; - } - return 0; -} - -/* - * obj_tx_free_init_worker_alloc_obj -- special part for the worker - * initialization function for benchmarks which needs allocated objects - * before operation. - */ -static int -obj_tx_init_worker_alloc_obj(struct benchmark *bench, - struct benchmark_args *args, - struct worker_info *worker) -{ - unsigned i; - if (obj_tx_init_worker(bench, args, worker) != 0) - return -1; - - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - for (i = 0; i < obj_bench->n_objs; i++) { - if (alloc_op[obj_bench->lib_mode](obj_bench, worker, i) != 0) - goto out; - } - return 0; -out: - for (; i > 0; i--) - free_op[obj_bench->lib_mode](obj_bench, worker, i - 1); - if (obj_bench->lib_mode == LIB_MODE_DRAM) - free(obj_worker->items); - else - free(obj_worker->oids); - free(obj_worker); - return -1; -} - -/* - * obj_tx_exit_worker -- common part for the worker de-initialization. - */ -static void -obj_tx_exit_worker(struct benchmark *bench, struct benchmark_args *args, - struct worker_info *worker) -{ - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - auto *obj_worker = (struct obj_tx_worker *)worker->priv; - for (unsigned i = 0; i < obj_bench->n_objs; i++) - free_op[obj_bench->lib_op_free](obj_bench, worker, i); - - if (obj_bench->lib_mode == LIB_MODE_DRAM) - free(obj_worker->items); - else - free(obj_worker->oids); - free(obj_worker); -} - -/* - * obj_tx_add_range_init -- specific part of the obj_tx_add_range - * benchmark initialization. - */ -static int -obj_tx_add_range_init(struct benchmark *bench, struct benchmark_args *args) -{ - auto *obj_args = (struct obj_tx_args *)args->opts; - obj_args->parse_mode = PARSE_OP_MODE_ADD_RANGE; - if (args->n_ops_per_thread > MAX_OPS) - args->n_ops_per_thread = MAX_OPS; - if (obj_tx_init(bench, args) != 0) - return -1; - - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - - obj_bench->n_oid = diff_num; - if (obj_bench->op_mode < OP_MODE_ALL_OBJ) { - obj_bench->n_oid = one_num; - obj_bench->n_objs = 1; - } - obj_bench->fn_off = off_entire; - if (obj_bench->op_mode == OP_MODE_ONE_OBJ_RANGE || - obj_bench->op_mode == OP_MODE_ONE_OBJ_NESTED_RANGE) { - obj_bench->fn_off = off_range; - if (args->n_ops_per_thread > args->dsize) - args->dsize = args->n_ops_per_thread; - - obj_bench->sizes[0] = args->dsize; - } - obj_bench->lib_op = (obj_bench->op_mode == OP_MODE_ONE_OBJ || - obj_bench->op_mode == OP_MODE_ALL_OBJ) - ? ADD_RANGE_MODE_ONE_TX - : ADD_RANGE_MODE_NESTED_TX; - return 0; -} - -/* - * obj_tx_free_init -- specific part of the obj_tx_free initialization. - */ -static int -obj_tx_free_init(struct benchmark *bench, struct benchmark_args *args) -{ - if (obj_tx_init(bench, args) != 0) - return -1; - - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - obj_bench->fn_op = free_op; - - /* - * Generally all objects which were allocated during worker - * initialization are released in main operation so there is no need to - * free them in exit operation. Only exception is situation where - * transaction (inside which object is releasing) is aborted. - * Then object is not released so there there is necessary to free it - * in exit operation. - */ - if (!(obj_bench->lib_op == LIB_MODE_OBJ_TX && - obj_bench->op_mode != OP_MODE_COMMIT)) - obj_bench->lib_op_free = LIB_MODE_NONE; - return 0; -} - -/* - * obj_tx_alloc_init -- specific part of the obj_tx_alloc initialization. - */ -static int -obj_tx_alloc_init(struct benchmark *bench, struct benchmark_args *args) -{ - if (obj_tx_init(bench, args) != 0) - return -1; - - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - obj_bench->fn_op = alloc_op; - - /* - * Generally all objects which will be allocated during main operation - * need to be released. Only exception is situation where transaction - * (inside which object is allocating) is aborted. Then object is not - * allocated so there is no need to free it in exit operation. - */ - if (obj_bench->lib_op == LIB_MODE_OBJ_TX && - obj_bench->op_mode != OP_MODE_COMMIT) - obj_bench->lib_op_free = LIB_MODE_NONE; - return 0; -} - -/* - * obj_tx_realloc_init -- specific part of the obj_tx_realloc initialization. - */ -static int -obj_tx_realloc_init(struct benchmark *bench, struct benchmark_args *args) -{ - if (obj_tx_init(bench, args) != 0) - return -1; - - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - obj_bench->resizes = - rand_values(obj_bench->obj_args->min_rsize, - obj_bench->obj_args->rsize, args->n_ops_per_thread); - if (obj_bench->resizes == nullptr) { - obj_tx_exit(bench, args); - return -1; - } - obj_bench->fn_op = realloc_op; - return 0; -} - -/* - * obj_tx_init -- common part of the benchmark initialization for transactional - * benchmarks in their init functions. Parses command line arguments, set - * variables and creates persistent pool. - */ -int -obj_tx_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - char path[PATH_MAX]; - if (util_safe_strcpy(path, args->fname, sizeof(path)) != 0) - return -1; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - pmembench_set_priv(bench, &obj_bench); - - obj_bench.obj_args = (struct obj_tx_args *)args->opts; - obj_bench.obj_args->obj_size = args->dsize; - obj_bench.obj_args->n_ops = args->n_ops_per_thread; - obj_bench.n_objs = args->n_ops_per_thread; - - obj_bench.lib_op = obj_bench.obj_args->lib != nullptr - ? parse_lib_mode(obj_bench.obj_args->lib) - : LIB_MODE_OBJ_ATOMIC; - - if (obj_bench.lib_op == LIB_MODE_NONE) - return -1; - - obj_bench.lib_mode = obj_bench.lib_op == LIB_MODE_DRAM - ? LIB_MODE_DRAM - : LIB_MODE_OBJ_ATOMIC; - - obj_bench.lib_op_free = obj_bench.lib_mode; - - obj_bench.nesting_mode = obj_bench.lib_op == LIB_MODE_OBJ_TX - ? NESTING_MODE_TX - : NESTING_MODE_SIM; - - /* - * Multiplication by FACTOR prevents from out of memory error - * as the actual size of the allocated persistent objects - * is always larger than requested. - */ - size_t dsize = obj_bench.obj_args->rsize > args->dsize - ? obj_bench.obj_args->rsize - : args->dsize; - size_t psize = args->n_ops_per_thread * (dsize + ALLOC_OVERHEAD) * - args->n_threads; - - psize += PMEMOBJ_MIN_POOL; - psize = (size_t)(psize * FACTOR); - - /* - * When adding all allocated objects to undo log there is necessary - * to prepare larger pool to prevent out of memory error. - */ - if (obj_bench.op_mode == OP_MODE_ALL_OBJ || - obj_bench.op_mode == OP_MODE_ALL_OBJ_NESTED) - psize *= 2; - - obj_bench.op_mode = parse_op[obj_bench.obj_args->parse_mode]( - obj_bench.obj_args->operation); - if (obj_bench.op_mode == OP_MODE_UNKNOWN) { - fprintf(stderr, "operation mode unknown\n"); - return -1; - } - - obj_bench.type_mode = parse_type_num_mode(obj_bench.obj_args->type_num); - if (obj_bench.type_mode == NUM_MODE_UNKNOWN) - return -1; - - obj_bench.fn_type_num = type_num_fn[obj_bench.type_mode]; - if (obj_bench.type_mode == NUM_MODE_RAND) { - obj_bench.random_types = - rand_values(1, UINT32_MAX, args->n_ops_per_thread); - if (obj_bench.random_types == nullptr) - return -1; - } - obj_bench.sizes = rand_values(obj_bench.obj_args->min_size, - obj_bench.obj_args->obj_size, - args->n_ops_per_thread); - if (obj_bench.sizes == nullptr) - goto free_random_types; - - if (obj_bench.lib_mode == LIB_MODE_DRAM) - return 0; - - /* Create pmemobj pool. */ - if (args->is_poolset || type == TYPE_DEVDAX) { - if (args->fsize < psize) { - fprintf(stderr, "file size too large\n"); - goto free_all; - } - - psize = 0; - } else if (args->is_dynamic_poolset) { - int ret = dynamic_poolset_create(args->fname, psize); - if (ret == -1) - goto free_all; - - if (util_safe_strcpy(path, POOLSET_PATH, sizeof(path)) != 0) - goto free_all; - - psize = 0; - } - - obj_bench.pop = pmemobj_create(path, LAYOUT_NAME, psize, args->fmode); - if (obj_bench.pop == nullptr) { - perror("pmemobj_create"); - goto free_all; - } - - return 0; -free_all: - free(obj_bench.sizes); -free_random_types: - if (obj_bench.type_mode == NUM_MODE_RAND) - free(obj_bench.random_types); - return -1; -} - -/* - * obj_tx_exit -- common part for the exit function of the transactional - * benchmarks in their exit functions. - */ -int -obj_tx_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - if (obj_bench->lib_mode != LIB_MODE_DRAM) - pmemobj_close(obj_bench->pop); - - free(obj_bench->sizes); - if (obj_bench->type_mode == NUM_MODE_RAND) - free(obj_bench->random_types); - return 0; -} - -/* - * obj_tx_realloc_exit -- common part for the exit function of the transactional - * benchmarks in their exit functions. - */ -static int -obj_tx_realloc_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *obj_bench = (struct obj_tx_bench *)pmembench_get_priv(bench); - free(obj_bench->resizes); - return obj_tx_exit(bench, args); -} - -/* Array defining common command line arguments. */ -static struct benchmark_clo obj_tx_clo[8]; - -static struct benchmark_info obj_tx_alloc; -static struct benchmark_info obj_tx_free; -static struct benchmark_info obj_tx_realloc; -static struct benchmark_info obj_tx_add_range; - -CONSTRUCTOR(pmemobj_tx_constructor) -void -pmemobj_tx_constructor(void) -{ - obj_tx_clo[0].opt_short = 'T'; - obj_tx_clo[0].opt_long = "type-number"; - obj_tx_clo[0].descr = "Type number - one, rand, per-thread"; - obj_tx_clo[0].def = "one"; - obj_tx_clo[0].type = CLO_TYPE_STR; - obj_tx_clo[0].off = clo_field_offset(struct obj_tx_args, type_num); - - obj_tx_clo[1].opt_short = 'O'; - obj_tx_clo[1].opt_long = "operation"; - obj_tx_clo[1].descr = "Type of operation"; - obj_tx_clo[1].def = "basic"; - obj_tx_clo[1].off = clo_field_offset(struct obj_tx_args, operation); - obj_tx_clo[1].type = CLO_TYPE_STR; - - obj_tx_clo[2].opt_short = 'm'; - obj_tx_clo[2].opt_long = "min-size"; - obj_tx_clo[2].type = CLO_TYPE_UINT; - obj_tx_clo[2].descr = "Minimum allocation size"; - obj_tx_clo[2].off = clo_field_offset(struct obj_tx_args, min_size); - obj_tx_clo[2].def = "0"; - obj_tx_clo[2].type_uint.size = - clo_field_size(struct obj_tx_args, min_size); - obj_tx_clo[2].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - obj_tx_clo[2].type_uint.min = 0; - obj_tx_clo[2].type_uint.max = UINT_MAX; - /* - * nclos field in benchmark_info structures is decremented to make this - * options available only for obj_tx_alloc, obj_tx_free and - * obj_tx_realloc benchmarks. - */ - obj_tx_clo[3].opt_short = 'L'; - obj_tx_clo[3].opt_long = "lib"; - obj_tx_clo[3].descr = "Type of library"; - obj_tx_clo[3].def = "tx"; - obj_tx_clo[3].off = clo_field_offset(struct obj_tx_args, lib); - obj_tx_clo[3].type = CLO_TYPE_STR; - - obj_tx_clo[4].opt_short = 'N'; - obj_tx_clo[4].opt_long = "nestings"; - obj_tx_clo[4].type = CLO_TYPE_UINT; - obj_tx_clo[4].descr = "Number of nested transactions"; - obj_tx_clo[4].off = clo_field_offset(struct obj_tx_args, nested); - obj_tx_clo[4].def = "0"; - obj_tx_clo[4].type_uint.size = - clo_field_size(struct obj_tx_args, nested); - obj_tx_clo[4].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - obj_tx_clo[4].type_uint.min = 0; - obj_tx_clo[4].type_uint.max = MAX_OPS; - - obj_tx_clo[5].opt_short = 'r'; - obj_tx_clo[5].opt_long = "min-rsize"; - obj_tx_clo[5].type = CLO_TYPE_UINT; - obj_tx_clo[5].descr = "Minimum reallocation size"; - obj_tx_clo[5].off = clo_field_offset(struct obj_tx_args, min_rsize); - obj_tx_clo[5].def = "0"; - obj_tx_clo[5].type_uint.size = - clo_field_size(struct obj_tx_args, min_rsize); - obj_tx_clo[5].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - obj_tx_clo[5].type_uint.min = 0; - obj_tx_clo[5].type_uint.max = UINT_MAX; - - obj_tx_clo[6].opt_short = 'R'; - obj_tx_clo[6].opt_long = "realloc-size"; - obj_tx_clo[6].type = CLO_TYPE_UINT; - obj_tx_clo[6].descr = "Reallocation size"; - obj_tx_clo[6].off = clo_field_offset(struct obj_tx_args, rsize); - obj_tx_clo[6].def = "1"; - obj_tx_clo[6].type_uint.size = - clo_field_size(struct obj_tx_args, rsize); - obj_tx_clo[6].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX; - obj_tx_clo[6].type_uint.min = 1; - obj_tx_clo[6].type_uint.max = ULONG_MAX; - - obj_tx_clo[7].opt_short = 'c'; - obj_tx_clo[7].opt_long = "changed-type"; - obj_tx_clo[7].descr = "Use another type number in " - "reallocation than in allocation"; - obj_tx_clo[7].type = CLO_TYPE_FLAG; - obj_tx_clo[7].off = clo_field_offset(struct obj_tx_args, change_type); - - obj_tx_alloc.name = "obj_tx_alloc"; - obj_tx_alloc.brief = "pmemobj_tx_alloc() benchmark"; - obj_tx_alloc.init = obj_tx_alloc_init; - obj_tx_alloc.exit = obj_tx_exit; - obj_tx_alloc.multithread = true; - obj_tx_alloc.multiops = true; - obj_tx_alloc.init_worker = obj_tx_init_worker; - obj_tx_alloc.free_worker = obj_tx_exit_worker; - obj_tx_alloc.operation = obj_tx_op; - obj_tx_alloc.measure_time = true; - obj_tx_alloc.clos = obj_tx_clo; - obj_tx_alloc.nclos = ARRAY_SIZE(obj_tx_clo) - 3; - obj_tx_alloc.opts_size = sizeof(struct obj_tx_args); - obj_tx_alloc.rm_file = true; - obj_tx_alloc.allow_poolset = true; - REGISTER_BENCHMARK(obj_tx_alloc); - - obj_tx_free.name = "obj_tx_free"; - obj_tx_free.brief = "pmemobj_tx_free() benchmark"; - obj_tx_free.init = obj_tx_free_init; - obj_tx_free.exit = obj_tx_exit; - obj_tx_free.multithread = true; - obj_tx_free.multiops = true; - obj_tx_free.init_worker = obj_tx_init_worker_alloc_obj; - obj_tx_free.free_worker = obj_tx_exit_worker; - obj_tx_free.operation = obj_tx_op; - obj_tx_free.measure_time = true; - obj_tx_free.clos = obj_tx_clo; - obj_tx_free.nclos = ARRAY_SIZE(obj_tx_clo) - 3; - obj_tx_free.opts_size = sizeof(struct obj_tx_args); - obj_tx_free.rm_file = true; - obj_tx_free.allow_poolset = true; - REGISTER_BENCHMARK(obj_tx_free); - - obj_tx_realloc.name = "obj_tx_realloc"; - obj_tx_realloc.brief = "pmemobj_tx_realloc() benchmark"; - obj_tx_realloc.init = obj_tx_realloc_init; - obj_tx_realloc.exit = obj_tx_realloc_exit; - obj_tx_realloc.multithread = true; - obj_tx_realloc.multiops = true; - obj_tx_realloc.init_worker = obj_tx_init_worker_alloc_obj; - obj_tx_realloc.free_worker = obj_tx_exit_worker; - obj_tx_realloc.operation = obj_tx_op; - obj_tx_realloc.measure_time = true; - obj_tx_realloc.clos = obj_tx_clo; - obj_tx_realloc.nclos = ARRAY_SIZE(obj_tx_clo); - obj_tx_realloc.opts_size = sizeof(struct obj_tx_args); - obj_tx_realloc.rm_file = true; - obj_tx_realloc.allow_poolset = true; - REGISTER_BENCHMARK(obj_tx_realloc); - - obj_tx_add_range.name = "obj_tx_add_range"; - obj_tx_add_range.brief = "pmemobj_tx_add_range() benchmark"; - obj_tx_add_range.init = obj_tx_add_range_init; - obj_tx_add_range.exit = obj_tx_exit; - obj_tx_add_range.multithread = true; - obj_tx_add_range.multiops = false; - obj_tx_add_range.init_worker = obj_tx_init_worker_alloc_obj; - obj_tx_add_range.free_worker = obj_tx_exit_worker; - obj_tx_add_range.operation = obj_tx_add_range_op; - obj_tx_add_range.measure_time = true; - obj_tx_add_range.clos = obj_tx_clo; - obj_tx_add_range.nclos = ARRAY_SIZE(obj_tx_clo) - 5; - obj_tx_add_range.opts_size = sizeof(struct obj_tx_args); - obj_tx_add_range.rm_file = true; - obj_tx_add_range.allow_poolset = true; - REGISTER_BENCHMARK(obj_tx_add_range); -} diff --git a/src/benchmarks/pmemobj_tx_add_range.cpp b/src/benchmarks/pmemobj_tx_add_range.cpp deleted file mode 100644 index 76fcf44ca3..0000000000 --- a/src/benchmarks/pmemobj_tx_add_range.cpp +++ /dev/null @@ -1,278 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2019-2020, Intel Corporation */ - -/* - * pmemobj_tx_add_range.cpp -- pmemobj_tx_add_range benchmarks definition - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "benchmark.hpp" -#include "file.h" -#include "libpmemobj.h" - -#define LAYOUT_NAME "tx_add_range_benchmark" - -/* - * POOL_SIZE_COEFFICIENT -- pool has to hold every allocated object with - * its snapshot (1 + 1), plus 0.5 because of fragmentation - */ -#define POOL_SIZE_COEFFICIENT (1 + 1 + 0.5) - -/* - * MAX_ALLOC_SIZE -- maximum size of one allocation (128 MiB) - */ -#define MAX_ALLOC_SIZE (1024 * 1024 * 128) - -/* - * ranged_obj -- ranged object - */ -struct ranged_obj { - void *ptr; /* address of allocated object */ - size_t size; /* size of allocated object */ -}; - -/* - * obj_bench_args -- benchmark specific command line options - */ -struct obj_bench_args { - uint64_t nranges; /* number of allocated objects */ - bool shuffle_objs; /* shuffles the array of allocated objects */ -}; - -/* - * obj_bench -- benchmark context - */ -struct obj_bench { - PMEMobjpool *pop; /* persistent pool handle */ - struct ranged_obj *ranges; /* array of ranges */ - size_t obj_size; /* size of a single range */ - uint64_t nranges; /* number of ranges */ - uint64_t nallocs; /* number of allocations */ - bool shuffle_objs; /* shuffles array of ranges */ - rng_t rng; /* PRNG */ -}; - -/* - * shuffle_ranges -- randomly shuffles elements in an array - * to avoid sequential pattern in the transaction loop - */ -static void -shuffle_ranges(struct ranged_obj *ranged, uint64_t nranges, rng_t *rng) -{ - struct ranged_obj tmp; - uint64_t dest; - - for (uint64_t n = 0; n < nranges; ++n) { - dest = RRAND_R(rng, nranges - 1, 0); - tmp = ranged[n]; - ranged[n] = ranged[dest]; - ranged[dest] = tmp; - } -} - -/* - * init_ranges -- allocate persistent objects and carve ranges from them - */ -static int -init_ranges(struct obj_bench *ob) -{ - assert(ob->nranges != 0); - ob->ranges = (struct ranged_obj *)malloc((ob->nranges) * - sizeof(struct ranged_obj)); - if (!ob->ranges) { - perror("malloc"); - return -1; - } - - size_t nranges_per_object = MAX_ALLOC_SIZE / ob->obj_size; - - for (size_t i = 0, n = 0; n < ob->nranges && i < ob->nallocs; i++) { - PMEMoid oid; - if (pmemobj_alloc(ob->pop, &oid, MAX_ALLOC_SIZE, 0, nullptr, - nullptr)) { - perror("pmemobj_alloc"); - goto err; - } - - for (size_t j = 0; j < nranges_per_object; j++) { - void *ptr = (char *)pmemobj_direct(oid) + - (j * ob->obj_size); - struct ranged_obj range = {ptr, ob->obj_size}; - ob->ranges[n++] = range; - if (n == ob->nranges) - break; - } - } - - if (ob->shuffle_objs == true) - shuffle_ranges(ob->ranges, ob->nranges, &ob->rng); - - return 0; - -err: - free(ob->ranges); - return -1; -} - -/* - * tx_add_range_init -- initialization function - */ -static int -tx_add_range_init(struct benchmark *bench, struct benchmark_args *args) -{ - assert(bench != nullptr); - assert(args != nullptr); - assert(args->opts != nullptr); - - struct obj_bench_args *bargs = (struct obj_bench_args *)args->opts; - - enum file_type type = util_file_get_type(args->fname); - if (type == OTHER_ERROR) { - fprintf(stderr, "could not check type of file %s\n", - args->fname); - return -1; - } - - auto *ob = (struct obj_bench *)malloc(sizeof(struct obj_bench)); - if (ob == nullptr) { - perror("malloc"); - return -1; - } - - /* let's calculate number of allocations */ - ob->nallocs = (args->dsize * bargs->nranges / MAX_ALLOC_SIZE) + 1; - - size_t pool_size; - - if (args->is_poolset || type == TYPE_DEVDAX) - pool_size = 0; - else { - pool_size = - ob->nallocs * MAX_ALLOC_SIZE * POOL_SIZE_COEFFICIENT; - } - - /* create pmemobj pool */ - ob->pop = pmemobj_create(args->fname, LAYOUT_NAME, pool_size, - args->fmode); - if (ob->pop == nullptr) { - fprintf(stderr, "%s\n", pmemobj_errormsg()); - goto err; - } - - ob->nranges = bargs->nranges; - ob->obj_size = args->dsize; - ob->shuffle_objs = bargs->shuffle_objs; - randomize_r(&ob->rng, args->seed); - - if (init_ranges(ob)) - goto err_pop_close; - - pmembench_set_priv(bench, ob); - - return 0; - -err_pop_close: - pmemobj_close(ob->pop); -err: - free(ob); - return -1; -} - -/* - * tx_add_range_op -- actual benchmark operation - */ -static int -tx_add_range_op(struct benchmark *bench, struct operation_info *info) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - int ret = 0; - - TX_BEGIN(ob->pop) - { - for (size_t i = 0; i < ob->nranges; i++) { - struct ranged_obj *r = &ob->ranges[i]; - pmemobj_tx_add_range_direct(r->ptr, r->size); - } - } - TX_ONABORT - { - fprintf(stderr, "transaction failed\n"); - ret = -1; - } - TX_END - - return ret; -} - -/* - * tx_add_range_exit -- benchmark cleanup function - */ -static int -tx_add_range_exit(struct benchmark *bench, struct benchmark_args *args) -{ - auto *ob = (struct obj_bench *)pmembench_get_priv(bench); - - pmemobj_close(ob->pop); - free(ob->ranges); - free(ob); - - return 0; -} - -static struct benchmark_clo tx_add_range_clo[2]; - -/* Stores information about benchmark. */ -static struct benchmark_info tx_add_range_info; -CONSTRUCTOR(tx_add_range_constructor) -void -tx_add_range_constructor(void) -{ - tx_add_range_clo[0].opt_short = 0; - tx_add_range_clo[0].opt_long = "num-of-ranges"; - tx_add_range_clo[0].descr = "Number of ranges"; - tx_add_range_clo[0].def = "1000"; - tx_add_range_clo[0].off = - clo_field_offset(struct obj_bench_args, nranges); - tx_add_range_clo[0].type = CLO_TYPE_UINT; - tx_add_range_clo[0].type_uint.size = - clo_field_size(struct obj_bench_args, nranges); - tx_add_range_clo[0].type_uint.base = CLO_INT_BASE_DEC; - tx_add_range_clo[0].type_uint.min = 1; - tx_add_range_clo[0].type_uint.max = ULONG_MAX; - - tx_add_range_clo[1].opt_short = 's'; - tx_add_range_clo[1].opt_long = "shuffle"; - tx_add_range_clo[1].descr = - "Use shuffle objects - " - "randomly shuffles array of allocated objects"; - tx_add_range_clo[1].def = "false"; - tx_add_range_clo[1].off = - clo_field_offset(struct obj_bench_args, shuffle_objs); - tx_add_range_clo[1].type = CLO_TYPE_FLAG; - - tx_add_range_info.name = "pmemobj_tx_add_range"; - tx_add_range_info.brief = "Benchmark for pmemobj_tx_add_range() " - "operation"; - tx_add_range_info.init = tx_add_range_init; - tx_add_range_info.exit = tx_add_range_exit; - tx_add_range_info.multithread = true; - tx_add_range_info.multiops = true; - tx_add_range_info.operation = tx_add_range_op; - tx_add_range_info.measure_time = true; - tx_add_range_info.clos = tx_add_range_clo; - tx_add_range_info.nclos = ARRAY_SIZE(tx_add_range_clo); - tx_add_range_info.opts_size = sizeof(struct obj_bench_args); - tx_add_range_info.rm_file = true; - tx_add_range_info.allow_poolset = true; - REGISTER_BENCHMARK(tx_add_range_info); -}; diff --git a/src/benchmarks/poolset_util.cpp b/src/benchmarks/poolset_util.cpp deleted file mode 100644 index e158da591c..0000000000 --- a/src/benchmarks/poolset_util.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2018, Intel Corporation */ - -#include -#include -#include - -#include "os.h" -#include "poolset_util.hpp" -#include "set.h" - -#define PART_TEMPLATE "part." -#define POOL_PART_SIZE (1UL << 30) - -/* - * dynamic_poolset_clear -- clears header in first part if it exists - */ -static int -dynamic_poolset_clear(const char *dir) -{ - char path[PATH_MAX]; - int count = snprintf(path, sizeof(path), - "%s" OS_DIR_SEP_STR PART_TEMPLATE "0", dir); - assert(count > 0); - if ((size_t)count >= sizeof(path)) { - fprintf(stderr, "path to a poolset part too long\n"); - return -1; - } - - int exists = util_file_exists(path); - if (exists < 0) - return -1; - - if (!exists) - return 0; - - return util_file_zero(path, 0, POOL_HDR_SIZE); -} - -/* - * dynamic_poolset_create -- clear pool's header and create new poolset - */ -int -dynamic_poolset_create(const char *path, size_t size) -{ - /* buffer for part's path and size */ - char buff[PATH_MAX + 20]; - - int ret; - int fd; - int count; - int curr_part = 0; - - ret = dynamic_poolset_clear(path); - if (ret == -1) - return -1; - - fd = os_open(POOLSET_PATH, O_RDWR | O_CREAT, 0644); - if (fd == -1) { - perror("open"); - return -1; - } - - char header[] = "PMEMPOOLSET\nOPTION SINGLEHDR\n"; - - ret = util_write_all(fd, header, sizeof(header) - 1); - if (ret == -1) - goto err; - - while (curr_part * POOL_PART_SIZE < size + POOL_HDR_SIZE) { - count = snprintf(buff, sizeof(buff), - "%lu %s" OS_DIR_SEP_STR PART_TEMPLATE "%d\n", - POOL_PART_SIZE, path, curr_part); - assert(count > 0); - if ((size_t)count >= sizeof(buff)) { - fprintf(stderr, "path to a poolset part too long\n"); - goto err; - } - - ret = util_write_all(fd, buff, count); - if (ret == -1) - goto err; - - curr_part++; - } - - close(fd); - return 0; - -err: - close(fd); - return -1; -} diff --git a/src/benchmarks/poolset_util.hpp b/src/benchmarks/poolset_util.hpp deleted file mode 100644 index e6add0b2c3..0000000000 --- a/src/benchmarks/poolset_util.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2018-2020, Intel Corporation */ -/* - * poolset_util.hpp -- this file provides interface for creating - * poolsets of specified size - */ - -#ifndef POOLSET_UTIL_HPP -#define POOLSET_UTIL_HPP - -#include - -#define POOLSET_PATH "pool.set" - -int dynamic_poolset_create(const char *path, size_t size); - -#endif diff --git a/src/benchmarks/scenario.cpp b/src/benchmarks/scenario.cpp deleted file mode 100644 index 53f8a85f1b..0000000000 --- a/src/benchmarks/scenario.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2019, Intel Corporation */ -/* - * scenario.cpp -- scenario module definitions - */ -#include -#include -#include - -#include "queue.h" -#include "scenario.hpp" - -/* - * kv_alloc -- allocate key/value structure - */ -struct kv * -kv_alloc(const char *key, const char *value) -{ - struct kv *kv = (struct kv *)malloc(sizeof(*kv)); - assert(kv != nullptr); - - kv->key = strdup(key); - assert(kv->key != nullptr); - - kv->value = strdup(value); - assert(kv->value != nullptr); - - return kv; -} - -/* - * kv_free -- free the key/value structure - */ -void -kv_free(struct kv *kv) -{ - assert(kv != nullptr); - free(kv->key); - free(kv->value); - free(kv); -} - -/* - * scenario_alloc -- allocate scenario structure - */ -struct scenario * -scenario_alloc(const char *name, const char *bench) -{ - struct scenario *s = (struct scenario *)malloc(sizeof(*s)); - assert(s != nullptr); - - PMDK_TAILQ_INIT(&s->head); - s->name = strdup(name); - assert(s->name != nullptr); - - s->benchmark = strdup(bench); - assert(s->benchmark != nullptr); - - s->group = nullptr; - - return s; -} - -/* - * scenario_free -- free the scenario structure and all its content - */ -void -scenario_free(struct scenario *s) -{ - assert(s != nullptr); - - while (!PMDK_TAILQ_EMPTY(&s->head)) { - struct kv *kv = PMDK_TAILQ_FIRST(&s->head); - PMDK_TAILQ_REMOVE(&s->head, kv, next); - kv_free(kv); - } - - free(s->group); - free(s->name); - free(s->benchmark); - free(s); -} - -/* - * scenario_set_group -- set group of scenario - */ -void -scenario_set_group(struct scenario *s, const char *group) -{ - assert(s != nullptr); - s->group = strdup(group); -} - -/* - * scenarios_alloc -- allocate scenarios structure - */ -struct scenarios * -scenarios_alloc(void) -{ - struct scenarios *scenarios = - (struct scenarios *)malloc(sizeof(*scenarios)); - assert(nullptr != scenarios); - - PMDK_TAILQ_INIT(&scenarios->head); - - return scenarios; -} - -/* - * scenarios_free -- free scenarios structure and all its content - */ -void -scenarios_free(struct scenarios *scenarios) -{ - assert(scenarios != nullptr); - while (!PMDK_TAILQ_EMPTY(&scenarios->head)) { - struct scenario *sce = PMDK_TAILQ_FIRST(&scenarios->head); - PMDK_TAILQ_REMOVE(&scenarios->head, sce, next); - scenario_free(sce); - } - - free(scenarios); -} - -/* - * scenarios_get_scenario -- get scenario of given name - */ -struct scenario * -scenarios_get_scenario(struct scenarios *ss, const char *name) -{ - struct scenario *scenario; - FOREACH_SCENARIO(scenario, ss) - { - if (strcmp(scenario->name, name) == 0) - return scenario; - } - return nullptr; -} - -/* - * contains_scenarios -- check if cmd line args contain any scenarios from ss - */ -bool -contains_scenarios(int argc, char **argv, struct scenarios *ss) -{ - assert(argv != nullptr); - assert(argc > 0); - assert(ss != nullptr); - - for (int i = 0; i < argc; i++) { - if (scenarios_get_scenario(ss, argv[i])) - return true; - } - return false; -} - -/* - * clone_scenario -- alloc a new scenario and copy all data from src scenario - */ -struct scenario * -clone_scenario(struct scenario *src_scenario) -{ - assert(src_scenario != nullptr); - - struct scenario *new_scenario = - scenario_alloc(src_scenario->name, src_scenario->benchmark); - assert(new_scenario != nullptr); - - struct kv *src_kv; - - FOREACH_KV(src_kv, src_scenario) - { - struct kv *new_kv = kv_alloc(src_kv->key, src_kv->value); - assert(new_kv != nullptr); - - PMDK_TAILQ_INSERT_TAIL(&new_scenario->head, new_kv, next); - } - - return new_scenario; -} -/* - * find_kv_in_scenario - find a kv in the given scenario with the given key - * value. Function returns the pointer to the kv structure containing the key or - * nullptr if it is not found - */ -struct kv * -find_kv_in_scenario(const char *key, const struct scenario *scenario) -{ - struct kv *kv; - - FOREACH_KV(kv, scenario) - { - if (strcmp(kv->key, key) == 0) - return kv; - } - return nullptr; -} diff --git a/src/benchmarks/scenario.hpp b/src/benchmarks/scenario.hpp deleted file mode 100644 index 64c1b1cee5..0000000000 --- a/src/benchmarks/scenario.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* Copyright 2015-2020, Intel Corporation */ -/* - * scenario.hpp -- scenario module declaration - */ - -#include "queue.h" -#include - -struct kv { - PMDK_TAILQ_ENTRY(kv) next; - char *key; - char *value; -}; - -struct scenario { - PMDK_TAILQ_ENTRY(scenario) next; - PMDK_TAILQ_HEAD(scenariohead, kv) head; - char *name; - char *benchmark; - char *group; -}; - -struct scenarios { - PMDK_TAILQ_HEAD(scenarioshead, scenario) head; -}; - -#define FOREACH_SCENARIO(s, ss) PMDK_TAILQ_FOREACH((s), &(ss)->head, next) -#define FOREACH_KV(kv, s) PMDK_TAILQ_FOREACH((kv), &(s)->head, next) - -struct kv *kv_alloc(const char *key, const char *value); -void kv_free(struct kv *kv); - -struct scenario *scenario_alloc(const char *name, const char *bench); -void scenario_free(struct scenario *s); -void scenario_set_group(struct scenario *s, const char *group); - -struct scenarios *scenarios_alloc(void); -void scenarios_free(struct scenarios *scenarios); - -struct scenario *scenarios_get_scenario(struct scenarios *ss, const char *name); - -bool contains_scenarios(int argc, char **argv, struct scenarios *ss); -struct scenario *clone_scenario(struct scenario *src_scenario); -struct kv *find_kv_in_scenario(const char *key, - const struct scenario *scenario); diff --git a/src/common.inc b/src/common.inc index 664548e43f..8a4f8b2073 100644 --- a/src/common.inc +++ b/src/common.inc @@ -39,14 +39,6 @@ ifeq ($(SRCVERSION),) $(error Cannot evaluate version) endif -ifeq ($(CLANG_FORMAT),) -ifeq ($(shell command -v clang-format-14 > /dev/null && echo y || echo n), y) -export CLANG_FORMAT ?= clang-format-14 -else -export CLANG_FORMAT ?= clang-format -endif -endif - ifeq ($(FLAKE8),) export FLAKE8 ?= flake8 endif @@ -93,7 +85,7 @@ check_librt = $(shell echo "int main() { struct timespec t; return clock_gettime # XXX: required by clock_gettime(), if glibc version < 2.17 # The os_clock_gettime() function is now in OS abstraction layer, -# linked to all the librariess, unit tests and benchmarks. +# linked to all the librariess and unit tests. ifeq ($(LIBRT_NEEDED),) export LIBRT_NEEDED := $(call check_librt) else @@ -204,7 +196,6 @@ export man3dir := $(mandir)/man3 export man5dir := $(mandir)/man5 export man7dir := $(mandir)/man7 export cstyle_bin := $(CSTYLE) -export clang_format_bin := $(CLANG_FORMAT) export flake8_bin := $(FLAKE8) ifneq ($(wildcard $(exec_prefix)/x86_64-linux-gnu),) @@ -224,15 +215,13 @@ cstyle-%: cstyle: cstyle-check -format: cstyle-format - ifeq ($(CSTYLEON),1) define check-cstyle - @$(STYLE_CHECK) check $1 && if [ "$2" != "" ]; then mkdir -p `dirname $2` && touch $2; fi + @$(STYLE_CHECK) $1 && if [ "$2" != "" ]; then mkdir -p `dirname $2` && touch $2; fi endef else ifeq ($(CSTYLEON),2) define check-cstyle - @$(STYLE_CHECK) check $1 && if [ "$2" != "" ]; then mkdir -p `dirname $2` && touch $2; fi || true + @$(STYLE_CHECK) $1 && if [ "$2" != "" ]; then mkdir -p `dirname $2` && touch $2; fi || true endef else define check-cstyle diff --git a/src/examples/Makefile.inc b/src/examples/Makefile.inc index ec9ca1a2e0..fc6a75e3eb 100644 --- a/src/examples/Makefile.inc +++ b/src/examples/Makefile.inc @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2015-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # examples/Makefile.inc -- build the Persistent Memory Development Kit examples @@ -39,21 +40,19 @@ all-dirs: TARGET = all clean-dirs: TARGET = clean clobber-dirs: TARGET = clobber cstyle-dirs: TARGET = cstyle -format-dirs: TARGET = format sparse-dirs: TARGET = sparse all: $(if $(DIRS), all-dirs) $(if $(LIBRARIES), all-libraries) $(if $(PROGS), all-progs) clean: $(if $(DIRS), clean-dirs) $(if $(PROGS), clean-progs) $(if $(LIBRARIES), clean-libraries) clobber: $(if $(DIRS), clobber-dirs) $(if $(PROGS), clobber-progs) $(if $(LIBRARIES), clobber-libraries) cstyle: $(if $(DIRS), cstyle-dirs) -format: $(if $(DIRS), format-dirs) sparse: $(if $(DIRS), sparse-dirs) $(if $(DIRS), , $(sparse-c)) DYNAMIC_LIBRARIES = $(addprefix lib, $(addsuffix .so, $(LIBRARIES))) STATIC_LIBRARIES = $(addprefix lib, $(addsuffix .a, $(LIBRARIES))) -all-dirs clean-dirs clobber-dirs cstyle-dirs format-dirs sparse-dirs: $(DIRS) +all-dirs clean-dirs clobber-dirs cstyle-dirs sparse-dirs: $(DIRS) all-progs: $(PROGS) all-libraries: $(DYNAMIC_LIBRARIES) $(STATIC_LIBRARIES) diff --git a/src/test/Makefile b/src/test/Makefile index dab26479f1..313b881e48 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -303,7 +303,6 @@ clean : TARGET = clean clobber : TARGET = clobber test : TARGET = test cstyle : TARGET = cstyle -format : TARGET = format check : TARGET = check pcheck : TARGET = pcheck sparse : TARGET = sparse @@ -314,7 +313,7 @@ SYNC_EXT=synced TESTCONFIG=$(TOP)/src/test/testconfig.sh FILE_MAX_DAX_DEVICES=$(TOP)/src/test/tools/anonymous_mmap/max_dax_devices -all test format sparse: $(TESTS_BUILD) envconfig.sh envconfig.py +all test sparse: $(TESTS_BUILD) envconfig.sh envconfig.py cstyle: $(TESTS_BUILD) $(CHECK_SHEBANG) $(foreach dir,$(TESTS_BUILD),$(dir)/TEST? $(dir)/TEST??) @@ -413,5 +412,5 @@ SUPP_SYNC_FILES=$(shell echo *.supp | sed s/supp/$(SYNC_EXT)/g) .PHONY: all check clean clobber cstyle pcheck pcheck-log pcheck-obj\ pcheck-other pcheck-pmem pcheck-pmempool\ - test unittest tools format pcheck-libpmempool pycheck\ + test unittest tools pcheck-libpmempool pycheck\ pcheck-local $(TESTS_BUILD) diff --git a/src/test/tools/Makefile b/src/test/tools/Makefile index 8d677bf197..4e536b42b2 100644 --- a/src/test/tools/Makefile +++ b/src/test/tools/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2015-2023, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # src/test/tools/Makefile -- build unit test helpers @@ -34,10 +35,9 @@ all : TARGET = all clean : TARGET = clean clobber : TARGET = clobber cstyle : TARGET = cstyle -format : TARGET = format sparse : TARGET = sparse -all test cstyle clean clobber format sparse: $(DIRS) +all test cstyle clean clobber sparse: $(DIRS) $(TESTCONFIG): @@ -46,4 +46,4 @@ $(DIRS): check pcheck pycheck: all -.PHONY: all clean clobber cstyle format check pcheck $(DIRS) +.PHONY: all clean clobber cstyle check pcheck $(DIRS) diff --git a/src/test/unittest/Makefile b/src/test/unittest/Makefile index 75242382d6..c39e66f9ac 100644 --- a/src/test/unittest/Makefile +++ b/src/test/unittest/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2014-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # src/test/unittest/Makefile -- build unittest support library @@ -113,6 +114,6 @@ test check pcheck pycheck: all sparse: $(sparse-c) -.PHONY: all test check clean clobber cstyle format pcheck +.PHONY: all test check clean clobber cstyle pcheck -include .deps/*.P diff --git a/src/tools/Makefile b/src/tools/Makefile index 7d8d394fc4..477efcdbff 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2014-2022, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Makefile -- top Makefile for tools # @@ -18,12 +19,11 @@ test : TARGET = test clean : TARGET = clean clobber: TARGET = clobber cstyle : TARGET = cstyle -format : TARGET = format install: TARGET = install uninstall: TARGET = uninstall sparse: TARGET = sparse -all clean clobber cstyle install uninstall check format test sparse: $(TARGETS) +all clean clobber cstyle install uninstall check test sparse: $(TARGETS) $(TESTCONFIG): @@ -39,4 +39,4 @@ cscope: cscope -q -b $(SCOPEFILES) ctags -e $(SCOPEFILES) -.PHONY: all clean clobber cstyle format install uninstall common cscope $(TARGETS) +.PHONY: all clean clobber cstyle install uninstall common cscope $(TARGETS) diff --git a/utils/ansible/opensuse-setup.yml b/utils/ansible/opensuse-setup.yml index 8424854944..6fc6367b80 100644 --- a/utils/ansible/opensuse-setup.yml +++ b/utils/ansible/opensuse-setup.yml @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2023-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # This playbook is designed to install all required packages and configure # OpenSUSE to execute tests. @@ -80,14 +81,6 @@ - systemd - libndctl-devel - - name: Install benchmarks dependencies (optional) - package: - state: present - name: - - glib2-devel - - numactl - - python3-pandas - - name: Install examples dependencies (optional) package: state: present diff --git a/utils/ansible/rockylinux-setup.yml b/utils/ansible/rockylinux-setup.yml index cfb335720f..cf85a81f5c 100644 --- a/utils/ansible/rockylinux-setup.yml +++ b/utils/ansible/rockylinux-setup.yml @@ -89,18 +89,6 @@ - passwd - pkgconfig - - name: Install benchmarks dependencies (optional) - package: - state: present - name: - - glib2-devel - - numactl - - python3-pip - - - name: Install benchmarks dependencies part 2 (optional) - ansible.builtin.pip: - name: pandas - - name: Install examples dependencies (optional) package: state: present diff --git a/utils/benchmarks/run_and_combine.py b/utils/benchmarks/run_and_combine.py deleted file mode 100755 index c48fd34283..0000000000 --- a/utils/benchmarks/run_and_combine.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python3 - -# SPDX-License-Identifier: BSD-3-Clause -# Copyright 2024, Intel Corporation - -import argparse -import json -import pandas as pd -import subprocess - - -PARSER = argparse.ArgumentParser() -PARSER.add_argument('--reference', metavar='LD_LIBRARY_PATH', required=True, - help='LD_LIBRARY_PATH where the first version of PMDK is built') -PARSER.add_argument('--rival', metavar='LD_LIBRARY_PATH', required=True, - help='LD_LIBRARY_PATH where the second version of PMDK is built') -PARSER.add_argument('-c', '--config', required=True, - help='Name of the .cfg file to use') -PARSER.add_argument('-s', '--scenario', required=True, - help='Name of the scenario to run') -PARSER.add_argument('-p', '--pmem_path', required=True, - help='PMEM-mounted directory to use') - - -COLUMNS_COMBINE = [ - 'ops-per-second[1/sec]', - 'total-avg[sec]', - 'total-max[sec]', - 'total-min[sec]', - 'total-median[sec]', - 'total-std-dev[sec]', - 'latency-avg[nsec]', - 'latency-min[nsec]', - 'latency-max[nsec]', - 'latency-std-dev[nsec]', - 'latency-pctl-50.0%[nsec]', - 'latency-pctl-99.0%[nsec]', - 'latency-pctl-99.9%[nsec]', -] - - -COLUMNS_COPY = [ - 'threads', - 'ops-per-thread', - 'data-size', - 'seed', - 'repeats', - 'thread-affinity', - 'main-affinity', - 'min-exe-time', - 'random', - 'min-size', - 'type-number', - 'operation', - 'lib', - 'nestings', - 'type', - 'max-key', - 'external-tx', - 'alloc', -] - - -def get_numa_node(pmem_path: str) -> int: - """Find the NUMA node of the device mounted at the specified path""" - # no slash at the end of the path - if pmem_path[-1] == '/': - pmem_path = pmem_path[0:-1] - # find the line describing the mount point - mount = subprocess.getoutput('mount') - mount_line = None - for line in mount.splitlines(): - if pmem_path in line: - mount_line = line - break - if mount_line is None: - print(mount) - raise Exception(f'Can not find the mounted PMEM device for: {pmem_path}') - # Extract blockdev from the found line e.g. - # /dev/pmem1 on /mnt/pmem1 type ext4 (rw,noatime,seclabel,nodelalloc,dax=always) - # - Linux device is the first part of the line e.g. /dev/pmem1 - # - blockdev is the name of the device file e.g. pmem1 - blockdev = mount_line.split(' ')[0].split('/')[2] - # Find the NDCTL namespace of the blockdev and extract its NUMA node - numa_node = None - namespaces = json.loads(subprocess.getoutput('ndctl list -v')) - for namespace in namespaces: - if namespace['mode'] == 'fsdax' and namespace['blockdev'] == blockdev: - numa_node = namespace['numa_node'] - break - if numa_node is None: - print(namespaces) - raise Exception(f'Can not find the namespace: mode == "fsdax" and blockdev == "{blockdev}"') - return numa_node - - -IDX_TO_NAME = ['ref', 'riv'] - - -def output_name(args: argparse.Namespace, idx: int) -> str: - """Generate a file name for an output ref or riv""" - return f'{args.config}__{args.scenario}_{IDX_TO_NAME[idx]}.csv' - - -def run(numa_node: int, args: argparse.Namespace, idx: int, ld_library_path: str) -> None: - """Run PMEMBENCH according to the provided parameters""" - config = f'src/benchmarks/{args.config}.cfg' - file = f'{args.pmem_path}/testfile.obj' - cmd = f'numactl --cpunodebind {numa_node} --localalloc ./src/benchmarks/pmembench {config} {args.scenario} --file {file}' - env = {'LD_LIBRARY_PATH': ld_library_path} - result = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, encoding='utf-8', shell=True) - # generate the file with the output - if result.returncode == 0: - # drop the first line e.g. obj_rbtree_map_insert: map_insert [1] - out = ''.join(result.stdout.splitlines(keepends=True)[1:]) - else: - out = result.stdout - with open(output_name(args, idx), 'w') as output: - output.write(out) - # validate the run - if result.returncode != 0: - print(result.stdout) - print(result.stderr) - exit(result.returncode) - - -def column_name(column: str, idx: int) -> str: - """Generate a column name with ref or rev infix""" - return f'-{IDX_TO_NAME[idx]}['.join(column.split('[')) - - -def combine(args: argparse.Namespace) -> None: - """" - Combine outputs from the reference and rival runs. - - Output data files: - - combined - contains data from ref and riv together with a normalized - difference between them. - - diff - just a normalized difference between ref and riv - """ - dfs = [pd.read_csv(output_name(args, idx), sep=';') for idx in range(2)] - combined = pd.DataFrame() - diff = pd.DataFrame() - for column in COLUMNS_COMBINE: - # Copy columns to combine from both ref and riv - for idx in range(2): - combined[column_name(column, idx)] = dfs[idx][column] - diff_column = f'{column}-diff' - # Normalized difference between ref and riv: - # diff = (riv - ref) / ref - # Both output data frames contains diff columns. - combined[diff_column] = (dfs[1][column] / dfs[0][column] - 1) - diff[diff_column] = combined[diff_column] - for column in COLUMNS_COPY: - if column in dfs[0].columns: - # These columns are identical in both data frames - # so they can be copied from either data frame ref or riv. - combined[column] = dfs[0][column] - diff[column] = dfs[0][column] - # Write the generated data frames to CSV files. - prefix = f'{args.config}__{args.scenario}' - combined.to_csv(f'{prefix}_combined.csv', index=False, float_format='%.3f') - diff.to_csv(f'{prefix}_diff.csv', index=False, float_format='%.3f') - - -def main(): - args = PARSER.parse_args() - numa_node = get_numa_node(args.pmem_path) - for idx, ld_library_path in enumerate([args.reference, args.rival]): - run(numa_node, args, idx, ld_library_path) - combine(args) - - -if __name__ == '__main__': - main() diff --git a/utils/check-area.sh b/utils/check-area.sh index 225f40ea66..2fd5bb82c3 100755 --- a/utils/check-area.sh +++ b/utils/check-area.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause # Copyright 2018-2023, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Finds applicable area name for specified commit id. @@ -38,7 +39,6 @@ categorize pmem -e "^src/libpmem/" -e "^src/include/libpmem.h" categorize pmem2 -e "^src/libpmem2/" -e "^src/include/libpmem2.h" -e "^src/include/libpmem2/" categorize obj -e "^src/libpmemobj/" -e "^src/include/libpmemobj.h" -e "^src/include/libpmemobj/" categorize pool -e "^src/libpmempool/" -e "^src/include/libpmempool.h" -e "^src/tools/pmempool/" -categorize benchmark -e "^src/benchmarks/" categorize examples -e "^src/examples/" categorize daxio -e "^src/tools/daxio/" categorize pmreorder -e "^src/tools/pmreorder/" diff --git a/utils/check-commit.sh b/utils/check-commit.sh index 7ae26e4fd8..8f97f74c59 100755 --- a/utils/check-commit.sh +++ b/utils/check-commit.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause # Copyright 2016-2023, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Used to check whether all the commit messages in a pull request @@ -30,7 +31,7 @@ if [[ $subject =~ ^Revert.* ]]; then fi # valid area names -AREAS="pmem\|pmem2\|obj\|pool\|set\|test\|benchmark\|examples\|doc\|core\|common\|daxio\|pmreorder" +AREAS="pmem\|pmem2\|obj\|pool\|set\|test\|examples\|doc\|core\|common\|daxio\|pmreorder" prefix=$(echo $subject | sed -n "s/^\($AREAS\)\:.*/\1/p") diff --git a/utils/docker/images/Dockerfile.opensuse-leap-15 b/utils/docker/images/Dockerfile.opensuse-leap-15 index 827c60c9c3..14807ea3b5 100644 --- a/utils/docker/images/Dockerfile.opensuse-leap-15 +++ b/utils/docker/images/Dockerfile.opensuse-leap-15 @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2016-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Dockerfile - a 'recipe' for Docker to build an image of openSUSE-based @@ -36,10 +37,6 @@ ENV VALGRIND_DEPS "\ findutils \ git" -# benchmarks dependencies (optional) -ENV BENCH_DEPS "\ - glib2-devel" - # examples dependencies (optional) ENV EXAMPLES_DEPS "\ fuse \ @@ -93,7 +90,6 @@ RUN zypper ar -f http://download.opensuse.org/distribution/leap/15.4/repo/oss/ o RUN zypper update -y && zypper install -y \ $BASE_DEPS \ $VALGRIND_DEPS \ - $BENCH_DEPS \ $EXAMPLES_DEPS \ $DOC_DEPS \ $TESTS_DEPS \ diff --git a/utils/docker/images/Dockerfile.rockylinux-8 b/utils/docker/images/Dockerfile.rockylinux-8 index 5650d881be..f7d3d4268a 100644 --- a/utils/docker/images/Dockerfile.rockylinux-8 +++ b/utils/docker/images/Dockerfile.rockylinux-8 @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2023-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Dockerfile - a 'recipe' for Docker to build an image of rockylinux-based @@ -33,10 +34,6 @@ ENV VALGRIND_DEPS "\ findutils \ git" -# benchmarks dependencies (optional) -ENV BENCH_DEPS "\ - glib2-devel" - # examples dependencies (optional) ENV EXAMPLES_DEPS "\ fuse \ @@ -92,7 +89,6 @@ RUN dnf update -y && dnf install -y epel-release \ && dnf install -y \ $BASE_DEPS \ $VALGRIND_DEPS \ - $BENCH_DEPS \ $EXAMPLES_DEPS \ $DOC_DEPS \ $TESTS_DEPS \ diff --git a/utils/docker/images/Dockerfile.rockylinux-9 b/utils/docker/images/Dockerfile.rockylinux-9 index c9dc999566..0086417891 100644 --- a/utils/docker/images/Dockerfile.rockylinux-9 +++ b/utils/docker/images/Dockerfile.rockylinux-9 @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2023-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Dockerfile - a 'recipe' for Docker to build an image of rockylinux-based @@ -33,10 +34,6 @@ ENV VALGRIND_DEPS "\ findutils \ git" -# benchmarks dependencies (optional) -ENV BENCH_DEPS "\ - glib2-devel" - # examples dependencies (optional) ENV EXAMPLES_DEPS "\ fuse \ @@ -90,7 +87,6 @@ RUN dnf update -y && dnf install -y epel-release \ && dnf --enablerepo devel install -y \ $BASE_DEPS \ $VALGRIND_DEPS \ - $BENCH_DEPS \ $EXAMPLES_DEPS \ $DOC_DEPS \ $TESTS_DEPS \ diff --git a/utils/docker/images/Dockerfile.ubuntu-22.04 b/utils/docker/images/Dockerfile.ubuntu-22.04 index 13afc6a09a..8c7a19f08c 100644 --- a/utils/docker/images/Dockerfile.ubuntu-22.04 +++ b/utils/docker/images/Dockerfile.ubuntu-22.04 @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright 2016-2024, Intel Corporation +# Copyright 2026, Hewlett Packard Enterprise Development LP # # Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based @@ -33,9 +34,6 @@ ENV VALGRIND_DEPS "autoconf \ build-essential \ git" -# benchmarks dependencies (optional) -ENV BENCH_DEPS libglib2.0-dev - # examples dependencies (optional) ENV EXAMPLES_DEPS "libfuse-dev \ libncurses5-dev \ @@ -69,7 +67,6 @@ ENV COVERITY_DEPS ruby gcc g++ wget ENV MISC_DEPS "clang \ hub \ rsync \ - clang-format \ flake8 \ python3-pip \ sudo \ @@ -88,7 +85,6 @@ RUN apt-get update && apt-get dist-upgrade -y \ && apt-get install -y --no-install-recommends \ $BASE_DEPS \ $VALGRIND_DEPS \ - $BENCH_DEPS \ $EXAMPLES_DEPS \ $DOC_DEPS \ $TESTS_DEPS \ diff --git a/utils/style_check.sh b/utils/style_check.sh index 2d764131f6..a080a4a859 100755 --- a/utils/style_check.sh +++ b/utils/style_check.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause # Copyright 2016-2023, Intel Corporation -# Copyright 2025, Hewlett Packard Enterprise Development LP +# Copyright 2025-2026, Hewlett Packard Enterprise Development LP # # utils/style_check.sh -- common style checking script # @@ -13,43 +13,6 @@ CLANG_ARGS=() FLAKE8_ARGS=() CHECK_TYPE=$1 -# When updating, please search for all references to "clang-format" and update -# them as well; at this time these are CONTRIBUTING.md src/common.inc and -# docker images. -[ -z "$clang_format_bin" ] && which clang-format-14 >/dev/null && - clang_format_bin=clang-format-14 -[ -z "$clang_format_bin" ] && which clang-format >/dev/null && - clang_format_bin=clang-format -[ -z "$clang_format_bin" ] && clang_format_bin=clang-format - -# -# print script usage -# -function usage() { - echo "$0 [C/C++ files]" -} - -# -# require clang-format version 14.0 -# -function check_clang_version() { - set +e - which ${clang_format_bin} &> /dev/null && ${clang_format_bin} --version |\ - grep "version 14\.0"\ - &> /dev/null - if [ $? -ne 0 ]; then - MSG="requires clang-format version==14.0" - if [ "x$CSTYLE_FAIL_IF_CLANG_FORMAT_MISSING" == "x1" ]; then - echo "FAIL: $MSG" - exit 1 - else - echo "SKIP: $MSG" - exit 0 - fi - fi - set -e -} - # # run old cstyle check # @@ -61,37 +24,6 @@ function run_cstyle() { ${cstyle_bin} -pP $@ } -# -# generate diff with clang-format rules -# -function run_clang_check() { - if [ $# -eq 0 ]; then - return - fi - check_clang_version - - for file in $@ - do - LINES=$(${clang_format_bin} -style=file $file |\ - git diff --no-index $file - | wc -l) - if [ $LINES -ne 0 ]; then - ${clang_format_bin} -style=file $file | git diff --no-index $file - - fi - done -} - -# -# in-place format according to clang-format rules -# -function run_clang_format() { - if [ $# -eq 0 ]; then - return - fi - check_clang_version - - ${clang_format_bin} -style=file -i $@ -} - function run_flake8() { if [ $# -eq 0 ]; then return @@ -109,9 +41,6 @@ for ((i=1; i<$#; i++)) { fi fi case ${ARGS[$i]} in - *.[ch]pp) - CLANG_ARGS+="${ARGS[$i]} " - ;; *.[ch]) CSTYLE_ARGS+="${ARGS[$i]} " @@ -128,20 +57,5 @@ for ((i=1; i<$#; i++)) { esac } -case $CHECK_TYPE in - check) - run_cstyle ${CSTYLE_ARGS} - run_clang_check ${CLANG_ARGS} - run_flake8 ${FLAKE8_ARGS} - ;; - - format) - run_clang_format ${CLANG_ARGS} - ;; - - *) - echo "Invalid parameters" - usage - exit 1 - ;; -esac +run_cstyle ${CSTYLE_ARGS} +run_flake8 ${FLAKE8_ARGS}