From d9496c7979c392534ddcd45080c9968cd3820c2e Mon Sep 17 00:00:00 2001 From: Daniel Rossier <205909+daniel-rossier@users.noreply.github.com> Date: Mon, 17 Jun 2024 22:56:51 +0200 Subject: [PATCH] First CI action for performance check of LVGL code base with SO3 (#4122) Co-authored-by: Anthony I. Jaccard Co-authored-by: AnthoJack --- .github/auto-comment.yml | 12 -- .github/workflows/check_perf.yml | 54 +++++++++ docs/cicd/LvglCheckPerfAction.png | Bin 0 -> 54990 bytes docs/cicd/index.rst | 89 ++++++++++++++ docs/index.rst | 1 + scripts/last_success_run_id.py | 17 +++ scripts/perf_report.py | 189 ++++++++++++++++++++++++++++++ tests/perf/CMakeLists.txt | 12 ++ tests/perf/func_thresholds.txt | 3 + tests/perf/prof_test.c | 52 ++++++++ tests/perf/prof_test_p.c | 11 ++ tests/perf/prof_test_p.h | 4 + 12 files changed, 432 insertions(+), 12 deletions(-) delete mode 100644 .github/auto-comment.yml create mode 100644 .github/workflows/check_perf.yml create mode 100644 docs/cicd/LvglCheckPerfAction.png create mode 100644 docs/cicd/index.rst create mode 100755 scripts/last_success_run_id.py create mode 100644 scripts/perf_report.py create mode 100644 tests/perf/CMakeLists.txt create mode 100644 tests/perf/func_thresholds.txt create mode 100644 tests/perf/prof_test.c create mode 100644 tests/perf/prof_test_p.c create mode 100644 tests/perf/prof_test_p.h diff --git a/.github/auto-comment.yml b/.github/auto-comment.yml deleted file mode 100644 index a141fb548..000000000 --- a/.github/auto-comment.yml +++ /dev/null @@ -1,12 +0,0 @@ -# Comment to a new issue. -pullRequestOpened: | - Thank you for raising your pull request. - - To ensure that all licensing criteria is met all repositories of the LVGL project apply a process called DCO (Developer's Certificate of Origin). - - The text of DCO can be read here: https://developercertificate.org/ - For a more detailed description see the [Documentation](https://docs.lvgl.io/latest/en/html/contributing/index.html#developer-certification-of-origin-dco) site. - - By contributing to any repositories of the LVGL project you state that your contribution corresponds with the DCO. - - No further action is required if your contribution fulfills the DCO. If you are not sure about it feel free to ask us in a comment. diff --git a/.github/workflows/check_perf.yml b/.github/workflows/check_perf.yml new file mode 100644 index 000000000..7980a6479 --- /dev/null +++ b/.github/workflows/check_perf.yml @@ -0,0 +1,54 @@ + +name: SO3-LVGL Performance check +on: [push, pull_request, workflow_dispatch] +jobs: + run_perf_test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + path: 'lvgl' + + - name: SO3-LVGL building the Docker image + run: | + wget https://raw.githubusercontent.com/smartobjectoriented/so3/40-expand-and-document-lvgl-perf-tests/Dockerfile.lvgl + docker build . -f Dockerfile.lvgl -t so3/virt64 --platform linux/amd64 --build-arg SO3_BRANCH=40-expand-and-document-lvgl-perf-tests + + - name: SO3-LVL Running containerized performance check app + run: docker run --privileged -v $PWD:/host -v /dev:/dev so3/virt64 + + - name: Store performance data as artifact + uses: actions/upload-artifact@v4 + with: + name: performance_data + path: perf_check*.txt + + - name: Find previous successful run + id: prev_success_run + run: | + wget ${{ github.api_url }}/repos/${{ github.repository }}/actions/workflows/52959381/runs + echo "ID=$(python3 lvgl/scripts/last_success_run_id.py runs)" >> "$GITHUB_OUTPUT" + + - name: Retrieve previous successful run performance data + if: ${{ steps.prev_success_run.outputs.ID != 0 }} + uses: actions/download-artifact@v4 + with: + name: performance_data + path: prev_performance_data + run-id: ${{ steps.prev_success_run.outputs.ID }} + continue-on-error: true + + - name: Performance report generation + id: perf_report + run: | + python3 lvgl/scripts/perf_report.py perf_check*.txt lvgl/tests/perf/func_thresholds.txt prev_performance_data/perf_check*.txt | tee perf_report.txt + python_return=${PIPESTATUS[0]} + echo "Python script returned $python_return" + exit $python_return + + - name: Store performance report as artifact + if: success() || failure() + uses: actions/upload-artifact@v4 + with: + name: performance_report + path: perf_report.txt diff --git a/docs/cicd/LvglCheckPerfAction.png b/docs/cicd/LvglCheckPerfAction.png new file mode 100644 index 0000000000000000000000000000000000000000..013e2bc70574482957609699bc01e52ea7fff3e5 GIT binary patch literal 54990 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 z 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 D(6t}s literal 0 HcmV?d00001 diff --git a/docs/cicd/index.rst b/docs/cicd/index.rst new file mode 100644 index 000000000..06f02c4f0 --- /dev/null +++ b/docs/cicd/index.rst @@ -0,0 +1,89 @@ +.. _cicd: + +============ +CICD +============ + +LVGL uses github actions to perform various operations on the code + + +Main Actions +------------ + +- Micropython build +- C/C++ build +- Documentation build +- PlatformIO publishing +- Release +- Performance test + +LVGL Performance Test +--------------------- + +SO3 is used to check the performance of LVGL. This workflow behaves as shown in this diagram: + +.. image:: LvglCheckPerfAction.png + +The actions are described below + +#. Retrieve the LVGL commit that triggered the action and store it in a "lvgl_base" folder for the dockerfile to use +#. Retrieve "Dockerfile.lvgl" from the SO3 repository and build the docker image +#. Run the docker image to generate the performance data (function execution times) +#. Store the performance data as an artifact for future reference +#. Find previous successful action run and recover the performance data from it +#. Process the performance data and compare it to previous executions and set thresholds to detect performance issues +#. Create an artifact in the form of a log file that shows the output of the regression test + +The image is ran using two volumes: One that redirects the container's "/host" folder to the workflow's working directory and one that allows the container to access the workflow's devices (in the /dev folder) as his own + +The workflow is setup to run when +* Commits are pushed to LVGL's repo +* A pull request is created +* Launched from another workflow + +Dockerfile +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +LVGL's check_perf workflow uses the Dockerfile.lvgl found at the root of this repository to create the image that runs SO3 on qemu and executes the tests. The dockerfile does the following: + +#. Creates an Alpine image and installs all the necessary tools (like gcc and qemu) +#. Recovers SO3's main branch in the root ("/") folder +#. Empties the "*/so3/usr/lib/lvgl*" folder and replaces its content with the LVGL repo to be tested (The LVGL code should be in a "lvgl_base" folder) +#. Patches SO3 so it executes the *prof_test* application instead of the shell at launch +#. Builds U-boot and the SO3 kernel +#. Imports the *prof_test* (*test/perf* folder from LVGL) application into SO3's userspace and builds the userspace +#. Sets up the image so it exposes the port 1234 when ran and executes "./st" + +Performance data files +^^^^^^^^^^^^^^^^^^^^^^^ + +The files used to report on the execution times of the profiled functions and have the same format: + +* 1 header line with no defined format (ignored by the script) +* N lines with function data following the "[parent/] [(info)] |