diff --git a/Dockerfile b/Dockerfile index 0bd51ac6f..20d2d033e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -84,22 +84,21 @@ RUN apt-get update && \ apt-get install -y --no-install-recommends \ git \ ca-certificates \ - && \ - if [ "$(uname -m)" != "aarch64" ]; then \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - curl \ - build-essential \ - iperf llvm-9-dev \ - libclang-9-dev \ - cmake \ - python3 \ - flex \ - libfl-dev \ - bison \ - libelf-dev \ - libz-dev \ - liblzma-dev; \ - fi + && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + curl \ + build-essential \ + iperf \ + llvm-9-dev \ + libclang-9-dev \ + cmake \ + python3 \ + flex \ + libfl-dev \ + bison \ + libelf-dev \ + libz-dev \ + liblzma-dev; # bcc helpers FROM bcc-builder-base AS bcc-helpers @@ -118,15 +117,12 @@ FROM bcc-builder-base AS bcc-builder WORKDIR /tmp COPY ./scripts/libunwind_build.sh . -RUN if [ "$(uname -m)" = "aarch64" ]; then \ - exit 0; \ - fi && \ - ./libunwind_build.sh +RUN ./libunwind_build.sh WORKDIR /bcc COPY ./scripts/pyperf_build.sh . -RUN ./pyperf_build.sh +RUN ./pyperf_build.sh container # phpspy FROM ubuntu${PHPSPY_BUILDER_UBUNTU} AS phpspy-builder diff --git a/README.md b/README.md index 12e67ed55..be78ea0d9 100644 --- a/README.md +++ b/README.md @@ -395,7 +395,7 @@ The runtime stacks are then merged into the data collected by `perf`, substituti | perf (native, Golang, ...) | :heavy_check_mark: | :heavy_check_mark: | | Java (async-profiler) | :heavy_check_mark: | :heavy_check_mark: | | Python (py-spy) | :heavy_check_mark: | :heavy_check_mark: | -| Python (PyPerf eBPF) | :heavy_check_mark: | :x: | +| Python (PyPerf eBPF) | :heavy_check_mark: | :heavy_check_mark: (experimental) | | Ruby (rbspy) | :heavy_check_mark: | :heavy_check_mark: | | PHP (phpspy) | :heavy_check_mark: | :heavy_check_mark: (experimental) | | NodeJS (perf) | :heavy_check_mark: | :heavy_check_mark: | diff --git a/gprofiler/profilers/python.py b/gprofiler/profilers/python.py index 1f622c481..0e32796b9 100644 --- a/gprofiler/profilers/python.py +++ b/gprofiler/profilers/python.py @@ -40,7 +40,6 @@ from gprofiler.metadata import application_identifiers from gprofiler.metadata.application_metadata import ApplicationMetadata from gprofiler.metadata.py_module_version import get_modules_versions -from gprofiler.metadata.system_metadata import get_arch from gprofiler.platform import is_linux, is_windows from gprofiler.profilers.profiler_base import ProfilerInterface, SpawningProcessProfilerBase from gprofiler.profilers.registry import ProfilerArgument, register_profiler @@ -295,9 +294,6 @@ def _should_skip_process(self, process: Process) -> bool: # py-spy is like pyspy, it's confusing and I mix between them possible_modes=["auto", "pyperf", "pyspy", "py-spy", "disabled"], default_mode="auto", - # we build pyspy for both, pyperf only for x86_64. - # TODO: this inconsistency shows that py-spy and pyperf should have different Profiler classes, - # we should split them in the future. supported_archs=["x86_64", "aarch64"], supported_windows_archs=["AMD64"], profiler_mode_argument_help="Select the Python profiling mode: auto (try PyPerf, resort to py-spy if it fails), " @@ -348,9 +344,9 @@ def __init__( assert python_mode in ("auto", "pyperf", "pyspy"), f"unexpected mode: {python_mode}" - if get_arch() != "x86_64" or is_windows(): + if is_windows(): if python_mode == "pyperf": - logger.warning("PyPerf is supported only on x86_64, falling back to py-spy") + logger.warning("PyPerf is supported only on Linux, falling back to py-spy") python_mode = "pyspy" if python_mode in ("auto", "pyperf"): diff --git a/pyi.Dockerfile b/pyi.Dockerfile index 26c42dda8..bba13a883 100644 --- a/pyi.Dockerfile +++ b/pyi.Dockerfile @@ -125,18 +125,14 @@ USER 1001 FROM ubuntu${PYPERF_BUILDER_UBUNTU} AS bcc-helpers WORKDIR /tmp -RUN if [ "$(uname -m)" = "aarch64" ]; then \ - exit 0; \ - fi && \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - clang-10 \ - libelf-dev \ - make \ - build-essential \ - llvm \ - ca-certificates \ - git +RUN apt-get update && apt-get install -y --no-install-recommends \ + clang-10 \ + libelf-dev \ + make \ + build-essential \ + llvm \ + ca-certificates \ + git COPY --from=perf-builder /bpftool /bpftool @@ -177,53 +173,45 @@ RUN ./python310_build.sh # TODO: copied from the main Dockerfile... but modified a lot. we'd want to share it some day. RUN yum install -y git && yum clean all + WORKDIR /bcc -# these are needed to build PyPerf, which we don't build on Aarch64, hence not installing them here. -RUN if [ "$(uname -m)" = "aarch64" ]; then exit 0; fi; yum install -y \ + +# these are needed to build PyPerf +RUN yum install -y \ curl \ cmake \ patch \ flex \ bison \ - zlib-devel.x86_64 \ + zlib-devel \ xz-devel \ ncurses-devel \ elfutils-libelf-devel && \ yum clean all -RUN if [ "$(uname -m)" = "aarch64" ]; \ - then exit 0; \ - fi && \ - yum install -y centos-release-scl-rh && \ - yum clean all +RUN yum install -y centos-release-scl-rh && yum clean all # mostly taken from https://github.com/iovisor/bcc/blob/master/INSTALL.md#install-and-compile-llvm -RUN if [ "$(uname -m)" = "aarch64" ]; \ - then exit 0; \ - fi && \ - yum install -y devtoolset-8 \ - llvm-toolset-7 \ - llvm-toolset-7-llvm-devel \ - llvm-toolset-7-llvm-static \ - llvm-toolset-7-clang-devel \ - devtoolset-8-elfutils-libelf-devel && \ +# on x86_64, the package is named llvm-toolset-7. on aarch64, it is named llvm-toolset-7.0... +RUN if [ "$(uname -m)" = "aarch64" ]; then v="7.0"; else v="7"; fi; yum install -y devtoolset-8 \ + llvm-toolset-$v \ + llvm-toolset-$v-llvm-devel \ + llvm-toolset-$v-llvm-static \ + llvm-toolset-$v-clang-devel \ + devtoolset-8-elfutils-libelf-devel && \ yum clean all COPY ./scripts/libunwind_build.sh . # hadolint ignore=SC1091 -RUN if [ "$(uname -m)" = "aarch64" ]; then \ - exit 0; \ - fi && \ - source scl_source enable devtoolset-8 && \ +RUN source scl_source enable devtoolset-8 && \ ./libunwind_build.sh +WORKDIR /bcc + COPY ./scripts/pyperf_build.sh . # hadolint ignore=SC1091 -RUN set -e; \ - if [ "$(uname -m)" != "aarch64" ]; then \ - source scl_source enable devtoolset-8 llvm-toolset-7; \ - fi && \ - source ./pyperf_build.sh - +RUN if [ "$(uname -m)" = "aarch64" ]; then v="7.0"; else v="7"; fi && \ + source scl_source enable devtoolset-8 "llvm-toolset-$v" && \ + source ./pyperf_build.sh exe # gProfiler part WORKDIR /app @@ -240,11 +228,13 @@ RUN set -e; \ yum install -y glibc-static zlib-devel.aarch64 && \ yum clean all; \ fi -# needed for aarch64, scons & wheel are needed to build staticx + RUN set -e; \ if [ "$(uname -m)" = "aarch64" ]; then \ ln -s /usr/lib64/python3.10/lib-dynload /usr/lib/python3.10/lib-dynload; \ fi + +# needed for aarch64, scons & wheel are needed to build staticx RUN set -e; \ if [ "$(uname -m)" = "aarch64" ]; then \ python3 -m pip install --no-cache-dir 'wheel==0.37.0' 'scons==4.2.0'; \ @@ -339,9 +329,8 @@ COPY ./scripts/list_needed_libs.sh ./scripts/list_needed_libs.sh # using scl here to get the proper LD_LIBRARY_PATH set # hadolint ignore=SC2046,SC2086 RUN set -e; \ - if [ $(uname -m) != "aarch64" ]; then \ - source scl_source enable devtoolset-8 llvm-toolset-7 ; \ - fi && \ + if [ $(uname -m) = "aarch64" ]; then v="7.0"; else v="7"; fi; \ + source scl_source enable devtoolset-8 "llvm-toolset-$v" && \ LIBS=$(./scripts/list_needed_libs.sh) && \ staticx $LIBS dist/gprofiler dist/gprofiler diff --git a/scripts/bcc_helpers_build.sh b/scripts/bcc_helpers_build.sh index a71043ac8..097e0ef64 100755 --- a/scripts/bcc_helpers_build.sh +++ b/scripts/bcc_helpers_build.sh @@ -5,14 +5,6 @@ # set -euo pipefail -# TODO support aarch64, after we support it in PyPerf -if [ "$(uname -m)" != "x86_64" ]; then - mkdir -p /bpf_get_fs_offset /bpf_get_stack_offset - touch /bpf_get_fs_offset/get_fs_offset - touch /bpf_get_stack_offset/get_stack_offset - exit 0 -fi - LLVM_STRIP=llvm-strip if ! command -v "$LLVM_STRIP" > /dev/null 2>&1 ; then LLVM_STRIP=llvm-strip-10 @@ -20,12 +12,12 @@ fi LIBBPF_MAKE_FLAGS="BPFTOOL=/bpftool CLANG=clang-10 LLVM_STRIP=$LLVM_STRIP CFLAGS=-static" -cd / && git clone -b v0.0.2 --depth=1 --recurse-submodules https://github.com/Jongy/bpf_get_fs_offset.git -cd /bpf_get_fs_offset && git reset --hard 8326d39cf44845d4b643ed4267994afca8ccecb3 +cd / && git clone -b aarch64 --depth=1 --recurse-submodules https://github.com/Jongy/bpf_get_fs_offset.git +cd /bpf_get_fs_offset && git reset --hard 094e93f979308d46dffb8d4ea88823f68d53ba85 # shellcheck disable=SC2086 cd /bpf_get_fs_offset && make $LIBBPF_MAKE_FLAGS -cd / && git clone -b v0.0.3 --depth=1 --recurse-submodules https://github.com/Jongy/bpf_get_stack_offset.git -cd /bpf_get_stack_offset && git reset --hard 54b70ee65708cc8d3d7817277e82376d95205356 +cd / && git clone -b aarch64 --depth=1 --recurse-submodules https://github.com/Jongy/bpf_get_stack_offset.git +cd /bpf_get_stack_offset && git reset --hard d8b77ce6da674c38ad0bb856686fde1e63ad0814 # shellcheck disable=SC2086 cd /bpf_get_stack_offset && make $LIBBPF_MAKE_FLAGS diff --git a/scripts/pyperf_build.sh b/scripts/pyperf_build.sh index 348bd1378..2f577a531 100755 --- a/scripts/pyperf_build.sh +++ b/scripts/pyperf_build.sh @@ -5,17 +5,17 @@ # set -euo pipefail -git clone --depth 1 -b v1.2.6 https://github.com/Granulate/bcc.git && cd bcc && git reset --hard 6a995642d12287f26cbb97edd3d29e62a5fde337 - -# (after clone, because we copy the licenses) -# TODO support aarch64 -if [ "$(uname -m)" != "x86_64" ]; then - mkdir -p /bcc/root/share/bcc/examples/cpp/ - touch /bcc/root/share/bcc/examples/cpp/PyPerf - exit 0 -fi +git clone --depth 1 -b aarch64 https://github.com/Granulate/bcc.git && cd bcc && git reset --hard 846228b6e3f244732783540e3e0b868271902e2d mkdir build cd build -cmake -DPYTHON_CMD=python3 -DINSTALL_CPP_EXAMPLES=y -DCMAKE_INSTALL_PREFIX=/bcc/root .. + +SHARED_ARG="" +# need in aarch64 as mentioned here: https://github.com/iovisor/bcc/issues/3333#issuecomment-803432248 +# container mdoe doesn't want it - we don't have the libs bundled. +# exe mode in x86_64 works fine so I don't change it. +if [ "$(uname -m)" = "aarch64" ] && [ "$1" == "exe" ]; then + SHARED_ARG=" -DENABLE_LLVM_SHARED=1" +fi +cmake -DPYTHON_CMD=python3 -DINSTALL_CPP_EXAMPLES=y -DCMAKE_INSTALL_PREFIX=/bcc/root "$SHARED_ARG" .. make -C examples/cpp/pyperf -j -l VERBOSE=1 install