ftrace: write "last read event timestamp" to assist parsing of ring buffer traces

-- Problem: --

Ftrace data is recorded per-cpu, grouping series of events from a given
per-cpu kernel buffer into an ftrace_event_bundle packet. When a
perfetto trace uses RING_BUFFER, the oldest trace packet wrapping can
leave us with very imbalanced per-cpu state as entire bundles of events
are overwritten.

This in turn is problematic when interpreting certain ftrace events
requires pairing them up (e.g. slice begin/end) or otherwise tracking
transitions, and the related events are not constrained to a single cpu.

Consider the following scenario of a {begin, end} pair of events that
represent a tracing slice. Assuming there's one bundle per cpu:
  cpu0: [e...E..e..e]    <- bundle
             ^event end
  cpu1: [.B.....e..eee.] <- bundle
          ^event begin

It is possible for us to observe cpu1's events, while cpu0's have been
overwritten in the ring buffer. In such a case, a naive parsing of all
events would conclude that the slice began and never ended.

The above is just the simplest example, things get more complicated once
we start reasoning about different kernel tracing bandwidth across cpus
and userspace transcoding breaking up reads in terms of KBs of tracing
data instead of timestamps.

-- Solution: --

Since traced_probes is the exclusive reader of per-cpu kernel ring
buffers, it knows the latest "consumed" event's timestamp for that
buffer. By putting this timestamp into the *next* bundle, we're
recording that "all ftrace data in this bundle is guaranteed to cover
the time range starting from where the last read stopped".

Example sketch:
  Initial state of the per-cpu ring buffers:
    cpu0: .eeee.e.
    cpu1: ee...ee.
    cpu2: ..ee.ee.
  After a read pass, some data has been consumed from each buf:
    cpu0: XXXee.e.
    cpu1: XXXXXXe.
    cpu2: XXXe.ee.
  Now, on the *next* bundle per cpu, we'll be emitting how far the
  consumed ('X') area extends.

In turn, from the trace_processor perspective, we can drop events until
the earliest timestamp covered by all per-cpu event bundles. This is
the maximum of all per-cpu "valid from" timestamps.

Bug: 192586066
Change-Id: Iebc6952a2f2a6a399b8cde64f210e28a69c04111
9 files changed
tree: 68065660c3a59012c317ff08125967b8f8527f39
  1. .github/
  2. bazel/
  3. build_overrides/
  4. buildtools/
  5. debian/
  6. docs/
  7. examples/
  8. gn/
  9. include/
  10. infra/
  11. protos/
  12. python/
  13. src/
  14. test/
  15. third_party/
  16. tools/
  17. ui/
  18. .clang-format
  19. .clang-tidy
  20. .git-blame-ignore-revs
  21. .gitattributes
  22. .gitignore
  23. .gn
  24. .style.yapf
  25. Android.bp
  26. Android.bp.extras
  27. BUILD
  28. BUILD.extras
  29. BUILD.gn
  30. CHANGELOG
  31. codereview.settings
  32. DIR_METADATA
  33. heapprofd.rc
  34. LICENSE
  35. meson.build
  36. METADATA
  37. MODULE_LICENSE_APACHE2
  38. OWNERS
  39. perfetto.rc
  40. PerfettoIntegrationTests.xml
  41. persistent_cfg.pbtxt
  42. PRESUBMIT.py
  43. README.chromium
  44. README.md
  45. TEST_MAPPING
  46. traced_perf.rc
  47. WATCHLISTS
  48. WORKSPACE
README.md

Perfetto - System profiling, app tracing and trace analysis

Perfetto is a production-grade open-source stack for performance instrumentation and trace analysis. It offers services and libraries and for recording system-level and app-level traces, native + java heap profiling, a library for analyzing traces using SQL and a web-based UI to visualize and explore multi-GB traces.

See https://perfetto.dev/docs or the /docs/ directory for documentation.