Skip to content

Add profiler plugin for each platform#15

Merged
sugarmanz merged 16 commits into
mainfrom
profiler-plugin
Jun 29, 2026
Merged

Add profiler plugin for each platform#15
sugarmanz merged 16 commits into
mainfrom
profiler-plugin

Conversation

@tmarmer

@tmarmer tmarmer commented May 8, 2026

Copy link
Copy Markdown
Contributor

This PR adds the ProfilerDevtoolsPlugin, available at the core layer with wrappers on each platform.

  • Tap into each of the core player hooks and collect timing information each time one is called.
    • Each hook call is assigned a ProfileNode which will have the start and end times, using the performance API when avialable, but defaulting to Date.now otherwise.
    • The value of each node is the total duration and is used by the flame-graph asset to determine the width of the bars it displays
    • The name is displayed on the graph and tooltip is displayed on hover
    • The children structure is inferred by when hooks are called, and is only needed for the flame-graph asset to render correctly.
      • Ideally we can group profiling data in a smarter way in the future and replace the current flame-graph with something that can better show the timings.
  • The plugin has a step to transform the profiling data to work with the flame-graph asset by inserting spacers and removing anything with a value of 0
    • The spacers are needed as the asset left-aligns everything relative to its parent so the (work) spacers provide a way to show the reelative timing with which a hook started relative to the its parent
    • Anything with a value of 0 doesn't render anyway so removing those helps group a few spacers to clean up the ui.
  • There is a rawData tab to show the profiling information without the transformation step.

Flame Graph:
Screenshot 2026-05-08 at 12 25 36 PM

Raw Data:
Screenshot 2026-05-08 at 12 25 52 PM

Change Type (required)

Indicate the type of change your pull request is:

  • patch
  • minor
  • major

Comment on lines +1 to +3
export const getNowTime = globalThis.performance
? () => globalThis.performance.now()
: () => Date.now();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance isn't available on the ios and kotlin integrations, so it's preferred for accuracy but Date.now still works.

"id": "Profile-main",
"type": "flame-graph",
"binding": "rootNode",
"width": "@[{{rootNode.value}} / 200]@",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks weird but it helps normalize the width of each bar on the graph to be 5px per millisecond. Since flame-graph doesn't show times this helps with at least seeing how long everything takes.

Comment thread devtools/plugins/profiler/core/src/addProfilerInterceptorsToHooks.ts Outdated
tmarmer and others added 15 commits June 29, 2026 05:49
The ios and swiftui BUILD files referenced PlayerUIDevtoolsPlugins and
PlayerUIDevtoolsSwiftUIPlugins (trailing 's'), which don't exist. Point
them at the real PlayerUIDevtoolsPlugin / PlayerUIDevtoolsSwiftUIPlugin
targets so the iOS dependency graph resolves.
Mirror the basic plugin: move the profiler flow out of the hand-written
core/src/plugin-flow.json and into a new @player-devtools/profiler-plugin-content
DSL package (flow.tsx + views/navigation/schema/common), compiled via
dsl_compile. core now imports ProfilerPluginData + INTERACTIONS from the
content package, so the flow and runtime share one source of truth.

Fixes drift the static JSON had accumulated:
- flow id now matches PLUGIN_ID (was player-ui-profiler-devtools-plugin)
- Raw tab reset now publishes reset-profiling (was clear-profiling, which
  had no handler, so the button was dead)
- view ids match VIEWS_IDS

Also add the missing ProfilerDevtoolsPlugin.produceState helper that
plugin.ts already called but was never defined.
Mirror basic/android: ProfilerAndroidDevtoolsPlugin wrapping the profiler
jvm plugin, with BUILD (kt_android), AndroidManifest, and overlay style.
The profiler Swift sources imported PlayerUIDevtoolsPlugins /
PlayerUIDevtoolsSwiftUIPlugins (trailing 's'), which aren't real module
names, causing 'no such module' build failures. Corrected to the singular
PlayerUIDevtoolsPlugin / PlayerUIDevtoolsSwiftUIPlugin.

Package.swift had a single, mis-named profiler target (pointing only at
the ios sources with minimal deps). Split it into two targets mirroring
the basic plugin so the swiftui wrapper is built/published and the ios
target has the deps its sources import:
- PlayerUIDevtoolsBaseProfilerDevtoolsPlugin (profiler/ios)
- PlayerUIDevtoolsProfilerPlugin (profiler/swiftui)

These names now match the Bazel targets and the @testable imports.
@sugarmanz sugarmanz changed the base branch from mobile-devtools to main June 29, 2026 13:21
@sugarmanz sugarmanz requested a review from a team as a code owner June 29, 2026 13:21
@sugarmanz sugarmanz merged commit 26bb336 into main Jun 29, 2026
8 checks passed
@sugarmanz sugarmanz deleted the profiler-plugin branch June 29, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants