perfetto: hold StatusOr's value in a union (#8126) **Summary** `StatusOr<T>` holds its value in a union rather than a `std::optional`, and `ASSIGN_OR_RETURN` moves an error out rather than copying it. Stacked on #8121. **Why** The optional's "has value" flag duplicated what the status already says. It cost a byte plus padding in every StatusOr, and a check on every access. `ASSIGN_OR_RETURN` also copied the error before returning it. Since #8120 holds errors on the heap, that copy was an allocation for every error propagated. **Changes** - The value lives in an anonymous union, as `std::optional` keeps its own, and exists exactly while the status is ok. - A value is only constructed where there was none, and only destroyed where there will be none. One value replaces another by `T`'s own assignment, so no object is ever replaced in place. This needs no casts and no `std::launder`. - A moved-from StatusOr keeps its status, and so keeps its moved-from value, which it still destroys. - `StatusOr<const T>` is no longer allowed: constructing into a const member would need a cast. Its two uses, `StatusOr<const char* const>` in the winscope plugins, now return `StatusOr<const char*>`. - `status() &&` moves an error out, and leaves the value of an ok StatusOr in place. `ASSIGN_OR_RETURN` returns through it. **Binary size** Stripped, against #8121: `trace_processor_shell` -40 KB, `perfetto` -0.9 KB, `libperfetto.so` -0.6 KB. **Benchmarks** Both builds alternated three times, pinned to one CPU. | Benchmark | #8121 | this | | | ----------------------- | -------- | -------- | ------ | | BM_StatusOrOkChain | 15.0 ns | 11.8 ns | -21% | | BM_StatusOrErrorChain | 77.2 ns | 53.5 ns | -31% | | BM_StatusOkChain | 4.4 ns | 4.4 ns | | | Others | | | +/-2% | Moving rather than copying the error takes `StatusOr` error propagation below `main` (63.9 ns before the stack). **Testing** - New `StatusOrTest` cases use a type which counts its live objects. They cover copy and move, every assignment between holding a value and holding an error, self-assignment, `status() &&`, and `ASSIGN_OR_RETURN`. - All unit, diff and integration tests pass locally, and the whole Linux clang build compiles.
Perfetto is an open-source suite of SDKs, daemons and tools which use tracing to help developers understand the behaviour of complex systems and root-cause functional and performance issues on client and embedded systems.
It is a production-grade tool that is the default tracing system for the Android operating system and the Chromium browser.
Perfetto is not a single tool, but a collection of components that work together:
Perfetto was designed to be a versatile and powerful tracing system for a wide range of use cases.
ftrace, allowing you to visualize scheduling, syscalls, interrupts, and custom kernel tracepoints on a timeline.chrome://tracing. Use it to debug and root-cause issues in the browser, V8, and Blink.We‘ve designed our documentation to guide you to the right information as quickly as possible, whether you’re a newcomer to performance analysis or an experienced developer.
New to tracing? If you're unfamiliar with concepts like tracing and profiling, start here:
Ready to dive in? Our “Getting Started” guide is the main entry point for all users. It will help you find the right tutorials and documentation for your specific needs:
Want the full overview? For a comprehensive look at what Perfetto is, why it's useful, and who uses it, see our main documentation page:
For users interested in the Debian distribution of Perfetto, the official source of truth and packaging efforts are maintained at Debian Perfetto Salsa Repository
Have questions? Need help?
We follow Google's Open Source Community Guidelines.