: perf: reduce data loss when profiling highly parallel CPU bound workloads
v15 cover : perf: reduce data loss when profiling highly parallel CPU bound workloads
Currently in record mode the tool implements trace writing serially. The algorithm loops over mapped per-cpu data buffers and stores ready data chunks into a trace file using write() system call.
At some circumstances the kernel may lack free space in a buffer because the other buffer's half is not yet written to disk due to some other buffer's data writing by the tool at the moment.
Thus serial trace writing implementation may cause the kernel to loose profiling data and that is what observed when profiling highly parallel CPU bound workloads on machines with big number of cores.
Experiment with profiling matrix multiplication code executing 128 threads on Intel Xeon Phi (KNM) with 272 cores, like below, demonstrates data loss metrics value of 98%:
/usr/bin/time perf record -o /tmp/perf-ser.data -a -N -B -T -R -g \
--call-graph dwarf,1024 --user-regs=IP,SP,BP --switch-events \
-e cycles,instructions,ref-cycles,software/period=1,name=cs,config=0x3/Duk -- \
matrix.gccData loss metrics is the ratio lost_time/elapsed_time where lost_time is the sum of time intervals containing PERF_RECORD_LOST records and elapsed_time is the elapsed application run time under profiling.
Applying asynchronous trace streaming thru Posix AIO API [1] lowers data loss metrics value providing 2x improvement (from 98% to ~1%)
Asynchronous trace streaming is currently limited to glibc linkage. musl libc [5] also provides Posix AIO API implementation, however the patchkit is not tested with it. There may be other libc libraries linked by Perf tool that currently lack Posix AIO API support [2], [3], [4] so NO_AIO define may be used to limit Perf tool binary to serial streaming only.
---
Alexey Budankov (3):
perf util: map data buffer for preserving collected data perf record: enable asynchronous trace writing perf record: extend trace writing to multi AIO
tools/build/Makefile.feature | 6 +- tools/build/feature/Makefile | 6 +- tools/build/feature/test-all.c | 5 + tools/build/feature/test-libaio.c | 16 ++ tools/perf/Documentation/perf-record.txt | 5 + tools/perf/Makefile.config | 6 + tools/perf/Makefile.perf | 7 +- tools/perf/builtin-record.c | 255 ++++++++++++++++++++++++++++++- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 2 +- tools/perf/util/mmap.c | 146 +++++++++++++++++- tools/perf/util/mmap.h | 26 +++- 13 files changed, 473 insertions(+), 14 deletions(-)
---
Changes in v15:
- implemented libaio feature check and defined HAVE_AIO_SUPPORT accordingly
- implemented nr_cblocks_max variable similar to nr_cblocks_default
Changes in v14:
- implement default nr_cblocks_default variable
- fix --aio option handling
Changes in v13:
- named new functions with _aio_ word
- grouped aio functions under single #ifdef HAVE_AIO_SUPPORT
- moved perf_mmap__aio_push() stub into header
- removed trailed white space
Changes in v12:
- applied stub functions design for the whole patch kit
- grouped AIO related data into a struct under struct perf_mmap
- implemented record__aio_get/set_pos(), record__aio_enabled()
- implemented simple --aio option
- extended --aio option to --aio-cblocks=<n>
Changes in v11:
- replacing the both lseek() syscalls in every loop iteration by the only
two syscalls just before and after the loop at record__mmap_read_evlist() and advancing *in-flight* off file pos value at perf_mmap__aio_push()
Changes in v10:
- moved specific code to perf_mmap__aio_mmap(), perf_mmap__aio_munmap();
- adjusted error reporting by using %m
- avoided lseek() setting file pos back in case of record__aio_write() failure
- compacted code selecting between serial and AIO streaming
- optimized call places of record__mmap_read_sync()
- added description of aio-cblocks option into perf-record.txt
Changes in v9:
- enable AIO streaming only when --aio-cblocks option is specified explicitly
- enable AIO based implementation when linking with glibc only
- define NO_AIO to limit Perf binary to serial implementation
Changes in v8:
- run the whole thing thru checkpatch.pl and corrected found issues except lines longer than 80 symbols
- corrected comments alignment and formatting
- moved multi AIO implementation into 3rd patch in the series
- implemented explicit cblocks array allocation
- split AIO completion check into separate record__aio_complete()
- set nr_cblocks default to 1 and max allowed value to 4
Changes in v7:
- implemented handling record.aio setting from perfconfig file
Changes in v6:
- adjusted setting of priorities for cblocks;
- handled errno == EAGAIN case from aio_write() return;
Changes in v5:
- resolved livelock on perf record -e intel_pt// -- dd if=/dev/zero of=/dev/null count=100000
- data loss metrics decreased from 25% to 2x in trialed configuration;
- reshaped layout of data structures;
- implemented --aio option;
- avoided nanosleep() prior calling aio_suspend();
- switched to per-cpu aio multi buffer record__aio_sync();
- record_mmap_read_sync() now does global sync just before
switching trace file or collection stop;
Changes in v4:
- converted mmap()/munmap() to malloc()/free() for mmap->data buffer management
- converted void *bf to struct perf_mmap *md in signatures
- written comment in perf_mmap__push() just before perf_mmap__get();
- written comment in record__mmap_read_sync() on possible restarting
of aio_write() operation and releasing perf_mmap object after all;
- added perf_mmap__put() for the cases of failed aio_write();
Changes in v3:
- written comments about nanosleep(0.5ms) call prior aio_suspend()
to cope with intrusiveness of its implementation in glibc;
- written comments about rationale behind coping profiling data
into mmap->data buffer;
Changes in v2:
- converted zalloc() to calloc() for allocation of mmap_aio array,
- cleared typo and adjusted fallback branch code;
---
[1] http://man7.org/linux/man-pages/man7/aio.7.html
[2] https://android.googlesource.com/platform/bionic/+/master/docs/status.md
[3] https://www.uclibc.org/
[4] https://uclibc-ng.org/
PATCH v15 1/3 : perf util: map data buffer for preserving collected data
The map->data buffer is used to preserve map->base profiling data for writing to disk. AIO map->cblock is used to queue corresponding map->data buffer for asynchronous writing.
---
Changes in v15:
- implemented libaio feature check and defined HAVE_AIO_SUPPORT accordingly
Changes in v13:
- grouped aio functions under single #ifdef HAVE_AIO_SUPPORT
Changes in v12:
- applied stub functions design for the whole patch kit
- grouped AIO related data into a struct under struct perf_mmap
Changes in v10:
- moved specific code to perf_mmap__aio_mmap(), perf_mmap__aio_munmap()
- adjusted error reporting by using %m
Changes in v9:
- implemented NO_AIO and HAVE_AIO_SUPPORT defines to cover cases of libc implementations without Posix AIO API support
Changes in v7:
- implemented handling record.aio setting from perfconfig file
Changes in v6:
- adjusted setting of priorities for cblocks;
Changes in v5:
- reshaped layout of data structures;
- implemented --aio option;
Changes in v4:
- converted mmap()/munmap() to malloc()/free() for mmap->data buffer management
Changes in v2:
- converted zalloc() to calloc() for allocation of mmap_aio array,
- cleared typo and adjusted fallback branch code;
--- tools/build/Makefile.feature | 6 +++-- tools/build/feature/Makefile | 6 ++++- tools/build/feature/test-all.c | 5 ++++ tools/build/feature/test-libaio.c | 16 +++++++++++++ tools/perf/Makefile.config | 6 +++++ tools/perf/Makefile.perf | 7 +++++- tools/perf/util/evlist.c | 2 +- tools/perf/util/mmap.c | 49 ++++++++++++++++++++++++++++++++++++++- tools/perf/util/mmap.h | 11 ++++++++- 9 files changed, 101 insertions(+), 7 deletions(-)
tools/build/Makefile.feature +4 -2
@@ -68,7 +68,8 @@ FEATURE_TESTS_BASIC := \ sched_getcpu \ sdt \ setns \ - libopencsd + libopencsd \ + libaio # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests
@@ -114,7 +115,8 @@ FEATURE_DISPLAY ?= \ zlib \ lzma \ get_cpuid \ - bpf + bpf \ + libaio # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not
tools/build/feature/Makefile +5 -1
@@ -58,7 +58,8 @@ FILES= \ test-libopencsd.bin \ test-clang.bin \ test-llvm.bin \ - test-llvm-version.bin + test-llvm-version.bin \ + test-libaio.bin FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -285,6 +286,9 @@ $(OUTPUT)test-clang.bin: -include $(OUTPUT)*.d +$(OUTPUT)test-libaio.bin: + $(BUILD) -lrt + ############################### clean:
tools/build/feature/test-all.c +5 -0
@@ -166,6 +166,10 @@# include "test-libopencsd.c" #undef main +#define main main_test_libaio +# include "test-libaio.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -204,6 +208,7 @@ int main(int argc, char *argv[])main_test_sdt ();main_test_setns ();main_test_libopencsd (); +main_test_libaio ();return 0 ; }
tools/build/feature/test-libaio.c new file +16 -0
@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <aio.h> + +int main (void ) +{ +struct aiocb aiocb; + + aiocb.aio_fildes =0 ; + aiocb.aio_offset =0 ; + aiocb.aio_buf =0 ; + aiocb.aio_nbytes =0 ; + aiocb.aio_reqprio =0 ; + aiocb.aio_sigevent.sigev_notify =1 /*SIGEV_NONE*/ ; + +return (int )aio_return (&aiocb); +}
tools/perf/Makefile.config +6 -0
@@ -357,6 +357,12 @@ ifeq ($(feature-glibc), 1) CFLAGS += -DHAVE_GLIBC_SUPPORT endif +ifeq ($(feature-libaio), 1) + ifndef NO_AIO + CFLAGS += -DHAVE_AIO_SUPPORT + endif +endif + ifdef NO_DWARF NO_LIBDW_DWARF_UNWIND := 1 endif
tools/perf/Makefile.perf +6 -1
@@ -97,8 +97,13 @@ include ../scripts/utilities.mak # Define LIBCLANGLLVM if you DO want builtin clang and llvm support. # When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if # llvm-config is not in $PATH. - +# # Define NO_CORESIGHT if you do not want support for CoreSight trace decoding. +# +# Define NO_AIO if you do not want support of Posix AIO based trace +# streaming for record mode. Currently Posix AIO trace streaming is +# supported only when linking with glibc. +# # As per kernel Makefile, avoid funny character set dependencies unexport LC_ALL
tools/perf/util/evlist.c +1 -1
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp; +struct mmap_params mp = { .nr_cblocks =0 };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
tools/perf/util/mmap.c +48 -1
63 lines not on this page · raw message
tools/perf/util/mmap.h +10 -1
@@ -6,6 +6,9 @@#include <linux/types.h> #include <asm/barrier.h> #include <stdbool.h> +#ifdef HAVE_AIO_SUPPORT +#include <aio.h> +#endif #include "auxtrace.h" #include "event.h"
@@ -26,6 +29,12 @@ struct perf_mmap {bool overwrite;struct auxtrace_mmap auxtrace_mmap;char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ; +#ifdef HAVE_AIO_SUPPORT +struct { +void *data; +struct aiocb cblock; + } aio; +#endif };/*
@@ -57,7 +66,7 @@ enum bkw_mmap_state { };struct mmap_params { -int prot, mask; +int prot, mask, nr_cblocks;struct auxtrace_mmap_params auxtrace_mp; };
tip-bot for Alexey Budankov
merge bot[tip:perf/core] tools build feature: Check if libaio is available
tools build feature: Check if libaio is available
Commit-ID: fd849f025a14fd31d90f779df3dcd6ff467cc35b Gitweb: https://git.kernel.org/tip/fd849f025a14fd31d90f779df3dcd6ff467cc35b Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:03:35 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Nov 2018 20:42:49 -0300
tools build feature: Check if libaio is available
This will be used by 'perf record' to speed up reading the perf ring buffer.
Committer testing:
$ make -C tools/perf O=/tmp/build/perf
make: Entering directory '/home/acme/git/perf/tools/perf'
BUILD: Doing 'make -j8' parallel buildAuto-detecting system features:
... dwarf: [ on ] ... dwarf_getlocations: [ on ] ... glibc: [ on ] ... gtk2: [ OFF ] ... libaudit: [ OFF ] ... libbfd: [ OFF ] ... libelf: [ on ] ... libnuma: [ OFF ] ... numa_num_possible_cpus: [ OFF ] ... libperl: [ OFF ] ... libpython: [ OFF ] ... libslang: [ on ] ... libcrypto: [ on ] ... libunwind: [ on ] ... libdw-dwarf-unwind: [ on ] ... zlib: [ on ] ... lzma: [ on ] ... get_cpuid: [ on ] ... bpf: [ on ] ... libaio: [ on ]
$ ls -la /tmp/build/perf/feature/test-libaio.* -rwxrwxr-x. 1 acme acme 18296 Nov 26 08:49 /tmp/build/perf/feature/test-libaio.bin -rw-rw-r--. 1 acme acme 1165 Nov 26 08:49 /tmp/build/perf/feature/test-libaio.d -rw-rw-r--. 1 acme acme 0 Nov 26 08:49 /tmp/build/perf/feature/test-libaio.make.output $ $ grep -i aio /tmp/build/perf/FEATURE-DUMP feature-libaio=1 $
--- tools/build/Makefile.feature | 6 ++++-- tools/build/feature/Makefile | 6 +++++- tools/build/feature/test-all.c | 5 +++++ tools/build/feature/test-libaio.c | 16 ++++++++++++++++ tools/perf/Makefile.config | 6 ++++++ tools/perf/Makefile.perf | 7 ++++++- 6 files changed, 42 insertions(+), 4 deletions(-)
tools/build/Makefile.feature +4 -2
@@ -70,7 +70,8 @@ FEATURE_TESTS_BASIC := \ sched_getcpu \ sdt \ setns \ - libopencsd + libopencsd \ + libaio # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests
@@ -116,7 +117,8 @@ FEATURE_DISPLAY ?= \ zlib \ lzma \ get_cpuid \ - bpf + bpf \ + libaio # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not
tools/build/feature/Makefile +5 -1
@@ -61,7 +61,8 @@ FILES= \ test-libopencsd.bin \ test-clang.bin \ test-llvm.bin \ - test-llvm-version.bin + test-llvm-version.bin \ + test-libaio.bin FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -297,6 +298,9 @@ $(OUTPUT)test-clang.bin: -include $(OUTPUT)*.d +$(OUTPUT)test-libaio.bin: + $(BUILD) -lrt + ############################### clean:
tools/build/feature/test-all.c +5 -0
@@ -174,6 +174,10 @@# include "test-libopencsd.c" #undef main +#define main main_test_libaio +# include "test-libaio.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -214,6 +218,7 @@ int main(int argc, char *argv[])main_test_sdt ();main_test_setns ();main_test_libopencsd (); +main_test_libaio ();return 0 ; }
tools/build/feature/test-libaio.c new file +16 -0
@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <aio.h> + +int main (void ) +{ +struct aiocb aiocb; + + aiocb.aio_fildes =0 ; + aiocb.aio_offset =0 ; + aiocb.aio_buf =0 ; + aiocb.aio_nbytes =0 ; + aiocb.aio_reqprio =0 ; + aiocb.aio_sigevent.sigev_notify =1 /*SIGEV_NONE*/ ; + +return (int )aio_return (&aiocb); +}
tools/perf/Makefile.config +6 -0
@@ -365,6 +365,12 @@ ifeq ($(feature-glibc), 1) CFLAGS += -DHAVE_GLIBC_SUPPORT endif +ifeq ($(feature-libaio), 1) + ifndef NO_AIO + CFLAGS += -DHAVE_AIO_SUPPORT + endif +endif + ifdef NO_DWARF NO_LIBDW_DWARF_UNWIND := 1 endif
tools/perf/Makefile.perf +6 -1
@@ -101,8 +101,13 @@ include ../scripts/utilities.mak # Define LIBCLANGLLVM if you DO want builtin clang and llvm support. # When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if # llvm-config is not in $PATH. - +# # Define NO_CORESIGHT if you do not want support for CoreSight trace decoding. +# +# Define NO_AIO if you do not want support of Posix AIO based trace +# streaming for record mode. Currently Posix AIO trace streaming is +# supported only when linking with glibc. +# # As per kernel Makefile, avoid funny character set dependencies unexport LC_ALL
tip-bot for Alexey Budankov
merge bot[tip:perf/core] perf mmap: Map data buffer for preserving collected data
In reply to Alexey Budankovperf mmap: Map data buffer for preserving collected data
Commit-ID: 98dffeb1a4000e93de9ae247651e0bf4a07dc6ea Gitweb: https://git.kernel.org/tip/98dffeb1a4000e93de9ae247651e0bf4a07dc6ea Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:03:35 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Nov 2018 20:42:49 -0300
perf mmap: Map data buffer for preserving collected data
The map->data buffer is used to preserve map->base profiling data for writing to disk. AIO map->cblock is used to queue corresponding map->data buffer for asynchronous writing.
--- tools/perf/util/evlist.c | 2 +- tools/perf/util/mmap.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/mmap.h | 11 ++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-)
tools/perf/util/evlist.c +1 -1
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp; +struct mmap_params mp = { .nr_cblocks =0 };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
tools/perf/util/mmap.c +48 -1
63 lines not on this page · raw message
tools/perf/util/mmap.h +10 -1
@@ -6,6 +6,9 @@#include <linux/types.h> #include <linux/ring_buffer.h> #include <stdbool.h> +#ifdef HAVE_AIO_SUPPORT +#include <aio.h> +#endif #include "auxtrace.h" #include "event.h"
@@ -26,6 +29,12 @@ struct perf_mmap {bool overwrite;struct auxtrace_mmap auxtrace_mmap;char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ; +#ifdef HAVE_AIO_SUPPORT +struct { +void *data; +struct aiocb cblock; + } aio; +#endif };/*
@@ -57,7 +66,7 @@ enum bkw_mmap_state { };struct mmap_params { -int prot, mask; +int prot, mask, nr_cblocks;struct auxtrace_mmap_params auxtrace_mp; };
tip-bot for Alexey Budankov
merge bot[tip:perf/core] perf mmap: Map data buffer for preserving collected data
In reply to Alexey Budankovperf mmap: Map data buffer for preserving collected data
Commit-ID: 0b77383134f3dbb461189a9c4f3b46b20152045d Gitweb: https://git.kernel.org/tip/0b77383134f3dbb461189a9c4f3b46b20152045d Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:03:35 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 17 Dec 2018 14:55:01 -0300
perf mmap: Map data buffer for preserving collected data
The map->data buffer is used to preserve map->base profiling data for writing to disk. AIO map->cblock is used to queue corresponding map->data buffer for asynchronous writing.
--- tools/perf/util/evlist.c | 2 +- tools/perf/util/mmap.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/mmap.h | 11 ++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-)
tools/perf/util/evlist.c +1 -1
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp; +struct mmap_params mp = { .nr_cblocks =0 };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
tools/perf/util/mmap.c +48 -1
63 lines not on this page · raw message
tools/perf/util/mmap.h +10 -1
@@ -6,6 +6,9 @@#include <linux/types.h> #include <linux/ring_buffer.h> #include <stdbool.h> +#ifdef HAVE_AIO_SUPPORT +#include <aio.h> +#endif #include "auxtrace.h" #include "event.h"
@@ -26,6 +29,12 @@ struct perf_mmap {bool overwrite;struct auxtrace_mmap auxtrace_mmap;char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ; +#ifdef HAVE_AIO_SUPPORT +struct { +void *data; +struct aiocb cblock; + } aio; +#endif };/*
@@ -57,7 +66,7 @@ enum bkw_mmap_state { };struct mmap_params { -int prot, mask; +int prot, mask, nr_cblocks;struct auxtrace_mmap_params auxtrace_mp; };
tip-bot for Alexey Budankov
merge bot[tip:perf/core] tools build feature: Check if libaio is available
In reply to Alexey Budankovtools build feature: Check if libaio is available
Commit-ID: 2a07d814747b386feec7d7150fe519feb2a2a5f2 Gitweb: https://git.kernel.org/tip/2a07d814747b386feec7d7150fe519feb2a2a5f2 Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:03:35 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 17 Dec 2018 14:54:54 -0300
tools build feature: Check if libaio is available
This will be used by 'perf record' to speed up reading the perf ring buffer.
Committer testing:
$ make -C tools/perf O=/tmp/build/perf
make: Entering directory '/home/acme/git/perf/tools/perf'
BUILD: Doing 'make -j8' parallel buildAuto-detecting system features:
... dwarf: [ on ] ... dwarf_getlocations: [ on ] ... glibc: [ on ] ... gtk2: [ OFF ] ... libaudit: [ OFF ] ... libbfd: [ OFF ] ... libelf: [ on ] ... libnuma: [ OFF ] ... numa_num_possible_cpus: [ OFF ] ... libperl: [ OFF ] ... libpython: [ OFF ] ... libslang: [ on ] ... libcrypto: [ on ] ... libunwind: [ on ] ... libdw-dwarf-unwind: [ on ] ... zlib: [ on ] ... lzma: [ on ] ... get_cpuid: [ on ] ... bpf: [ on ] ... libaio: [ on ]
$ ls -la /tmp/build/perf/feature/test-libaio.* -rwxrwxr-x. 1 acme acme 18296 Nov 26 08:49 /tmp/build/perf/feature/test-libaio.bin -rw-rw-r--. 1 acme acme 1165 Nov 26 08:49 /tmp/build/perf/feature/test-libaio.d -rw-rw-r--. 1 acme acme 0 Nov 26 08:49 /tmp/build/perf/feature/test-libaio.make.output $ $ grep -i aio /tmp/build/perf/FEATURE-DUMP feature-libaio=1 $
--- tools/build/Makefile.feature | 6 ++++-- tools/build/feature/Makefile | 6 +++++- tools/build/feature/test-all.c | 5 +++++ tools/build/feature/test-libaio.c | 16 ++++++++++++++++ tools/perf/Makefile.config | 6 ++++++ tools/perf/Makefile.perf | 7 ++++++- 6 files changed, 42 insertions(+), 4 deletions(-)
tools/build/Makefile.feature +4 -2
@@ -70,7 +70,8 @@ FEATURE_TESTS_BASIC := \ sched_getcpu \ sdt \ setns \ - libopencsd + libopencsd \ + libaio # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests
@@ -116,7 +117,8 @@ FEATURE_DISPLAY ?= \ zlib \ lzma \ get_cpuid \ - bpf + bpf \ + libaio # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not
tools/build/feature/Makefile +5 -1
@@ -61,7 +61,8 @@ FILES= \ test-libopencsd.bin \ test-clang.bin \ test-llvm.bin \ - test-llvm-version.bin + test-llvm-version.bin \ + test-libaio.bin FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -297,6 +298,9 @@ $(OUTPUT)test-clang.bin: -include $(OUTPUT)*.d +$(OUTPUT)test-libaio.bin: + $(BUILD) -lrt + ############################### clean:
tools/build/feature/test-all.c +5 -0
@@ -174,6 +174,10 @@# include "test-libopencsd.c" #undef main +#define main main_test_libaio +# include "test-libaio.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -214,6 +218,7 @@ int main(int argc, char *argv[])main_test_sdt ();main_test_setns ();main_test_libopencsd (); +main_test_libaio ();return 0 ; }
tools/build/feature/test-libaio.c new file +16 -0
@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <aio.h> + +int main (void ) +{ +struct aiocb aiocb; + + aiocb.aio_fildes =0 ; + aiocb.aio_offset =0 ; + aiocb.aio_buf =0 ; + aiocb.aio_nbytes =0 ; + aiocb.aio_reqprio =0 ; + aiocb.aio_sigevent.sigev_notify =1 /*SIGEV_NONE*/ ; + +return (int )aio_return (&aiocb); +}
tools/perf/Makefile.config +6 -0
@@ -365,6 +365,12 @@ ifeq ($(feature-glibc), 1) CFLAGS += -DHAVE_GLIBC_SUPPORT endif +ifeq ($(feature-libaio), 1) + ifndef NO_AIO + CFLAGS += -DHAVE_AIO_SUPPORT + endif +endif + ifdef NO_DWARF NO_LIBDW_DWARF_UNWIND := 1 endif
tools/perf/Makefile.perf +6 -1
@@ -101,8 +101,13 @@ include ../scripts/utilities.mak # Define LIBCLANGLLVM if you DO want builtin clang and llvm support. # When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if # llvm-config is not in $PATH. - +# # Define NO_CORESIGHT if you do not want support for CoreSight trace decoding. +# +# Define NO_AIO if you do not want support of Posix AIO based trace +# streaming for record mode. Currently Posix AIO trace streaming is +# supported only when linking with glibc. +# # As per kernel Makefile, avoid funny character set dependencies unexport LC_ALL
PATCH v15 2/3 : perf record: enable asynchronous trace writing
In reply to Alexey BudankovTrace file offset is read once before mmaps iterating loop and written back after all performance data enqueued for aio writing. Trace file offset is incremented linearly after every successful aio write operation.
record__aio_sync() blocks till completion of started AIO operation and then proceeds.
record__aio_mmap_read_sync() implements a barrier for all incomplete aio write requests.
---
Changes in v14:
- implement default nr_cblocks_default variable
Changes in v13:
- named new functions with _aio_ word
- grouped aio functions under single #ifdef HAVE_AIO_SUPPORT
- moved perf_mmap__aio_push() stub into header
- removed trailed white space
Changes in v12:
- implemented record__aio_get/set_pos(), record__aio_enabled()
- implemented simple --aio option
Changes in v11:
- replacing the both lseek() syscalls in every loop iteration by the only
two syscalls just before and after the loop at record__mmap_read_evlist() and advancing *in-flight* off file pos value at perf_mmap__aio_push()
Changes in v10:
- avoided lseek() setting file pos back in case of record__aio_write() failure
- compacted code selecting between serial and AIO streaming
- optimized call places of record__mmap_read_sync()
Changes in v9:
- enable AIO streaming only when --aio-cblocks option is specified explicitly Changes in v8:
- split AIO completion check into separate record__aio_complete()
Changes in v6:
- handled errno == EAGAIN case from aio_write();
Changes in v5:
- data loss metrics decreased from 25% to 2x in trialed configuration;
- avoided nanosleep() prior calling aio_suspend();
- switched to per cpu multi record__aio_sync() aio
- record_mmap_read_sync() now does global barrier just before
switching trace file or collection stop;
- resolved livelock on perf record -e intel_pt// -- dd if=/dev/zero of=/dev/null count=100000 Changes in v4:
- converted void *bf to struct perf_mmap *md in signatures
- written comment in perf_mmap__push() just before perf_mmap__get();
- written comment in record__mmap_read_sync() on possible restarting
of aio_write() operation and releasing perf_mmap object after all;
- added perf_mmap__put() for the cases of failed aio_write();
Changes in v3:
- written comments about nanosleep(0.5ms) call prior aio_suspend()
to cope with intrusiveness of its implementation in glibc;
- written comments about rationale behind coping profiling data
into mmap->data buffer;
--- tools/perf/Documentation/perf-record.txt | 5 + tools/perf/builtin-record.c | 218 ++++++++++++++++++++++++++++++- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 2 +- tools/perf/util/mmap.c | 77 ++++++++++- tools/perf/util/mmap.h | 14 ++ 7 files changed, 314 insertions(+), 9 deletions(-)
tools/perf/Documentation/perf-record.txt +5 -0
@@ -435,6 +435,11 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. +--aio:: +Enable asynchronous (Posix AIO) trace writing mode. +Asynchronous mode is supported only when linking Perf tool with libc library +providing implementation for Posix AIO API. + --all-kernel:: Configure all used events to run in kernel space.
tools/perf/builtin-record.c +214 -4
276 lines not on this page · raw message
tools/perf/perf.h +1 -0
@@ -82,6 +82,7 @@ struct record_opts {bool use_clockid;clockid_t clockid;unsigned int proc_map_timeout; +int nr_cblocks; };struct option ;
tools/perf/util/evlist.c +3 -3
@@ -1018,7 +1018,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,*/ int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite) +bool auxtrace_overwrite,int nr_cblocks) {struct perf_evsel *evsel;const struct cpu_map *cpus = evlist->cpus;
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp = { .nr_cblocks =0 }; +struct mmap_params mp = { .nr_cblocks = nr_cblocks };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
@@ -1060,7 +1060,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages) { -return perf_evlist__mmap_ex (evlist, pages,0 , false); +return perf_evlist__mmap_ex (evlist, pages,0 , false,0 ); }int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target)
tools/perf/util/evlist.h +1 -1
@@ -162,7 +162,7 @@ unsigned long perf_event_mlock_kb_in_pages(void);int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite); +bool auxtrace_overwrite,int nr_cblocks);int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages);void perf_evlist__munmap (struct perf_evlist *evlist);
tools/perf/util/mmap.c +76 -1
89 lines not on this page · raw message
tools/perf/util/mmap.h +14 -0
@@ -12,6 +12,7 @@#include "auxtrace.h" #include "event.h" +struct aiocb ;/** * struct perf_mmap - perf's ring buffer mmap details *
@@ -33,6 +34,7 @@ struct perf_mmap {struct {void *data;struct aiocb cblock; +int nr_cblocks; } aio;#endif };
@@ -103,6 +105,18 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size)); +#ifdef HAVE_AIO_SUPPORT +int perf_mmap__aio_push (struct perf_mmap *md,void *to, +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off), +off_t *off); +#else +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused , +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused , +off_t *off__maybe_unused ) +{ +return 0 ; +} +#endif size_t perf_mmap__mmap_len (struct perf_mmap *map);
tip-bot for Alexey Budankov
merge bot[tip:perf/core] perf record: Enable asynchronous trace writing
perf record: Enable asynchronous trace writing
Commit-ID: ea9ec1c457818547c035ff0f34d3335f6bfeaeb3 Gitweb: https://git.kernel.org/tip/ea9ec1c457818547c035ff0f34d3335f6bfeaeb3 Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:04:58 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Nov 2018 20:42:49 -0300
perf record: Enable asynchronous trace writing
The trace file offset is read once before mmaps iterating loop and written back after all performance data is enqueued for aio writing.
The trace file offset is incremented linearly after every successful aio write operation.
record__aio_sync() blocks till completion of the started AIO operation and then proceeds.
record__aio_mmap_read_sync() implements a barrier for all incomplete aio write requests.
--- tools/perf/Documentation/perf-record.txt | 5 + tools/perf/builtin-record.c | 218 ++++++++++++++++++++++++++++++- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 2 +- tools/perf/util/mmap.c | 77 ++++++++++- tools/perf/util/mmap.h | 14 ++ 7 files changed, 314 insertions(+), 9 deletions(-)
tools/perf/Documentation/perf-record.txt +5 -0
@@ -435,6 +435,11 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. +--aio:: +Enable asynchronous (Posix AIO) trace writing mode. +Asynchronous mode is supported only when linking Perf tool with libc library +providing implementation for Posix AIO API. + --all-kernel:: Configure all used events to run in kernel space.
tools/perf/builtin-record.c +214 -4
276 lines not on this page · raw message
tools/perf/perf.h +1 -0
@@ -83,6 +83,7 @@ struct record_opts {clockid_t clockid;u64 clockid_res_ns;unsigned int proc_map_timeout; +int nr_cblocks; };struct option ;
tools/perf/util/evlist.c +3 -3
@@ -1018,7 +1018,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,*/ int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite) +bool auxtrace_overwrite,int nr_cblocks) {struct perf_evsel *evsel;const struct cpu_map *cpus = evlist->cpus;
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp = { .nr_cblocks =0 }; +struct mmap_params mp = { .nr_cblocks = nr_cblocks };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
@@ -1060,7 +1060,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages) { -return perf_evlist__mmap_ex (evlist, pages,0 , false); +return perf_evlist__mmap_ex (evlist, pages,0 , false,0 ); }int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target)
tools/perf/util/evlist.h +1 -1
@@ -162,7 +162,7 @@ unsigned long perf_event_mlock_kb_in_pages(void);int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite); +bool auxtrace_overwrite,int nr_cblocks);int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages);void perf_evlist__munmap (struct perf_evlist *evlist);
tools/perf/util/mmap.c +76 -1
89 lines not on this page · raw message
tools/perf/util/mmap.h +14 -0
@@ -12,6 +12,7 @@#include "auxtrace.h" #include "event.h" +struct aiocb ;/** * struct perf_mmap - perf's ring buffer mmap details *
@@ -33,6 +34,7 @@ struct perf_mmap {struct {void *data;struct aiocb cblock; +int nr_cblocks; } aio;#endif };
@@ -94,6 +96,18 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size)); +#ifdef HAVE_AIO_SUPPORT +int perf_mmap__aio_push (struct perf_mmap *md,void *to, +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off), +off_t *off); +#else +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused , +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused , +off_t *off__maybe_unused ) +{ +return 0 ; +} +#endif size_t perf_mmap__mmap_len (struct perf_mmap *map);
tip-bot for Alexey Budankov
merge bot[tip:perf/core] perf record: Enable asynchronous trace writing
In reply to Alexey Budankovperf record: Enable asynchronous trace writing
Commit-ID: d3d1af6f011a553a00d2bda90b2700c0d56bd8f7 Gitweb: https://git.kernel.org/tip/d3d1af6f011a553a00d2bda90b2700c0d56bd8f7 Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:04:58 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 17 Dec 2018 14:55:08 -0300
perf record: Enable asynchronous trace writing
The trace file offset is read once before mmaps iterating loop and written back after all performance data is enqueued for aio writing.
The trace file offset is incremented linearly after every successful aio write operation.
record__aio_sync() blocks till completion of the started AIO operation and then proceeds.
record__aio_mmap_read_sync() implements a barrier for all incomplete aio write requests.
--- tools/perf/Documentation/perf-record.txt | 5 + tools/perf/builtin-record.c | 218 ++++++++++++++++++++++++++++++- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 2 +- tools/perf/util/mmap.c | 77 ++++++++++- tools/perf/util/mmap.h | 14 ++ 7 files changed, 314 insertions(+), 9 deletions(-)
tools/perf/Documentation/perf-record.txt +5 -0
@@ -435,6 +435,11 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. +--aio:: +Enable asynchronous (Posix AIO) trace writing mode. +Asynchronous mode is supported only when linking Perf tool with libc library +providing implementation for Posix AIO API. + --all-kernel:: Configure all used events to run in kernel space.
tools/perf/builtin-record.c +214 -4
276 lines not on this page · raw message
tools/perf/perf.h +1 -0
@@ -83,6 +83,7 @@ struct record_opts {clockid_t clockid;u64 clockid_res_ns;unsigned int proc_map_timeout; +int nr_cblocks; };struct option ;
tools/perf/util/evlist.c +3 -3
@@ -1018,7 +1018,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,*/ int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite) +bool auxtrace_overwrite,int nr_cblocks) {struct perf_evsel *evsel;const struct cpu_map *cpus = evlist->cpus;
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp = { .nr_cblocks =0 }; +struct mmap_params mp = { .nr_cblocks = nr_cblocks };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
@@ -1060,7 +1060,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages) { -return perf_evlist__mmap_ex (evlist, pages,0 , false); +return perf_evlist__mmap_ex (evlist, pages,0 , false,0 ); }int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target)
tools/perf/util/evlist.h +1 -1
@@ -162,7 +162,7 @@ unsigned long perf_event_mlock_kb_in_pages(void);int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite); +bool auxtrace_overwrite,int nr_cblocks);int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages);void perf_evlist__munmap (struct perf_evlist *evlist);
tools/perf/util/mmap.c +76 -1
89 lines not on this page · raw message
tools/perf/util/mmap.h +14 -0
@@ -12,6 +12,7 @@#include "auxtrace.h" #include "event.h" +struct aiocb ;/** * struct perf_mmap - perf's ring buffer mmap details *
@@ -33,6 +34,7 @@ struct perf_mmap {struct {void *data;struct aiocb cblock; +int nr_cblocks; } aio;#endif };
@@ -94,6 +96,18 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size)); +#ifdef HAVE_AIO_SUPPORT +int perf_mmap__aio_push (struct perf_mmap *md,void *to, +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off), +off_t *off); +#else +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused , +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused , +off_t *off__maybe_unused ) +{ +return 0 ; +} +#endif size_t perf_mmap__mmap_len (struct perf_mmap *map);
PATCH v15 3/3 : perf record: extend trace writing to multi AIO
In reply to Alexey BudankovMulti AIO trace writing allows caching more kernel data into userspace memory postponing trace writing for the sake of overall profiling data thruput increase. It could be seen as kernel data buffer extension into userspace memory.
With aio option value different from 0, default value is 1, tool has capability to cache more and more data into user space along with delegating spill to AIO.
That allows avoiding suspend at record__aio_sync() between calls of record__mmap_read_evlist() and increase profiling data thruput for the cost of userspace memory.
---
Changes in v15:
- implemented nr_cblocks_max variable similar to nr_cblocks_default Changes in v14:
- fix --aio option handling
Changes in v13:
- preserved --aio option name avoiding complication Changes in v12:
- extended --aio option to --aio-cblocks=<n>
Changes in v10:
- added description of aio-cblocks option into perf-record.tx
--- tools/perf/Documentation/perf-record.txt | 4 +- tools/perf/builtin-record.c | 67 +++++++++++++++++++++++++------- tools/perf/util/mmap.c | 64 ++++++++++++++++++++---------- tools/perf/util/mmap.h | 9 +++-- 4 files changed, 102 insertions(+), 42 deletions(-)
tools/perf/Documentation/perf-record.txt +2 -2
@@ -435,8 +435,8 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. ---aio:: -Enable asynchronous (Posix AIO) trace writing mode. +--aio[=n]:: +Use <n> control blocks in asynchronous (Posix AIO) trace writing mode (default: 1, max: 4). Asynchronous mode is supported only when linking Perf tool with libc library providing implementation for Posix AIO API.
tools/perf/builtin-record.c +52 -15
128 lines not on this page · raw message
tools/perf/util/mmap.c +43 -21
112 lines not on this page · raw message
tools/perf/util/mmap.h +5 -4
@@ -32,8 +32,9 @@ struct perf_mmap {char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ;#ifdef HAVE_AIO_SUPPORT struct { -void *data; -struct aiocb cblock; +void **data; +struct aiocb *cblocks; +struct aiocb **aiocb;int nr_cblocks; } aio;#endif
@@ -106,11 +107,11 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size));#ifdef HAVE_AIO_SUPPORT -int perf_mmap__aio_push (struct perf_mmap *md,void *to, +int perf_mmap__aio_push (struct perf_mmap *md,void *to,int idx,int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off),off_t *off);#else -static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused , +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused ,int idx__maybe_unused ,int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused ,off_t *off__maybe_unused ) {
tip-bot for Alexey Budankov
merge bot[tip:perf/core] perf record: Extend trace writing to multi AIO
perf record: Extend trace writing to multi AIO
Commit-ID: c46216881879ba2576732805bf5f27d04998719b Gitweb: https://git.kernel.org/tip/c46216881879ba2576732805bf5f27d04998719b Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:07:19 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 29 Nov 2018 20:42:50 -0300
perf record: Extend trace writing to multi AIO
Multi AIO trace writing allows caching more kernel data into userspace memory postponing trace writing for the sake of overall profiling data thruput increase. It could be seen as kernel data buffer extension into userspace memory.
With an --aio option value different from 0 (default value is 1) the tool has capability to cache more and more data into user space along with delegating spill to AIO.
That allows avoiding to suspend at record__aio_sync() between calls of record__mmap_read_evlist() and increases profiling data thruput at the cost of userspace memory.
--- tools/perf/Documentation/perf-record.txt | 4 +- tools/perf/builtin-record.c | 67 +++++++++++++++++++++++++------- tools/perf/util/mmap.c | 64 ++++++++++++++++++++---------- tools/perf/util/mmap.h | 9 +++-- 4 files changed, 102 insertions(+), 42 deletions(-)
tools/perf/Documentation/perf-record.txt +2 -2
@@ -435,8 +435,8 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. ---aio:: -Enable asynchronous (Posix AIO) trace writing mode. +--aio[=n]:: +Use <n> control blocks in asynchronous (Posix AIO) trace writing mode (default: 1, max: 4). Asynchronous mode is supported only when linking Perf tool with libc library providing implementation for Posix AIO API.
tools/perf/builtin-record.c +52 -15
128 lines not on this page · raw message
tools/perf/util/mmap.c +43 -21
112 lines not on this page · raw message
tools/perf/util/mmap.h +5 -4
@@ -32,8 +32,9 @@ struct perf_mmap {char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ;#ifdef HAVE_AIO_SUPPORT struct { -void *data; -struct aiocb cblock; +void **data; +struct aiocb *cblocks; +struct aiocb **aiocb;int nr_cblocks; } aio;#endif
@@ -97,11 +98,11 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size));#ifdef HAVE_AIO_SUPPORT -int perf_mmap__aio_push (struct perf_mmap *md,void *to, +int perf_mmap__aio_push (struct perf_mmap *md,void *to,int idx,int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off),off_t *off);#else -static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused , +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused ,int idx__maybe_unused ,int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused ,off_t *off__maybe_unused ) {
tip-bot for Alexey Budankov
merge bot[tip:perf/core] perf record: Extend trace writing to multi AIO
In reply to Alexey Budankovperf record: Extend trace writing to multi AIO
Commit-ID: 93f20c0fe3e86088ec041e47755367c4bed584c6 Gitweb: https://git.kernel.org/tip/93f20c0fe3e86088ec041e47755367c4bed584c6 Author: Alexey Budankov <[email protected]> AuthorDate: Tue, 6 Nov 2018 12:07:19 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 17 Dec 2018 14:55:11 -0300
perf record: Extend trace writing to multi AIO
Multi AIO trace writing allows caching more kernel data into userspace memory postponing trace writing for the sake of overall profiling data thruput increase. It could be seen as kernel data buffer extension into userspace memory.
With an --aio option value different from 0 (default value is 1) the tool has capability to cache more and more data into user space along with delegating spill to AIO.
That allows avoiding to suspend at record__aio_sync() between calls of record__mmap_read_evlist() and increases profiling data thruput at the cost of userspace memory.
--- tools/perf/Documentation/perf-record.txt | 4 +- tools/perf/builtin-record.c | 67 +++++++++++++++++++++++++------- tools/perf/util/mmap.c | 64 ++++++++++++++++++++---------- tools/perf/util/mmap.h | 9 +++-- 4 files changed, 102 insertions(+), 42 deletions(-)
tools/perf/Documentation/perf-record.txt +2 -2
@@ -435,8 +435,8 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. ---aio:: -Enable asynchronous (Posix AIO) trace writing mode. +--aio[=n]:: +Use <n> control blocks in asynchronous (Posix AIO) trace writing mode (default: 1, max: 4). Asynchronous mode is supported only when linking Perf tool with libc library providing implementation for Posix AIO API.
tools/perf/builtin-record.c +52 -15
128 lines not on this page · raw message
tools/perf/util/mmap.c +43 -21
112 lines not on this page · raw message
tools/perf/util/mmap.h +5 -4
@@ -32,8 +32,9 @@ struct perf_mmap {char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ;#ifdef HAVE_AIO_SUPPORT struct { -void *data; -struct aiocb cblock; +void **data; +struct aiocb *cblocks; +struct aiocb **aiocb;int nr_cblocks; } aio;#endif
@@ -97,11 +98,11 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size));#ifdef HAVE_AIO_SUPPORT -int perf_mmap__aio_push (struct perf_mmap *md,void *to, +int perf_mmap__aio_push (struct perf_mmap *md,void *to,int idx,int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off),off_t *off);#else -static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused , +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused ,int idx__maybe_unused ,int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused ,off_t *off__maybe_unused ) {
Quoted 38 lines · Alexey Budankov
Currently in record mode the tool implements trace writing serially. The algorithm loops over mapped per-cpu data buffers and stores ready data chunks into a trace file using
write()system call.At some circumstances the kernel may lack free space in a buffer because the other buffer's half is not yet written to disk due to some other buffer's data writing by the tool at the moment.
Thus serial trace writing implementation may cause the kernel to loose profiling data and that is what observed when profiling highly parallel CPU bound workloads on machines with big number of cores.
Experiment with profiling matrix multiplication code executing 128 threads on Intel Xeon Phi (KNM) with 272 cores, like below, demonstrates data loss metrics value of 98%:
/usr/bin/time perf record -o /tmp/perf-ser.data -a -N -B -T -R -g \ --call-graph dwarf,1024 --user-regs=IP,SP,BP --switch-events \ -e cycles,instructions,ref-cycles,software/period=1,name=cs,config=0x3/Duk -- \ matrix.gccData loss metrics is the ratio lost_time/elapsed_time where
lost_timeis the sum of time intervals containingPERF_RECORD_LOSTrecords andelapsed_timeis the elapsed application run time under profiling.Applying asynchronous trace streaming thru Posix AIO API [1] lowers data loss metrics value providing 2x improvement (from 98% to ~1%)
Asynchronous trace streaming is currently limited to glibc linkage. musl libc [5] also provides Posix AIO API implementation, however the patchkit is not tested with it. There may be other libc libraries linked by Perf tool that currently lack Posix AIO API support [2], [3], [4] so
NO_AIOdefine may be used to limit Perf tool binary to serial streaming only.
Quoted 5 lines
---
Alexey Budankov (3):
perf util: map data buffer for preserving collected data perf record: enable asynchronous trace writing perf record: extend trace writing to multi AIO
FYI I was rebasing my threads branch on top of this and first 2 won't apply anymore on Arnaldo's perf/core
Arnaldo,
could we get this merged soon? the world around is moving fast and we don't want 20th revision on this ;-)
thanks,
jirka
Hi,
Quoted 2 lines · Jiri Olsa
Quoted 1 line · Alexey Budankov
<SNIP>
Quoted 7 lines
Quoted 4 lines
Alexey Budankov (3):
perf util: map data buffer for preserving collected data perf record: enable asynchronous trace writing perf record: extend trace writing to multi AIOFYI I was rebasing my threads branch on top of this and first 2 won't apply anymore on Arnaldo's perf/core
Thanks for the info. git apply -3 resolves rebasing issue. Below is the whole patch for Arnaldo's perf/core.
-Alexey
--- tools/build/Makefile.feature | 6 +- tools/build/feature/Makefile | 6 +- tools/build/feature/test-all.c | 5 + tools/build/feature/test-libaio.c | 16 ++ tools/perf/Documentation/perf-record.txt | 5 + tools/perf/Makefile.config | 6 + tools/perf/Makefile.perf | 7 +- tools/perf/builtin-record.c | 255 ++++++++++++++++++++++++++++++- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evlist.h | 2 +- tools/perf/util/mmap.c | 146 +++++++++++++++++- tools/perf/util/mmap.h | 26 +++- 13 files changed, 473 insertions(+), 14 deletions(-)
tools/build/Makefile.feature +4 -2
@@ -68,7 +68,8 @@ FEATURE_TESTS_BASIC := \ sched_getcpu \ sdt \ setns \ - libopencsd + libopencsd \ + libaio # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests
@@ -114,7 +115,8 @@ FEATURE_DISPLAY ?= \ zlib \ lzma \ get_cpuid \ - bpf + bpf \ + libaio # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not
tools/build/feature/Makefile +5 -1
@@ -58,7 +58,8 @@ FILES= \ test-libopencsd.bin \ test-clang.bin \ test-llvm.bin \ - test-llvm-version.bin + test-llvm-version.bin \ + test-libaio.bin FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -285,6 +286,9 @@ $(OUTPUT)test-clang.bin: -include $(OUTPUT)*.d +$(OUTPUT)test-libaio.bin: + $(BUILD) -lrt + ############################### clean:
tools/build/feature/test-all.c +5 -0
@@ -166,6 +166,10 @@# include "test-libopencsd.c" #undef main +#define main main_test_libaio +# include "test-libaio.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -204,6 +208,7 @@ int main(int argc, char *argv[])main_test_sdt ();main_test_setns ();main_test_libopencsd (); +main_test_libaio ();return 0 ; }
tools/build/feature/test-libaio.c new file +16 -0
@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <aio.h> + +int main (void ) +{ +struct aiocb aiocb; + + aiocb.aio_fildes =0 ; + aiocb.aio_offset =0 ; + aiocb.aio_buf =0 ; + aiocb.aio_nbytes =0 ; + aiocb.aio_reqprio =0 ; + aiocb.aio_sigevent.sigev_notify =1 /*SIGEV_NONE*/ ; + +return (int )aio_return (&aiocb); +}
tools/perf/Documentation/perf-record.txt +5 -0
@@ -435,6 +435,11 @@ Specify vmlinux path which has debuginfo. --buildid-all:: Record build-id of all DSOs regardless whether it's actually hit or not. +--aio[=n]:: +Use <n> control blocks in asynchronous (Posix AIO) trace writing mode (default: 1, max: 4). +Asynchronous mode is supported only when linking Perf tool with libc library +providing implementation for Posix AIO API. + --all-kernel:: Configure all used events to run in kernel space.
tools/perf/Makefile.config +6 -0
@@ -357,6 +357,12 @@ ifeq ($(feature-glibc), 1) CFLAGS += -DHAVE_GLIBC_SUPPORT endif +ifeq ($(feature-libaio), 1) + ifndef NO_AIO + CFLAGS += -DHAVE_AIO_SUPPORT + endif +endif + ifdef NO_DWARF NO_LIBDW_DWARF_UNWIND := 1 endif
tools/perf/Makefile.perf +6 -1
@@ -98,8 +98,13 @@ include ../scripts/utilities.mak # Define LIBCLANGLLVM if you DO want builtin clang and llvm support. # When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if # llvm-config is not in $PATH. - +# # Define NO_CORESIGHT if you do not want support for CoreSight trace decoding. +# +# Define NO_AIO if you do not want support of Posix AIO based trace +# streaming for record mode. Currently Posix AIO trace streaming is +# supported only when linking with glibc. +# # As per kernel Makefile, avoid funny character set dependencies unexport LC_ALL
tools/perf/builtin-record.c +251 -4
319 lines not on this page · raw message
tools/perf/perf.h +1 -0
@@ -83,6 +83,7 @@ struct record_opts {clockid_t clockid;u64 clockid_res_ns;unsigned int proc_map_timeout; +int nr_cblocks; };struct option ;
tools/perf/util/evlist.c +3 -3
@@ -1018,7 +1018,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,*/ int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite) +bool auxtrace_overwrite,int nr_cblocks) {struct perf_evsel *evsel;const struct cpu_map *cpus = evlist->cpus;
@@ -1028,7 +1028,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,* Its value is decided by evsel's write_backward. * So &mp should not be passed through const pointer. */ -struct mmap_params mp; +struct mmap_params mp = { .nr_cblocks = nr_cblocks };if (!evlist->mmap) evlist->mmap =perf_evlist__alloc_mmap (evlist, false);
@@ -1060,7 +1060,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages) { -return perf_evlist__mmap_ex (evlist, pages,0 , false); +return perf_evlist__mmap_ex (evlist, pages,0 , false,0 ); }int perf_evlist__create_maps (struct perf_evlist *evlist,struct target *target)
tools/perf/util/evlist.h +1 -1
@@ -162,7 +162,7 @@ unsigned long perf_event_mlock_kb_in_pages(void);int perf_evlist__mmap_ex (struct perf_evlist *evlist,unsigned int pages,unsigned int auxtrace_pages, -bool auxtrace_overwrite); +bool auxtrace_overwrite,int nr_cblocks);int perf_evlist__mmap (struct perf_evlist *evlist,unsigned int pages);void perf_evlist__munmap (struct perf_evlist *evlist);
tools/perf/util/mmap.c +145 -1
160 lines not on this page · raw message
tools/perf/util/mmap.h +25 -1
@@ -6,9 +6,13 @@#include <linux/types.h> #include <linux/ring_buffer.h> #include <stdbool.h> +#ifdef HAVE_AIO_SUPPORT +#include <aio.h> +#endif #include "auxtrace.h" #include "event.h" +struct aiocb ;/** * struct perf_mmap - perf's ring buffer mmap details *
@@ -26,6 +30,14 @@ struct perf_mmap {bool overwrite;struct auxtrace_mmap auxtrace_mmap;char event_copy[PERF_SAMPLE_MAX_SIZE ]__aligned(8) ; +#ifdef HAVE_AIO_SUPPORT +struct { +void **data; +struct aiocb *cblocks; +struct aiocb **aiocb; +int nr_cblocks; + } aio; +#endif };/*
@@ -57,7 +69,7 @@ enum bkw_mmap_state { };struct mmap_params { -int prot, mask; +int prot, mask, nr_cblocks;struct auxtrace_mmap_params auxtrace_mp; };
@@ -85,6 +97,18 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map);int perf_mmap__push (struct perf_mmap *md,void *to,int push (struct perf_mmap *map,void *to,void *buf,size_t size)); +#ifdef HAVE_AIO_SUPPORT +int perf_mmap__aio_push (struct perf_mmap *md,void *to,int idx, +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off), +off_t *off); +#else +static inline int perf_mmap__aio_push (struct perf_mmap *md__maybe_unused ,void *to__maybe_unused ,int idx__maybe_unused , +int push (void *to,struct aiocb *cblock,void *buf,size_t size,off_t off)__maybe_unused , +off_t *off__maybe_unused ) +{ +return 0 ; +} +#endif size_t perf_mmap__mmap_len (struct perf_mmap *map);
Namhyung Kim
maintainerHi,
Quoted 45 lines · Jiri Olsa
Quoted 38 lines · Alexey Budankov
Currently in record mode the tool implements trace writing serially. The algorithm loops over mapped per-cpu data buffers and stores ready data chunks into a trace file using
write()system call.At some circumstances the kernel may lack free space in a buffer because the other buffer's half is not yet written to disk due to some other buffer's data writing by the tool at the moment.
Thus serial trace writing implementation may cause the kernel to loose profiling data and that is what observed when profiling highly parallel CPU bound workloads on machines with big number of cores.
Experiment with profiling matrix multiplication code executing 128 threads on Intel Xeon Phi (KNM) with 272 cores, like below, demonstrates data loss metrics value of 98%:
/usr/bin/time perf record -o /tmp/perf-ser.data -a -N -B -T -R -g \ --call-graph dwarf,1024 --user-regs=IP,SP,BP --switch-events \ -e cycles,instructions,ref-cycles,software/period=1,name=cs,config=0x3/Duk -- \ matrix.gccData loss metrics is the ratio lost_time/elapsed_time where
lost_timeis the sum of time intervals containingPERF_RECORD_LOSTrecords andelapsed_timeis the elapsed application run time under profiling.Applying asynchronous trace streaming thru Posix AIO API [1] lowers data loss metrics value providing 2x improvement (from 98% to ~1%)
Asynchronous trace streaming is currently limited to glibc linkage. musl libc [5] also provides Posix AIO API implementation, however the patchkit is not tested with it. There may be other libc libraries linked by Perf tool that currently lack Posix AIO API support [2], [3], [4] so
NO_AIOdefine may be used to limit Perf tool binary to serial streaming only.Quoted 5 lines
---
Alexey Budankov (3):
perf util: map data buffer for preserving collected data perf record: enable asynchronous trace writing perf record: extend trace writing to multi AIO
Quoted 6 lines
FYI I was rebasing my threads branch on top of this and first 2 won't apply anymore on Arnaldo's perf/core
Arnaldo,
could we get this merged soon? the world around is moving fast and we don't want 20th revision on this ;-)
I think I gave my ack to this already too.
Thanks,
Namhyung