-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add react-native-perf-stats native module #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
d84225d
feat: add react-native-perf-stats native module
huhuanming 3790dd1
chore: bump all packages to 3.0.25
huhuanming 3b8b33a
fix(perf-stats): close start/stop race that stranded sampler
huhuanming e9bc74e
docs(perf-stats): rewrite README with real API and scoped package name
huhuanming cdd69c9
feat(perf-stats): log sustained CPU/RSS anomalies to native-logger
huhuanming d169842
fix(perf-stats): use literal 1005 for ABOVE_SUB_PANEL window type
huhuanming 9d79002
feat(perf-stats): add UI FPS and JS FPS metrics
huhuanming 60ba089
feat(perf-stats): auto-manage JS FPS tracker from start/stop
huhuanming 7b2d9ce
fix(perf-stats): keep iOS overlay above modal-presented controllers
huhuanming 94ca464
3.0.28
huhuanming 32a6520
fix(perf-stats): prevent Android overlay leak on Activity destroy
huhuanming File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
native-modules/react-native-check-biometric-auth-changed/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # OSX | ||
| # | ||
| .DS_Store | ||
|
|
||
| # XDE | ||
| .expo/ | ||
|
|
||
| # VSCode | ||
| .vscode/ | ||
| jsconfig.json | ||
|
|
||
| # Xcode | ||
| # | ||
| build/ | ||
| *.pbxuser | ||
| !default.pbxuser | ||
| *.mode1v3 | ||
| !default.mode1v3 | ||
| *.mode2v3 | ||
| !default.mode2v3 | ||
| *.perspectivev3 | ||
| !default.perspectivev3 | ||
| xcuserdata | ||
| *.xccheckout | ||
| *.moved-aside | ||
| DerivedData | ||
| *.hmap | ||
| *.ipa | ||
| *.xcuserstate | ||
| project.xcworkspace | ||
| **/.xcode.env.local | ||
|
|
||
| # Android/IJ | ||
| # | ||
| .classpath | ||
| .cxx | ||
| .gradle | ||
| .idea | ||
| .project | ||
| .settings | ||
| local.properties | ||
| android.iml | ||
|
|
||
| # Cocoapods | ||
| # | ||
| example/ios/Pods | ||
|
|
||
| # Ruby | ||
| example/vendor/ | ||
|
|
||
| # node.js | ||
| # | ||
| node_modules/ | ||
| npm-debug.log | ||
| yarn-debug.log | ||
| yarn-error.log | ||
|
|
||
| # BUCK | ||
| buck-out/ | ||
| \.buckd/ | ||
| android/app/libs | ||
| android/keystores/debug.keystore | ||
|
|
||
| # Yarn | ||
| .yarn/* | ||
| !.yarn/patches | ||
| !.yarn/plugins | ||
| !.yarn/releases | ||
| !.yarn/sdks | ||
| !.yarn/versions | ||
|
|
||
| # Expo | ||
| .expo/ | ||
|
|
||
| # Turborepo | ||
| .turbo/ | ||
|
|
||
| # generated by bob | ||
| lib/ | ||
|
|
||
| # React Native Codegen | ||
| ios/generated | ||
| android/generated | ||
|
|
||
| # React Native Nitro Modules | ||
| nitrogen/ | ||
|
|
||
|
|
||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| MIT License | ||
|
|
||
| Copyright (c) 2024 OneKey | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| # @onekeyfe/react-native-perf-stats | ||
|
|
||
| Native CPU, RAM, UI-FPS and JS-FPS sampler for React Native, with an optional draggable on-screen overlay. Built on [Nitro Modules](https://nitro.margelo.com/) — the sampler runs on a dedicated background thread so the overlay keeps updating even when the JS thread is frozen. | ||
|
|
||
| - **Android**: HandlerThread + `/proc/self/stat` (CPU ticks) + `/proc/self/statm` (RSS) + `Choreographer.FrameCallback` (UI FPS); overlay attached via `WindowManager` to the current Activity (no `SYSTEM_ALERT_WINDOW` permission). | ||
| - **iOS**: GCD dispatch source + `task_info` (`phys_footprint`) + `CADisplayLink` (UI FPS); overlay added as a `UILabel` on the key `UIWindow`. | ||
| - **JS FPS**: opt-in JS-side `requestAnimationFrame` ticker that pushes its per-second count to native via `setJsFpsHint`. Started by `startJsFpsTracker()`. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```sh | ||
| yarn add @onekeyfe/react-native-perf-stats react-native-nitro-modules | ||
| ``` | ||
|
|
||
| `react-native-nitro-modules` is a required peer dependency. | ||
|
|
||
| ## Usage | ||
|
|
||
| ```ts | ||
| import { ReactNativePerfStats } from '@onekeyfe/react-native-perf-stats'; | ||
|
|
||
| // Start sampling at 1 Hz. Idempotent — calling again just updates the interval. | ||
| // Also kicks off the JS-side rAF tracker so PerfSample.jsFps is populated. | ||
| ReactNativePerfStats.start(1000); | ||
|
|
||
| // Show the floating overlay (drag to reposition). | ||
| ReactNativePerfStats.showOverlay(); | ||
|
|
||
| // One-shot read without touching the overlay timer. | ||
| const sample = await ReactNativePerfStats.sample(); | ||
| console.log(sample); | ||
| // { cpu: 12.3, rss: 187654144, uiFps: 59, jsFps: 60, timestamp: 1730000000000 } | ||
|
|
||
| // Tear down. Also stops the JS-side rAF tracker. | ||
| ReactNativePerfStats.hideOverlay(); | ||
| ReactNativePerfStats.stop(); | ||
| ``` | ||
|
|
||
| ### `PerfSample` | ||
|
|
||
| | field | unit | notes | | ||
| | ----------- | --------------------- | ------------------------------------------------------------------------------------------------------ | | ||
| | `cpu` | percent of one core | `(Δcpu / Δwall) * 100`. May exceed 100 on multi-core saturation. First sample after launch is `0`. | | ||
| | `rss` | bytes | iOS `phys_footprint`, Android `VmRSS`. | | ||
| | `uiFps` | frames per second | UI thread frame rate over the last sampling window. `0` until at least one window has elapsed. | | ||
| | `jsFps` | frames per second | JS thread rAF count. `0` unless `startJsFpsTracker()` has been called and reported at least once. | | ||
| | `timestamp` | ms since unix epoch | Wall-clock at sample time. | | ||
|
|
||
| ### API | ||
|
|
||
| - `start(intervalMs: number): void` — minimum interval is clamped to 200 ms. Also starts the JS-side rAF tracker (matched to `intervalMs`) so `jsFps` flows automatically. | ||
| - `stop(): void` — stops the JS-side tracker, the native sampler, and hides the overlay. | ||
| - `showOverlay(): void` / `hideOverlay(): void` — overlay shows `--` until `start` runs. | ||
| - `sample(): Promise<PerfSample>` — runs off the JS thread, shares baseline with the overlay sampler. | ||
| - `setJsFpsHint(fps: number): void` — low-level escape hatch; normally driven by the auto-managed tracker. | ||
| - `startJsFpsTracker(reportIntervalMs?: number): void` / `stopJsFpsTracker(): void` — manual control of the JS-side rAF tracker. Useful if you want JS FPS without enabling the native sampler. Calling `startJsFpsTracker` with a different `reportIntervalMs` while running restarts the loop with the new interval. | ||
|
|
||
| ### Anomaly logging | ||
|
|
||
| While the sampler is running, the native side emits a warn to `@onekeyfe/react-native-native-logger` (`OneKeyLog.warn`, tag `PerfStats`) whenever a metric stays over its threshold for **5 consecutive samples**. Each category has an independent **30 s cooldown** so a sustained spike produces one log every 30 s rather than one per sample. | ||
|
|
||
| | metric | threshold | | ||
| | ------ | ---------------- | | ||
| | CPU | ≥ 150 % | | ||
| | RSS | ≥ 800 MB | | ||
| | UI FPS | ≤ 45 fps (and > 0) | | ||
| | JS FPS | ≤ 30 fps (and > 0) | | ||
|
|
||
| One-off `sample()` calls do **not** trip this path — only the periodic timer started by `start()` does. | ||
|
|
||
| ## License | ||
|
|
||
| MIT |
30 changes: 30 additions & 0 deletions
30
native-modules/react-native-perf-stats/ReactNativePerfStats.podspec
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| require "json" | ||
|
|
||
| package = JSON.parse(File.read(File.join(__dir__, "package.json"))) | ||
|
|
||
| Pod::Spec.new do |s| | ||
| s.name = "ReactNativePerfStats" | ||
| s.version = package["version"] | ||
| s.summary = package["description"] | ||
| s.homepage = package["homepage"] | ||
| s.license = package["license"] | ||
| s.authors = package["author"] | ||
|
|
||
| s.platforms = { :ios => min_ios_version_supported } | ||
| s.source = { :git => "https://github.com/OneKeyHQ/app-modules/react-native-perf-stats.git", :tag => "#{s.version}" } | ||
|
|
||
| s.source_files = [ | ||
| "ios/**/*.{swift}", | ||
| "ios/**/*.{m,mm}", | ||
| "cpp/**/*.{hpp,cpp}", | ||
| ] | ||
|
|
||
| s.dependency 'React-jsi' | ||
| s.dependency 'React-callinvoker' | ||
| s.dependency 'ReactNativeNativeLogger' | ||
|
|
||
| load 'nitrogen/generated/ios/ReactNativePerfStats+autolinking.rb' | ||
| add_nitrogen_files(s) | ||
|
|
||
| install_modules_dependencies(s) | ||
| end |
24 changes: 24 additions & 0 deletions
24
native-modules/react-native-perf-stats/android/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| project(reactnativeperfstats) | ||
| cmake_minimum_required(VERSION 3.9.0) | ||
|
|
||
| set(PACKAGE_NAME reactnativeperfstats) | ||
| set(CMAKE_VERBOSE_MAKEFILE ON) | ||
| set(CMAKE_CXX_STANDARD 20) | ||
|
|
||
| # Define C++ library and add all sources | ||
| add_library(${PACKAGE_NAME} SHARED src/main/cpp/cpp-adapter.cpp) | ||
|
|
||
| # Add Nitrogen specs :) | ||
| include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/reactnativeperfstats+autolinking.cmake) | ||
|
|
||
| # Set up local includes | ||
| include_directories("src/main/cpp" "../cpp") | ||
|
|
||
| find_library(LOG_LIB log) | ||
|
|
||
| # Link all libraries together | ||
| target_link_libraries( | ||
| ${PACKAGE_NAME} | ||
| ${LOG_LIB} | ||
| android # <-- Android core | ||
| ) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.