[libcamera-devel] [PATCH v2 1/1] Use tracing with perfetto in ChromeOS
Harvey Yang
chenghaoyang at chromium.org
Fri Jul 22 14:00:28 CEST 2022
As ChromeOS is using perfetto (project named as CrOSetto). When ChromeOS
uses libcamera, it should use perfetto to collect traces instead of
lttng.
Signed-off-by: Harvey Yang <chenghaoyang at chromium.org>
---
Documentation/guides/tracing.rst | 114 ++++++++++++++----
include/libcamera/internal/tracepoints.h.in | 37 +++++-
.../internal/tracepoints/meson.build | 25 ++--
.../internal/tracepoints/pipeline.perfetto | 10 ++
.../internal/tracepoints/request.perfetto | 30 +++++
meson.build | 7 +-
src/android/cros/camera3_hal.cpp | 5 +
src/android/cros/meson.build | 1 +
src/libcamera/meson.build | 14 ++-
src/libcamera/pipeline_perfetto.cpp | 24 ++++
src/libcamera/request_perfetto.cpp | 73 +++++++++++
src/libcamera/tracepoints.cpp | 11 ++
12 files changed, 312 insertions(+), 39 deletions(-)
create mode 100644 include/libcamera/internal/tracepoints/pipeline.perfetto
create mode 100644 include/libcamera/internal/tracepoints/request.perfetto
create mode 100644 src/libcamera/pipeline_perfetto.cpp
create mode 100644 src/libcamera/request_perfetto.cpp
diff --git a/Documentation/guides/tracing.rst b/Documentation/guides/tracing.rst
index ae960d85..53d6232e 100644
--- a/Documentation/guides/tracing.rst
+++ b/Documentation/guides/tracing.rst
@@ -16,33 +16,50 @@ at periodic points in time. This can be done with other tools such as
callgrind, perf, gprof, etc., without modification to the application,
and is out of scope for this guide.
+Library: Perfetto vs lttng-ust
+---------
+
+To integrate with CrOS tracing infrastructure, which uses perfetto (or called
+CrOSetto in CrOS), we implement the tracepoint macros (will be described below)
+with two different libraries: CrOS with perfetto, and the rest with lttng-ust.
+
Compiling
---------
-To compile libcamera with tracing support, it must be enabled through the
-meson ``tracing`` option. It depends on the lttng-ust library (available in the
-``liblttng-ust-dev`` package for Debian-based distributions).
-By default the tracing option in meson is set to ``auto``, so if
-liblttng is detected, it will be enabled by default. Conversely, if the option
-is set to disabled, then libcamera will be compiled without tracing support.
+To compile libcamera with perfetto support in CrOS, it must be enabled through
+the meson ``tracing`` option. In CrOS, it depends on the perfetto library,
+which is by default available in CrOS; In the rest, it depends on the lttng-ust
+library (available in the ``liblttng-ust-dev`` package for Debian-based
+distributions).
+By default the tracing option in meson is set to ``auto``, so if the library is
+detected, it will be enabled by default. Conversely, if the option is set to
+disabled, then libcamera will be compiled without tracing support.
Defining tracepoints
--------------------
libcamera already contains a set of tracepoints. To define additional
-tracepoints, create a file
-``include/libcamera/internal/tracepoints/{file}.tp``, where ``file`` is a
-reasonable name related to the category of tracepoints that you wish to
-define. For example, the tracepoints file for the Request object is called
-``request.tp``. An entry for this file must be added in
-``include/libcamera/internal/tracepoints/meson.build``.
-
-In this tracepoints file, define your tracepoints `as mandated by lttng
+tracepoints, create two files ``{file}.tp`` and ``{file}.perfetto``, for lttng
+and perfetto respectively, under ``include/libcamera/internal/tracepoints/``,
+and the perfetto implementation file ``src/libcamera/{file}_perfetto.cpp``,
+where ``file`` is a reasonable name related to the category of tracepoints that
+you wish to define. For example, the tracepoints files for the Request object is
+called ``request.tp`` and ``request.perfetto``. Entries for the files must be
+added in ``include/libcamera/internal/tracepoints/meson.build``.
+
+In the perfetto tracepoints files, declare the tracepoint functions in
+``{file}.perfetto``, and define them in ``{file}_perfetto.cpp``, `as mandated
+by perfetto <https://perfetto.dev/docs/instrumentation/track-events>`_.
+Currently the only enabled perfetto::Category is ``libcamera``. If you intend to
+use another category, remember to define it in
+``include/libcamera/internal/tracepoints.h.in``, and enable it when collecting
+traces.
+
+In the lttng tracepoints file, define your tracepoints `as mandated by lttng
<https://lttng.org/man/3/lttng-ust>`_. The header boilerplate must *not* be
included (as it will conflict with the rest of our infrastructure), and
only the tracepoint definitions (with the ``TRACEPOINT_*`` macros) should be
included.
-
All tracepoint providers shall be ``libcamera``. According to lttng, the
tracepoint provider should be per-project; this is the rationale for this
decision. To group tracepoint events, we recommend using
@@ -68,9 +85,9 @@ Then to use the tracepoint:
``LIBCAMERA_TRACEPOINT({tracepoint_event}, args...)``
-This macro must be used, as opposed to lttng's macros directly, because
-lttng is an optional dependency of libcamera, so the code must compile and run
-even when lttng is not present or when tracing is disabled.
+This macro must be used, as opposed to perfetto's/lttng's macros directly,
+because tracing support is optional of libcamera, so the code must compile and
+run even when perfetto/lttng is not present or when tracing is disabled.
The tracepoint provider name, as declared in the tracepoint definition, is not
included in the parameters of the tracepoint.
@@ -86,7 +103,7 @@ and when the pipeline handler receives the corresponding response from the IPA,
respectively. These are the tracepoints that our sample analysis script
(see "Analyzing a trace") scans for when computing statistics on IPA call time.
-Using tracepoints (from an application)
+Using lttng tracepoints (from an application)
---------------------------------------
As applications are not part of libcamera, but rather users of libcamera,
@@ -94,13 +111,66 @@ applications should seek their own tracing mechanisms. For ease of tracing
the application alongside tracing libcamera, it is recommended to also
`use lttng <https://lttng.org/docs/#doc-tracing-your-own-user-application>`_.
-Using tracepoints (from closed-source IPA)
+Using lttng tracepoints (from closed-source IPA)
------------------------------------------
Similar to applications, closed-source IPAs can simply use lttng on their own,
or any other tracing mechanism if desired.
-Collecting a trace
+Collecting a perfetto trace
+------------------
+
+A trace can be collected with the following steps:
+
+1. Start `traced` if it hasn't been started.
+.. code-block:: bash
+
+ start traced
+
+2. Start a consumer that includes “track_event” data source in the trace
+ config, and “libcamera” category.
+.. code-block:: bash
+
+ perfetto -c - --txt -o /tmp/perfetto-trace \
+ <<EOF
+
+ buffers: {
+ size_kb: 63488
+ fill_policy: DISCARD
+ }
+ buffers: {
+ size_kb: 2048
+ fill_policy: DISCARD
+ }
+ data_sources: {
+ config {
+ name: "track_event"
+ track_event_config {
+ enabled_categories: "libcamera"
+ }
+ }
+ }
+ duration_ms: 10000
+
+ EOF
+
+3. Execute the libcamera behavior you intend to trace during the set duration
+ (10000 ms) in the above example.
+
+4. After the consumer (cmd `perfetto`) is done, you can find the trace result
+ in ``/tmp/perfetto-trace``.
+
+Analyzing a perfetto trace
+-----------------
+
+Follow the `guide <https://perfetto.dev/docs/visualization/perfetto-ui>`_ to
+visualize the trace.
+
+In other words, upload the trace to `Perfetto UI <https://ui.perfetto.dev/>`_,
+where you can check the timeline of tracepoints on each process/thread. You can
+also run SQL queries to do analysis.
+
+Collecting a lttng trace
------------------
A trace can be collected fairly simply from lttng:
@@ -123,7 +193,7 @@ viewed by: ``lttng view -t $PATH_TO_TRACE``, where ``$PATH_TO_TRACE`` is the
path that was printed when the session was created. This is the same path that
is used when analyzing traces programatically, as described in the next section.
-Analyzing a trace
+Analyzing a lttng trace
-----------------
As mentioned above, while an lttng tracing session exists and the trace is not
diff --git a/include/libcamera/internal/tracepoints.h.in b/include/libcamera/internal/tracepoints.h.in
index d0fc1365..d91fadd7 100644
--- a/include/libcamera/internal/tracepoints.h.in
+++ b/include/libcamera/internal/tracepoints.h.in
@@ -9,7 +9,24 @@
#ifndef __LIBCAMERA_INTERNAL_TRACEPOINTS_H__
#define __LIBCAMERA_INTERNAL_TRACEPOINTS_H__
-#if HAVE_TRACING
+#if HAVE_PERFETTO
+
+#include <perfetto/perfetto.h>
+
+PERFETTO_DEFINE_CATEGORIES(
+ perfetto::Category("libcamera")
+ .SetDescription("Events from libcamera"));
+
+#define LIBCAMERA_TRACEPOINT(t_name, ...) \
+LIBCAMERA_TRACE_EVENT_##t_name(__VA_ARGS__)
+
+#define LIBCAMERA_TRACEPOINT_IPA_BEGIN(pipe, func) \
+LIBCAMERA_TRACE_EVENT_ipa_call_begin(#pipe, #func)
+
+#define LIBCAMERA_TRACEPOINT_IPA_END(pipe, func) \
+LIBCAMERA_TRACE_EVENT_ipa_call_end(#pipe, #func)
+
+#elif HAVE_TRACING /* !HAVE_PERFETTO */
#define LIBCAMERA_TRACEPOINT(...) tracepoint(libcamera, __VA_ARGS__)
#define LIBCAMERA_TRACEPOINT_IPA_BEGIN(pipe, func) \
@@ -18,7 +35,7 @@ tracepoint(libcamera, ipa_call_begin, #pipe, #func)
#define LIBCAMERA_TRACEPOINT_IPA_END(pipe, func) \
tracepoint(libcamera, ipa_call_end, #pipe, #func)
-#else
+#else /* HAVE_PERFETTO */
namespace {
@@ -34,12 +51,15 @@ inline void unused([[maybe_unused]] Args&& ...args)
#define LIBCAMERA_TRACEPOINT_IPA_BEGIN(pipe, func)
#define LIBCAMERA_TRACEPOINT_IPA_END(pipe, func)
-#endif /* HAVE_TRACING */
+#endif /* HAVE_PERFETTO */
#endif /* __LIBCAMERA_INTERNAL_TRACEPOINTS_H__ */
+#if HAVE_PERFETTO
+
+#include <perfetto/perfetto.h>
-#if HAVE_TRACING
+#elif HAVE_TRACING
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER libcamera
@@ -52,10 +72,15 @@ inline void unused([[maybe_unused]] Args&& ...args)
#include <lttng/tracepoint.h>
-{{source}}
#endif /* INCLUDE_LIBCAMERA_INTERNAL_TRACEPOINTS_TP_H */
#include <lttng/tracepoint-event.h>
-#endif /* HAVE_TRACING */
+#endif /* HAVE_PERFETTO */
+
+#if HAVE_PERFETTO || HAVE_TRACING
+
+{{source}}
+
+#endif /* HAVE_PERFETTO || HAVE_TRACING */
diff --git a/include/libcamera/internal/tracepoints/meson.build b/include/libcamera/internal/tracepoints/meson.build
index d9b2fca5..ff5aece6 100644
--- a/include/libcamera/internal/tracepoints/meson.build
+++ b/include/libcamera/internal/tracepoints/meson.build
@@ -1,12 +1,19 @@
# SPDX-License-Identifier: CC0-1.0
-# enum files must go first
-tracepoint_files = files([
- 'buffer_enums.tp',
- 'request_enums.tp',
-])
+if get_option('android').enabled() and get_option('android_platform') == 'cros'
+ tracepoint_files = files([
+ 'pipeline.perfetto',
+ 'request.perfetto',
+ ])
+else
+ # enum files must go first
+ tracepoint_files = files([
+ 'buffer_enums.tp',
+ 'request_enums.tp',
+ ])
-tracepoint_files += files([
- 'pipeline.tp',
- 'request.tp',
-])
+ tracepoint_files += files([
+ 'pipeline.tp',
+ 'request.tp',
+ ])
+endif
diff --git a/include/libcamera/internal/tracepoints/pipeline.perfetto b/include/libcamera/internal/tracepoints/pipeline.perfetto
new file mode 100644
index 00000000..5f45295e
--- /dev/null
+++ b/include/libcamera/internal/tracepoints/pipeline.perfetto
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * pipeline.tp - Tracepoints for pipelines
+ */
+
+void LIBCAMERA_TRACE_EVENT_ipa_call_begin(const char *pipe, const char *func);
+
+void LIBCAMERA_TRACE_EVENT_ipa_call_end(const char *pipe, const char *func);
diff --git a/include/libcamera/internal/tracepoints/request.perfetto b/include/libcamera/internal/tracepoints/request.perfetto
new file mode 100644
index 00000000..fd6a42a4
--- /dev/null
+++ b/include/libcamera/internal/tracepoints/request.perfetto
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * request.tp - Tracepoints for the request object
+ */
+
+#include <libcamera/internal/request.h>
+
+#include <libcamera/framebuffer.h>
+
+void LIBCAMERA_TRACE_EVENT_request(libcamera::Request *req);
+
+void LIBCAMERA_TRACE_EVENT_request_construct(libcamera::Request *req);
+
+void LIBCAMERA_TRACE_EVENT_request_destroy(libcamera::Request *req);
+
+void LIBCAMERA_TRACE_EVENT_request_reuse(libcamera::Request *req);
+
+void LIBCAMERA_TRACE_EVENT_request_queue(libcamera::Request *req);
+
+void LIBCAMERA_TRACE_EVENT_request_device_queue(libcamera::Request *req);
+
+void LIBCAMERA_TRACE_EVENT_request_complete(libcamera::Request::Private *req);
+
+void LIBCAMERA_TRACE_EVENT_request_cancel(libcamera::Request::Private *req);
+
+void LIBCAMERA_TRACE_EVENT_request_complete_buffer(
+ libcamera::Request::Private *req,
+ libcamera::FrameBuffer * buf);
diff --git a/meson.build b/meson.build
index 29d8542d..434540e1 100644
--- a/meson.build
+++ b/meson.build
@@ -125,7 +125,11 @@ libcamera_includes = include_directories('include')
py_modules = []
# Libraries used by multiple components
-liblttng = cc.find_library('lttng-ust', required : get_option('tracing'))
+libperfetto = dependency('perfetto', required : get_option('tracing').enabled()
+ and get_option('android').enabled()
+ and get_option('android_platform') == 'cros')
+liblttng = cc.find_library('lttng-ust', required : get_option('tracing').enabled()
+ and not libperfetto.found())
# Pipeline handlers
#
@@ -176,6 +180,7 @@ py_mod.find_installation('python3', modules: py_modules)
summary({
'Enabled pipelines': pipelines,
'Enabled IPA modules': ipa_modules,
+ 'Perfetto support': perfetto_enabled,
'Tracing support': tracing_enabled,
'Android support': android_enabled,
'GStreamer support': gst_enabled,
diff --git a/src/android/cros/camera3_hal.cpp b/src/android/cros/camera3_hal.cpp
index fb863b5f..2fbd7f14 100644
--- a/src/android/cros/camera3_hal.cpp
+++ b/src/android/cros/camera3_hal.cpp
@@ -7,10 +7,15 @@
#include <cros-camera/cros_camera_hal.h>
+#include "libcamera/internal/tracepoints.h"
#include "../camera_hal_manager.h"
static void set_up([[maybe_unused]] cros::CameraMojoChannelManagerToken *token)
{
+ perfetto::TracingInitArgs args;
+ args.backends |= perfetto::kSystemBackend;
+ perfetto::Tracing::Initialize(args);
+ perfetto::TrackEvent::Register();
}
static void tear_down()
diff --git a/src/android/cros/meson.build b/src/android/cros/meson.build
index 35995dd8..68f2bd9e 100644
--- a/src/android/cros/meson.build
+++ b/src/android/cros/meson.build
@@ -9,5 +9,6 @@ android_hal_sources += files([
])
android_deps += dependency('libcros_camera')
+android_deps += dependency('perfetto')
android_cpp_args += ['-DOS_CHROMEOS']
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 26912ca1..39a55a17 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -71,11 +71,22 @@ if libgnutls.found()
config_h.set('HAVE_GNUTLS', 1)
endif
-if liblttng.found()
+if libperfetto.found()
+ perfetto_enabled = true
+ tracing_enabled = false
+ config_h.set('HAVE_PERFETTO', 1)
+ libcamera_sources += [
+ 'pipeline_perfetto.cpp',
+ 'request_perfetto.cpp',
+ 'tracepoints.cpp',
+ ]
+elif liblttng.found()
+ perfetto_enabled = false
tracing_enabled = true
config_h.set('HAVE_TRACING', 1)
libcamera_sources += files(['tracepoints.cpp'])
else
+ perfetto_enabled = false
tracing_enabled = false
endif
@@ -125,6 +136,7 @@ libcamera_deps = [
libdl,
libgnutls,
liblttng,
+ libperfetto,
libudev,
]
diff --git a/src/libcamera/pipeline_perfetto.cpp b/src/libcamera/pipeline_perfetto.cpp
new file mode 100644
index 00000000..07b82ffd
--- /dev/null
+++ b/src/libcamera/pipeline_perfetto.cpp
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * pipeline.tp - Tracepoints for pipelines
+ */
+
+#include "libcamera/internal/tracepoints.h"
+
+void LIBCAMERA_TRACE_EVENT_ipa_call_begin(const char *pipe, const char *func)
+{
+ // TODO: Consider TRACE_EVENT_BEGIN
+ TRACE_EVENT("libcamera", "ipa_call_begin",
+ "pipeline_name", pipe,
+ "function_name", func);
+}
+
+void LIBCAMERA_TRACE_EVENT_ipa_call_end(const char *pipe, const char *func)
+{
+ // TODO: Consider TRACE_EVENT_END
+ TRACE_EVENT("libcamera", "ipa_call_end",
+ "pipeline_name", pipe,
+ "function_name", func);
+}
diff --git a/src/libcamera/request_perfetto.cpp b/src/libcamera/request_perfetto.cpp
new file mode 100644
index 00000000..2cfff28e
--- /dev/null
+++ b/src/libcamera/request_perfetto.cpp
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * request.tp - Tracepoints for the request object
+ */
+
+#include <libcamera/framebuffer.h>
+
+#include "libcamera/internal/request.h"
+#include "libcamera/internal/tracepoints.h"
+
+void LIBCAMERA_TRACE_EVENT_request(libcamera::Request *req)
+{
+ TRACE_EVENT("libcamera", "request",
+ "request_ptr", reinterpret_cast<uintptr_t>(req),
+ "cookie", req->cookie(),
+ "status", req->status()); // TODO
+}
+
+void LIBCAMERA_TRACE_EVENT_request_construct(libcamera::Request *req)
+{
+ TRACE_EVENT("libcamera", "request_construct",
+ "request_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_destroy(libcamera::Request *req)
+{
+ TRACE_EVENT("libcamera", "request_destroy",
+ "request_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_reuse(libcamera::Request *req)
+{
+ TRACE_EVENT("libcamera", "request_reuse",
+ "request_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_queue(libcamera::Request *req)
+{
+ TRACE_EVENT("libcamera", "request_queue",
+ "request_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_device_queue(libcamera::Request *req)
+{
+ TRACE_EVENT("libcamera", "request_device_queue",
+ "request_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_complete(libcamera::Request::Private *req)
+{
+ TRACE_EVENT("libcamera", "request_complete",
+ "request_private_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_cancel(libcamera::Request::Private *req)
+{
+ TRACE_EVENT("libcamera", "request_cancel",
+ "request_private_ptr", reinterpret_cast<uintptr_t>(req));
+}
+
+void LIBCAMERA_TRACE_EVENT_request_complete_buffer(
+ libcamera::Request::Private *req,
+ libcamera::FrameBuffer *buf)
+{
+ TRACE_EVENT("libcamera", "request_complete_buffer",
+ "request_private_ptr", reinterpret_cast<uintptr_t>(req),
+ "cookie", req->_o<libcamera::Request>()->cookie(),
+ "status", req->_o<libcamera::Request>()->status(), // TODO
+ "buffer_ptr", reinterpret_cast<uintptr_t>(buf),
+ "buffer_status", buf->metadata().status); // TODO
+}
diff --git a/src/libcamera/tracepoints.cpp b/src/libcamera/tracepoints.cpp
index 0173b75a..a07ea531 100644
--- a/src/libcamera/tracepoints.cpp
+++ b/src/libcamera/tracepoints.cpp
@@ -4,7 +4,18 @@
*
* tracepoints.cpp - Tracepoints with lttng
*/
+
+#if HAVE_PERFETTO
+
+#include "libcamera/internal/tracepoints.h"
+
+PERFETTO_TRACK_EVENT_STATIC_STORAGE();
+
+#else
+
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
#include "libcamera/internal/tracepoints.h"
+
+#endif /* HAVE_PERFETTO */
--
2.37.1.359.gd136c6c3e2-goog
More information about the libcamera-devel
mailing list