{"_id":"@artshin/expo-perf-recorder","_rev":"2-8a09a0e9c6d619ee696f6acc09c2c742","name":"@artshin/expo-perf-recorder","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@artshin/expo-perf-recorder","version":"0.0.1","keywords":["expo","expo-module","react-native","profiler","performance","devtools"],"license":"MIT","_id":"@artshin/expo-perf-recorder@0.0.1","maintainers":[{"name":"artshin","email":"ashnkvch@gmail.com"}],"homepage":"https://github.com/artshin/perf-recorder/tree/main/packages/expo-perf-recorder#readme","bugs":{"url":"https://github.com/artshin/perf-recorder/issues"},"dist":{"shasum":"6f19eb36b916c279ad0ca359fd8f36d9a8b779c1","tarball":"https://registry.npmjs.org/@artshin/expo-perf-recorder/-/expo-perf-recorder-0.0.1.tgz","fileCount":234,"integrity":"sha512-+usIo3vAWXhTqUgzxqbI3DSGZc/6oISRMXysaswNniHUmL8r2UaY32oOa5Q6DB0A8xMJqu4BWN6lBZC4vXhqXQ==","signatures":[{"sig":"MEQCIBoekiyhPxGfcRYRxdAW/wc0EpTJoWnbRn4jqJ96CrU4AiAbBMa6xJ+A9t8AWTVTnfXCkScBhfoDe+Ex19l2EQVRTw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1330544},"main":"build/index.js","types":"build/index.d.ts","exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./auto":{"types":"./build/auto.d.ts","default":"./build/auto.js"},"./package.json":"./package.json"},"gitHead":"724557a293eaee1fd50218f94abf18e916a2b008","scripts":{"lint":"expo-module lint","test":"expo-module test","build":"expo-module build","clean":"expo-module clean","prepare":"expo-module prepare","expo-module":"expo-module","prepublishOnly":"expo-module prepublishOnly"},"_npmUser":{"name":"artshin","email":"ashnkvch@gmail.com"},"repository":{"url":"git+https://github.com/artshin/perf-recorder.git","type":"git","directory":"packages/expo-perf-recorder"},"_npmVersion":"11.6.2","description":"Continuous background React profiler for Expo / React Native (dev-only). Captures React DevTools profiling dumps in JS and persists, analyses and aggregates them natively, off the JS thread.","directories":{},"sideEffects":["./auto.ts","./build/auto.js"],"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"expo":"*","jest":"^29.7.0","react":"*","eslint":"^9.36.0","prettier":"^3.4.2","@types/jest":"^29.5.14","react-native":"*","expo-module-scripts":"^4.1.7","eslint-config-universe":"^15.0.3"},"peerDependencies":{"expo":">=52.0.0","react":">=18.0.0","react-native":">=0.76.0"},"_npmOperationalInternal":{"tmp":"tmp/expo-perf-recorder_0.0.1_1779897426809_0.1151446665628093","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@artshin/expo-perf-recorder","version":"0.0.2","description":"Continuous background React profiler for Expo / React Native (dev-only). Captures React DevTools profiling dumps in JS and persists, analyses and aggregates them natively, off the JS thread.","repository":{"type":"git","url":"git+https://github.com/artshin/perf-recorder.git","directory":"packages/expo-perf-recorder"},"homepage":"https://github.com/artshin/perf-recorder/tree/main/packages/expo-perf-recorder#readme","bugs":{"url":"https://github.com/artshin/perf-recorder/issues"},"main":"build/index.js","types":"build/index.d.ts","exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./auto":{"types":"./build/auto.d.ts","default":"./build/auto.js"},"./package.json":"./package.json"},"sideEffects":["./auto.ts","./build/auto.js"],"scripts":{"build":"expo-module build","clean":"expo-module clean","lint":"expo-module lint","test":"expo-module test","prepare":"expo-module prepare","prepublishOnly":"expo-module prepublishOnly","expo-module":"expo-module"},"keywords":["expo","expo-module","react-native","profiler","performance","devtools"],"license":"MIT","peerDependencies":{"expo":">=52.0.0","react":">=18.0.0","react-native":">=0.76.0"},"devDependencies":{"@types/jest":"^29.5.14","eslint":"^9.36.0","eslint-config-universe":"^15.0.3","expo":"*","expo-module-scripts":"^4.1.7","jest":"^29.7.0","prettier":"^3.4.2","react":"*","react-native":"*"},"gitHead":"cb2bc81a8b94fbaf5d2ab0375aa8d4febee44e3d","_id":"@artshin/expo-perf-recorder@0.0.2","_nodeVersion":"24.15.0","_npmVersion":"11.15.0","dist":{"integrity":"sha512-azFT4tmqB40+Kib0C9yk397SYL5U7EXXKJ+hiaN69iBBNGLeiC1/9tPSdN4Az0P/UoBuG542D1Sp3WHcc3YW8A==","shasum":"851cbffa2d54b635724b88dea882b97c9a2ecfcd","tarball":"https://registry.npmjs.org/@artshin/expo-perf-recorder/-/expo-perf-recorder-0.0.2.tgz","fileCount":39,"unpackedSize":113218,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@artshin%2fexpo-perf-recorder@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBac4ps1f65RYsFcxNEfzM9xigiWMtr/fFYRca82qld/AiEA/F9k5Z13PHuZHHKJP78NoYK0/AWlUzcDe57EewtbqMk="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8a643307-da18-4eb1-9d5f-c7dc9bc622a2"}},"directories":{},"maintainers":[{"name":"artshin","email":"ashnkvch@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/expo-perf-recorder_0.0.2_1779899986904_0.4689746337477625"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-27T15:57:06.665Z","modified":"2026-05-27T16:39:47.353Z","0.0.1":"2026-05-27T15:57:07.024Z","0.0.2":"2026-05-27T16:39:47.052Z"},"bugs":{"url":"https://github.com/artshin/perf-recorder/issues"},"license":"MIT","homepage":"https://github.com/artshin/perf-recorder/tree/main/packages/expo-perf-recorder#readme","keywords":["expo","expo-module","react-native","profiler","performance","devtools"],"repository":{"type":"git","url":"git+https://github.com/artshin/perf-recorder.git","directory":"packages/expo-perf-recorder"},"description":"Continuous background React profiler for Expo / React Native (dev-only). Captures React DevTools profiling dumps in JS and persists, analyses and aggregates them natively, off the JS thread.","maintainers":[{"name":"artshin","email":"ashnkvch@gmail.com"}],"readme":"# @artshin/expo-perf-recorder\n\n[![npm](https://img.shields.io/npm/v/@artshin/expo-perf-recorder)](https://www.npmjs.com/package/@artshin/expo-perf-recorder)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)\n\nContinuous, **dev-only** background React profiler for Expo / React Native apps,\nshipped as a self-contained Expo module (autolinked native Kotlin + Swift). It\nrecords the same data the React DevTools profiler captures (`getProfilingData()`\nV5 exports), but **automatically and on an interval** — then persists, analyses,\nand aggregates it natively, off the JS thread, so stats are available on demand.\n\nThe companion Rozenite DevTools panel + agent tools live in\n[`@artshin/rozenite-perf-recorder`](../rozenite-perf-recorder).\n\n## Install\n\n```sh\nnpx expo install @artshin/expo-perf-recorder\n```\n\nExpo autolinking picks up the native module from `node_modules` — no manual\nlinking. Rebuild the dev client / run `expo prebuild` so the native code is\ncompiled in.\n\n## How it works\n\n| Layer | Where | Responsibility |\n|-------|-------|----------------|\n| Capture | JS (`src/capture.ts`) | Taps `__REACT_DEVTOOLS_GLOBAL_HOOK__`, runs a continuous loop: every `intervalMs` it stops the profiling window, ships the V5 export to native, and re-arms a fresh window (so in-memory commit data never grows unbounded). |\n| Persist + analyse + stats | Native (Kotlin / Swift) | Parses each dump on a background thread, ring-buffers raw dumps to disk, and folds results into rolling stats that **survive Fast Refresh**. |\n| Stats UI | JS (`src/overlay/PerfOverlay.tsx`) | Floating dev overlay. A richer Rozenite devtools panel ships in `@artshin/rozenite-perf-recorder`. |\n\nCapture *must* run in the app's JS runtime — the timing data lives in React's\nin-memory fiber tree, reachable only through the devtools hook. Everything else\nis native and off-thread.\n\n## Usage\n\n### Zero-integration (recommended)\n\nAdd one side-effect import to your app entry (`index.ts`):\n\n```ts\nimport \"@artshin/expo-perf-recorder/auto\"; // dev-only; no-op in production\n```\n\nThat's it — the loop arms itself once the devtools agent attaches.\n\n### Show live stats\n\nMount the overlay near the app root (dev branch only):\n\n```tsx\nimport { PerfOverlay } from \"@artshin/expo-perf-recorder\";\n// ...\n{__DEV__ && <PerfOverlay />}\n```\n\nTap the pill to expand; long-press to clear stats.\n\n### Programmatic\n\n```ts\nimport {\n  startPerfRecorder,\n  stopPerfRecorder,\n  getPerfStats,\n  clearPerfData,\n} from \"@artshin/expo-perf-recorder\";\n\nawait startPerfRecorder({ intervalMs: 8000, mainRendererOnly: true, maxDumps: 50 });\nconst stats = await getPerfStats(); // PerfStats\nawait stopPerfRecorder();\nawait clearPerfData();\n```\n\n## Config\n\n| Option | Default | Notes |\n|--------|---------|-------|\n| `intervalMs` | `10000` | Window length / ship cadence. Bounds memory. |\n| `mainRendererOnly` | `true` | Skip secondary reconcilers (e.g. Skia) — they have destabilised devtools attach on this app. |\n| `maxDumps` | `50` | Raw dumps retained in the native disk ring buffer. |\n\n## Caveats\n\n- **Dev-only.** Guarded by `__DEV__`; profiling mode adds per-commit overhead and\n  skews absolute numbers — read it for trends/regressions, not budgets.\n- **Names** come from the in-app DevTools operations decoder (`src/operations.ts`),\n  injected into each dump's `snapshots` before shipping; `commitData.updaters` is\n  the secondary source. Requires the devtools agent attached (see `:8097` caveat).\n- Rolling fiber stats are keyed by **name**, not id, because element ids reset on\n  every JS reload.\n- Raw dumps land in the app cache dir (`<cache>/perf-recorder/`), newest-last.\n\n## Companion panel\n\n`@artshin/rozenite-perf-recorder` is a standalone Rozenite DevTools panel +\nagent tools that talk to this module's native side by name\n(`requireNativeModule(\"PerfRecorder\")`). It surfaces the same rolling stats in a\nRozenite panel and exposes `get-stats` / `clear` / `list-dumps` / `get-dump`\nagent tools. See that package's README.\n","readmeFilename":"README.md"}