{"id":50680418,"url":"https://github.com/jack1590/roku-perfetto","last_synced_at":"2026-06-08T18:04:24.345Z","repository":{"id":351186026,"uuid":"1209776905","full_name":"jack1590/roku-perfetto","owner":"jack1590","description":"Library to handle perfetto into Roku ecosystem","archived":false,"fork":false,"pushed_at":"2026-04-13T23:50:33.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-14T01:19:13.688Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jack1590.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-13T19:14:11.000Z","updated_at":"2026-04-13T23:50:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jack1590/roku-perfetto","commit_stats":null,"previous_names":["jack1590/roku-perfetto"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jack1590/roku-perfetto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jack1590%2Froku-perfetto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jack1590%2Froku-perfetto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jack1590%2Froku-perfetto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jack1590%2Froku-perfetto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jack1590","download_url":"https://codeload.github.com/jack1590/roku-perfetto/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jack1590%2Froku-perfetto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34073840,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T18:04:22.992Z","updated_at":"2026-06-08T18:04:24.340Z","avatar_url":"https://github.com/jack1590.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# roku-perfetto\n\nLibrary for Roku Perfetto tracing — ECP control, WebSocket recording, trace analysis with PerfettoSQL, and AI-friendly performance reports.\n\nRequires **Roku OS 15.1+** with [Perfetto tracing](https://developer.roku.com/docs/developer-program/dev-tools/app-tracing.md) support.\n\n## Install\n\n```bash\nnpm install roku-perfetto\n```\n\n## Quick Start\n\n### Record a trace\n\n```ts\nimport { PerfettoClient } from 'roku-perfetto';\n\nconst client = new PerfettoClient('192.168.1.86');\nawait client.enable('dev');\nawait client.startRecording('trace.perfetto');\n// ... interact with the app ...\nconst result = await client.stopRecording();\nconsole.log(`Saved ${result.bytesWritten} bytes to ${result.filePath}`);\n```\n\n### Analyze a trace\n\n```ts\nimport { openTrace } from 'roku-perfetto';\n\nconst analyzer = await openTrace('trace.perfetto');\nconst summary = await analyzer.performanceSummary();\nconsole.log(summary.overallAssessment);\nconsole.log(summary.frameDrops.suggestion);\nawait analyzer.close();\n```\n\n### Run a custom PerfettoSQL query\n\n```ts\nimport { openTrace } from 'roku-perfetto';\n\nconst analyzer = await openTrace('trace.perfetto');\nconst result = await analyzer.query(\n  \"SELECT * FROM slice WHERE name = 'swapBuffers' ORDER BY dur DESC LIMIT 10\"\n);\nconsole.log(result.rows);\nawait analyzer.close();\n```\n\n### Compare two traces\n\n```ts\nimport { comparePerfetto } from 'roku-perfetto';\n\nconst report = await comparePerfetto('before.trace', 'after.trace');\nconsole.log(report.summary);\nconsole.log(`Regressions: ${report.regressions.length}`);\nconsole.log(`Improvements: ${report.improvements.length}`);\n```\n\n## CLI\n\n```bash\n# Enable tracing on a device\nroku-perfetto enable 192.168.1.86 dev\n\n# Record a 30-second trace\nroku-perfetto record --host 192.168.1.86 --channel dev --duration 30 -o trace.perfetto\n\n# Full performance summary\nroku-perfetto analyze summary trace.perfetto\n\n# Specific analysis\nroku-perfetto analyze frame-drops trace.perfetto --threshold 16\nroku-perfetto analyze key-events trace.perfetto\nroku-perfetto analyze observers trace.perfetto\nroku-perfetto analyze rendezvous trace.perfetto\nroku-perfetto analyze set-fields trace.perfetto\nroku-perfetto analyze threads trace.perfetto\n\n# JSON output (for programmatic consumption)\nroku-perfetto analyze summary trace.perfetto -f json\n\n# Raw PerfettoSQL query\nroku-perfetto query trace.perfetto \"SELECT * FROM slice WHERE name = 'keyEvent' ORDER BY dur DESC\"\n\n# Compare two traces\nroku-perfetto compare before.trace after.trace\n\n# Trace metadata\nroku-perfetto info trace.perfetto\n```\n\n## API Reference\n\n### `PerfettoClient`\n\nHandles ECP communication and WebSocket trace recording with a Roku device.\n\n| Method | Description |\n|--------|-------------|\n| `enable(channelId?)` | Enable Perfetto tracing for a channel via ECP POST |\n| `startRecording(filePath, channelId?)` | Open WebSocket and stream binary trace data to a file |\n| `stopRecording()` | Close WebSocket, finalize file, return recording stats |\n| `isRecording()` | Check if a recording session is active |\n| `getSession()` | Get current session info (host, bytes, duration) |\n\n### `RokuAnalyzer`\n\nHigh-level Roku-specific trace analysis with AI-friendly `suggestion` fields.\n\n| Method | Description |\n|--------|-------------|\n| `RokuAnalyzer.open(tracePath, opts?)` | Open a trace file and return an analyzer |\n| `performanceSummary(opts?)` | Full report: frame drops + key events + observers + rendezvous + threads |\n| `analyzeFrameDrops(opts?)` | swapBuffers duration analysis with drop rate |\n| `analyzeKeyEvents(opts?)` | OnKeyEvent duration analysis |\n| `analyzeObservers(opts?)` | observer.callback analysis |\n| `analyzeRendezvous(opts?)` | Cross-thread synchronization analysis |\n| `analyzeSetFields(opts?)` | roSGNode.setField call analysis |\n| `analyzeThreads(opts?)` | Per-thread overview with top slices |\n| `traceInfo()` | Trace duration, slice count, thread count |\n| `query(sql)` | Run a raw PerfettoSQL query |\n| `close()` | Shut down the trace processor |\n\n### `TraceProcessor`\n\nLow-level wrapper around the Perfetto `trace_processor` binary.\n\n| Method | Description |\n|--------|-------------|\n| `TraceProcessor.open(tracePath, opts?)` | Spawn trace_processor with --httpd, wait for ready |\n| `query(sql)` | Execute PerfettoSQL, return structured rows |\n| `status()` | Check trace processor status |\n| `close()` | Kill the trace processor process |\n\n### `comparePerfetto(beforePath, afterPath, opts?)`\n\nCompare two trace files and return a `ComparisonReport` with metric deltas, regressions, and improvements.\n\n### `openTrace(tracePath, opts?)`\n\nConvenience function that opens a trace and returns a ready-to-use `RokuAnalyzer`.\n\n## Analysis Modes\n\n| Mode | What it checks | Key metric |\n|------|---------------|------------|\n| `summary` | Everything below combined | `overallAssessment` |\n| `frame-drops` | swapBuffers durations | Frame drop rate % |\n| `key-events` | keyEvent handler durations | Avg response time |\n| `observers` | observer.callback durations | Slow callback count |\n| `rendezvous` | Cross-thread sync points | Long rendezvous count |\n| `set-fields` | roSGNode.setField calls | Avg setField duration |\n| `threads` | Per-thread activity overview | Top slices by duration |\n\n## Built-in PerfettoSQL Queries\n\nThe library exports the Roku-specific queries as constants for custom use:\n\n```ts\nimport { FRAME_DROPS_QUERY, KEY_EVENTS_QUERY, OBSERVER_QUERY } from 'roku-perfetto';\n```\n\n## trace_processor Binary\n\nThe library automatically downloads the Perfetto `trace_processor` prebuilt binary from `https://get.perfetto.dev/trace_processor` on first use. The binary is cached at `~/.roku-perfetto/bin/trace_processor`.\n\nSupported platforms: **macOS** and **Linux**.\n\nYou can provide a custom binary path:\n\n```ts\nconst analyzer = await RokuAnalyzer.open('trace.perfetto', {\n  binPath: '/usr/local/bin/trace_processor',\n});\n```\n\n## Prerequisites\n\n- **Node.js 18+**\n- **Roku OS 15.1+** on the target device\n- For sideloaded apps: `run_as_process=1` in the manifest\n- For production/beta apps: device must be keyed with the app signing key\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjack1590%2Froku-perfetto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjack1590%2Froku-perfetto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjack1590%2Froku-perfetto/lists"}