Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
dto-test*
libdto.so*
libdto_explicit.so*
build*/
tests/baselines*/
dtoctl
/doc/dtoctl.1
49 changes: 49 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,47 @@ if (HAS_WAITPKG)
endforeach()
endif()

# Build dtoctl. By default it preloads the libdto.so installed alongside it,
# found relative to the dtoctl binary so "cmake --install --prefix" still works,
# and falls back to the configured install path. Set DTOCTL_LIBPATH to always
# preload a specific library instead.
set(DTOCTL_LIBPATH "" CACHE FILEPATH
"Path to libdto.so that dtoctl preloads by default (empty: the installed libdto.so)")
add_executable(dtoctl dtoctl.c)
target_compile_definitions(dtoctl PRIVATE DTO_VERSION="${PROJECT_VERSION}")
if(DTOCTL_LIBPATH)
target_compile_definitions(dtoctl PRIVATE LIBDTO_PATH="${DTOCTL_LIBPATH}")
else()
# Not cached, so it follows later changes to CMAKE_INSTALL_PREFIX.
get_filename_component(DTOCTL_LIBDIR "${CMAKE_INSTALL_LIBDIR}" ABSOLUTE
BASE_DIR "${CMAKE_INSTALL_PREFIX}")
get_filename_component(DTOCTL_BINDIR "${CMAKE_INSTALL_BINDIR}" ABSOLUTE
BASE_DIR "${CMAKE_INSTALL_PREFIX}")
file(RELATIVE_PATH DTOCTL_REL_LIBPATH "${DTOCTL_BINDIR}" "${DTOCTL_LIBDIR}/libdto.so")
target_compile_definitions(dtoctl PRIVATE
LIBDTO_PATH="${DTOCTL_LIBDIR}/libdto.so"
LIBDTO_REL_PATH="${DTOCTL_REL_LIBPATH}")
endif()
install(TARGETS dtoctl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

# Build and install the optional section 1 manual.
find_program(PANDOC_EXECUTABLE NAMES pandoc)
if(PANDOC_EXECUTABLE)
set(DTOCTL_MAN_PAGE "${CMAKE_CURRENT_BINARY_DIR}/doc/dtoctl.1")
add_custom_command(
OUTPUT "${DTOCTL_MAN_PAGE}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/doc"
COMMAND "${PANDOC_EXECUTABLE}" --standalone --to=man
"${CMAKE_CURRENT_SOURCE_DIR}/doc/dtoctl.md" -o "${DTOCTL_MAN_PAGE}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/doc/dtoctl.md"
COMMENT "Generating dtoctl(1) manual"
VERBATIM)
add_custom_target(dtoctl-man ALL DEPENDS "${DTOCTL_MAN_PAGE}")
install(FILES "${DTOCTL_MAN_PAGE}" DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
else()
message(STATUS "Skipping dtoctl manual generation and installation: install pandoc to build the man page.")
endif()

# Build dto-test and dto-test-wodto
add_executable(dto-test dto-test.c)
target_link_libraries(dto-test PRIVATE DTO::dto pthread)
Expand Down Expand Up @@ -158,6 +199,14 @@ if(DTO_BUILD_TESTS)
TIMEOUT 120
)
endif()
# dtoctl option handling and environment setup (no DSA hardware needed)
add_test(NAME dtoctl
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_dtoctl.sh
$<TARGET_FILE:dtoctl> $<TARGET_FILE:dto>)
set_tests_properties(dtoctl PROPERTIES
LABELS "functional"
TIMEOUT 60
)

# ---- A/B performance regression test ----
# The baseline object is compiled from unguarded upstream sources that
Expand Down
36 changes: 33 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@
#
# SPDX-License-Identifier: MIT

all: libdto dto-test-wodto
all: libdto dtoctl dto-test-wodto man

.PHONY: man install-man

DML_LIB_CXX=-D_GNU_SOURCE

# Path to libdto.so that dtoctl prepends to LD_PRELOAD (matches "make install").
DTOCTL_LIBPATH ?= /usr/lib64/libdto.so
PANDOC ?= pandoc
MANDIR ?= /usr/share/man
# Version reported by "dtoctl --version", taken from the CMake project.
DTO_VERSION := $(shell grep -o 'DTO VERSION [0-9.]*' CMakeLists.txt | cut -d' ' -f3)

libdto: dto.c
gcc -shared -fPIC -Wl,-soname,libdto.so dto.c $(DML_LIB_CXX) -DDTO_STATS_SUPPORT -DDTO_ACCEL_CONFIG_SUPPORT -DDTO_NUMA_SUPPORT -o libdto.so.1.0 -laccel-config -ldl -lnuma -mwaitpkg

Expand All @@ -16,11 +25,31 @@ libdto_nostats: dto.c
libdto_explicit: dto.c
gcc -shared -fPIC -Wl,-soname,libdto_explicit.so dto.c $(DML_LIB_CXX) -DDTO_NO_LIBC_INTERPOSE -DDTO_ACCEL_CONFIG_SUPPORT -DDTO_NUMA_SUPPORT -o libdto_explicit.so.1.0 -laccel-config -ldl -lnuma -mwaitpkg

install:
dtoctl: dtoctl.c
gcc -O2 -Wall dtoctl.c -DLIBDTO_PATH=\"$(DTOCTL_LIBPATH)\" -DDTO_VERSION=\"$(DTO_VERSION)\" -o dtoctl

man: doc/dtoctl.1

doc/dtoctl.1: doc/dtoctl.md
@if command -v "$(PANDOC)" >/dev/null 2>&1; then \
"$(PANDOC)" --standalone --to=man $< -o $@; \
else \
echo "Skipping dtoctl manual generation: install pandoc to build the man page."; \
fi

install: dtoctl install-man
cp libdto.so.1.0 /usr/lib64/
cp dto.h /usr/include/
ln -sf /usr/lib64/libdto.so.1.0 /usr/lib64/libdto.so.1
ln -sf /usr/lib64/libdto.so.1.0 /usr/lib64/libdto.so
cp dtoctl /usr/bin/

install-man: man
@if [ -f doc/dtoctl.1 ]; then \
install -D -m 644 doc/dtoctl.1 "$(MANDIR)/man1/dtoctl.1"; \
else \
echo "Skipping dtoctl manual installation: no generated man page is available."; \
fi

install-local:
ln -sf ./libdto.so.1.0 ./libdto.so.1
Expand All @@ -33,4 +62,5 @@ dto-test-wodto: dto-test.c
gcc -g dto-test.c $(DML_LIB_CXX) -o dto-test-wodto -lpthread

clean:
rm -rf *.o *.so dto-test
rm -rf *.o *.so dto-test dtoctl
rm -f doc/dtoctl.1
61 changes: 58 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ Following environment variables control the behavior of DTO library:
Should be enabled for debugging/profiling only, not for perf evaluation (enabling it slows down the workload). Default is 0.
DTO_STATS_FILE=<path> when DTO_COLLECT_STATS=1, redirect histogram output to the provided regular file instead of standard output.
The file is truncated when DTO loads; failures fall back to standard output and emit an error.
DTO_WAIT_METHOD=<yield,busypoll,umwait> (specifies the method to use while waiting for DSA to complete operation, default is yield)
DTO_MIN_BYTES=xxxx (specifies minimum size of API call needed for DSA operation execution, default is 16384 bytes)
DTO_WAIT_METHOD=<yield,busypoll,umwait,tpause> (specifies the method to use while waiting for DSA to complete operation, default is busypoll)
DTO_MIN_BYTES=xxxx (specifies minimum size of API call needed for DSA operation execution, default is 65536 bytes)
DTO_CPU_SIZE_FRACTION=0.xx (specifies fraction of job performed by CPU, in parallel to DSA). Default is 0.00
DTO_AUTO_ADJUST_KNOBS=0/1 (disables/enables auto tuning of cpu_size_fraction and dsa_min_bytes parameters. 0 -- disable, 1 -- enable (default))
DTO_IS_NUMA_AWARE=0/1/2 (disables/buffer-centric/cpu-centric numa awareness. 0 -- disable (default), 1 -- buffer-centric, 2 - cpu-centric)
Expand All @@ -69,7 +69,7 @@ Following environment variables control the behavior of DTO library:
DTO_DSA_CC=0/1, 1 (default) - DTO sets DSA Cache Control flag to 1 if DSA supports cache control, 0 - DTO sets DSA Cache Control flag to 0
DTO_OVERLAPPING_MEMMOVE_ACTION=0/1 0 (default) DTO submits memmove operations with overlapping buffers entirely to CPU, 1 - entirely to DSA
DTO_UMWAIT_DELAY=xxxx defines delay for umwait command (check max possible value at: /sys/devices/system/cpu/umwait_control/max_time), default is 100000
DTO_LOG_FILE=<dto log file path> Redirect the DTO output to the specified file instead of std output (useful for debugging and statistics collection). file name is suffixed by process pid.
DTO_LOG_FILE=<dto log file path> Redirect the DTO output to the specified file instead of std output (useful for debugging and statistics collection). file name is suffixed by the program name and process pid (<path>.<program>.<pid>).
DTO_LOG_LEVEL=0/1/2 controls the log level. higher value means more verbose logging (default 0).
DTO_CRC_MIN_BYTES=xxxx smallest buffer dto_crc32c_with_seed() sends to DSA; smaller ones are checksummed on the CPU (default: DTO_MIN_BYTES).
```
Expand Down Expand Up @@ -140,6 +140,61 @@ Programs that only use this API, and must not have their own large libc copies
sent to DSA, can link `libdto_explicit` instead: the same library without the
memcpy/memset/memmove/memcmp interposers (`-ldto_explicit`, or
`DTO::dto_explicit` from CMake).
## Using dtoctl

Setting `LD_PRELOAD` and exporting the `DTO_*` environment variables by hand is
error prone. The `dtoctl` tool provides a simpler interface: it takes the DTO
settings as command line options, converts them to the corresponding `DTO_*`
environment variables, prepends `libdto.so` to `LD_PRELOAD`, and then runs the
target program. For example, instead of

```bash
export LD_PRELOAD=/usr/local/lib/libdto.so
export DTO_WAIT_METHOD=busypoll
export DTO_CPU_SIZE_FRACTION=0.33
export DTO_AUTO_ADJUST_KNOBS=1
./prog
```

you can run

```bash
dtoctl -w busypoll -c 0.33 ./prog
```

Every environment variable listed above has a corresponding option, and option
values are checked before the program runs (DTO itself silently falls back to a
default on a value it does not understand). Only the options you pass are
applied: a `DTO_*` variable you already exported is left untouched, an explicit
option overrides it, and `-i/--ignore-env` drops all inherited `DTO_*`
variables.

The `libdto.so` path is resolved from `-l/--library`, then `$DTO_LIBRARY`, then
the library installed with `dtoctl`, then the compiled-in default
(`/usr/local/lib/libdto.so` for a CMake build, `/usr/lib64/libdto.so` for the
Makefile build). It is made absolute and prepended to any existing
`LD_PRELOAD`, and `dtoctl` fails if the library cannot be read rather than
running the program without DTO.

To see what would run without running it, use `--dry-run`:

```bash
$ dtoctl --dry-run -w umwait -b 16K ./prog
library: /usr/lib64/libdto.so.1.0 (compiled-in default)
LD_PRELOAD=/usr/lib64/libdto.so.1.0
DTO_WAIT_METHOD=umwait # option
DTO_MIN_BYTES=16384 # option
command: ./prog
```

DSA work queues are often accessible to root only. Run `sudo dtoctl ...`
rather than `dtoctl sudo ...`, which loses `LD_PRELOAD` and the `DTO_*`
variables, and pass settings as options: `sudo` does not pass on variables
exported in your shell.

Run `dtoctl --help` for the option list, or `man 1 dtoctl` for the full manual,
which documents each option and gives a ready-to-run command for each of the
usage models above.

## Build

Expand Down
14 changes: 14 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ the work queue has (it reports which), so run the suite once with
`block_on_fault` enabled and once without to cover both. It assumes all work
queues DTO uses share the same setting.

## dtoctl Tests

Checks for the `dtoctl` wrapper: every option sets its `DTO_*` variable,
invalid values are rejected, the library path is resolved and validated,
`LD_PRELOAD` and inherited variables are handled, and exit statuses follow
`env(1)`. The last check runs a program under `dtoctl` and reads libdto's own
configuration trace. No DSA hardware is needed.

```bash
ctest -R dtoctl
# or directly, from the source directory
tests/test_dtoctl.sh build/dtoctl build/libdto.so
```

## Performance Tests

The performance test (`perf`) detects regressions in libdto by
Expand Down
Loading
Loading