Skip to content
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

Performance Enhancement: Migrate to Modern React Native Architecture 🚀 #8521

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions tfjs-react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,46 +37,44 @@
"update-apk": "./scripts/update-apk.sh"
},
"devDependencies": {
"@react-native-async-storage/async-storage": "^1.13.0",
"@tensorflow/tfjs-backend-cpu": "~4.3.0",
"@tensorflow/tfjs-backend-webgl": "~4.3.0",
"@tensorflow/tfjs-core": "4.3.0",
"@types/base64-js": "^1.2.5",
"@tensorflow/tfjs-backend-cpu": "~4.22.0",
"@tensorflow/tfjs-backend-webgl": "~4.22.0",
"@tensorflow/tfjs-core": "~4.22.0",
"@types/jasmine": "~3.3.0",
"@types/react-native": "0.60.2",
"@types/react-native-fs": "^2.13.0",
"clang-format": "~1.8.0",
"expo-asset": "^7.0.0",
"expo-camera": "^7.0.0",
"expo-gl": "^7.0.0",
"gts": "^3.1.0",
"react": "^16.12.0",
"rimraf": "~2.6.2",
"@types/react": "^19.0.8",
"@types/react-native": "^0.73.0",
"clang-format": "^1.8.0",
"expo-asset": "^11.0.2",
"expo-camera": "^16.0.14",
"expo-gl": "^15.0.4",
"gts": "^6.0.2",
"react": "^19.0.0",
"rimraf": "^6.0.1",
"rollup": "^0.58.2",
"rollup-plugin-commonjs": "9.1.3",
"rollup-plugin-node-resolve": "3.3.0",
"rollup-plugin-typescript2": "0.13.0",
"rollup-plugin-uglify": "~3.0.0",
"tslint": "~6.1.3",
"tslint-no-circular-imports": "^0.7.0",
"typescript": "4.4.2",
"yalc": "^1.0.0-pre.50"
"typescript": "^5.7.3",
"yalc": "^1.0.0-pre.53"
},
"dependencies": {
"base64-js": "^1.3.0",
"buffer": "^5.2.1",
"jpeg-js": "^0.4.3"
"@dr.pogodin/react-native-fs": "^2.31.0",
"base64-js": "^1.5.1",
"buffer": "^6.0.3",
"jpeg-js": "^0.4.4",
"react-native-mmkv": "^3.2.0"
},
"peerDependencies": {
"@react-native-async-storage/async-storage": "^1.13.0",
"@tensorflow/tfjs-backend-cpu": "^4.13.0",
"@tensorflow/tfjs-backend-webgl": "^4.13.0",
"@tensorflow/tfjs-core": "^4.13.0",
"expo-camera": "^13.4.4",
"expo-gl": "^13.0.1",
"react": "*",
"react-native": ">= 0.72.0",
"react-native-fs": "^2.20.0"
"@tensorflow/tfjs-backend-cpu": "^4.22.0",
"@tensorflow/tfjs-backend-webgl": "^4.22.0",
"@tensorflow/tfjs-core": "^4.22.0",
"expo-camera": ">=16.0.0",
"expo-gl": ">=15.0.0",
"react": ">=18.3.1",
"react-native": ">= 0.76.0"
},
"resolutions": {
"minimist": "1.2.6"
Expand Down
43 changes: 22 additions & 21 deletions tfjs-react-native/src/async_storage_io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
* =============================================================================
*/

import {AsyncStorageStatic} from '@react-native-async-storage/async-storage';
import {io} from '@tensorflow/tfjs-core';
import {fromByteArray, toByteArray} from 'base64-js';
import {MMKV} from 'react-native-mmkv';

type StorageKeys = {
info: string,
Expand Down Expand Up @@ -56,13 +56,14 @@ function getModelArtifactsInfoForJSON(modelArtifacts: io.ModelArtifacts):
modelTopologyType: 'JSON',
weightDataBytes: modelArtifacts.weightData == null ?
0 :
//@ts-ignore
modelArtifacts.weightData.byteLength,
};
}

class AsyncStorageHandler implements io.IOHandler {
protected readonly keys: StorageKeys;
protected asyncStorage: AsyncStorageStatic;
protected mmkvStore: MMKV;

constructor(protected readonly modelPath: string) {
if (modelPath == null || !modelPath) {
Expand All @@ -74,9 +75,9 @@ class AsyncStorageHandler implements io.IOHandler {
// needs to be installed by the user if they use this handler. We don't
// want users who are not using AsyncStorage to have to install this
// library.
this.asyncStorage =
// tslint:disable-next-line:no-require-imports
require('@react-native-async-storage/async-storage').default;
this.mmkvStore = new MMKV({
id: 'tfjs.react-native.store'
})
}

/**
Expand All @@ -99,19 +100,20 @@ class AsyncStorageHandler implements io.IOHandler {
const {weightData, ...modelArtifactsWithoutWeights} = modelArtifacts;

try {
this.asyncStorage.setItem(
this.keys.info, JSON.stringify(modelArtifactsInfo));
this.asyncStorage.setItem(
this.keys.modelArtifactsWithoutWeights,
JSON.stringify(modelArtifactsWithoutWeights));
this.asyncStorage.setItem(
this.keys.weightData, fromByteArray(new Uint8Array(weightData)));
this.mmkvStore.set(
this.keys.info, JSON.stringify(modelArtifacts));
this.mmkvStore.set(
this.keys.modelArtifactsWithoutWeights,
JSON.stringify(modelArtifactsWithoutWeights));
this.mmkvStore.set(
//@ts-ignore
this.keys.weightData, fromByteArray(new Uint8Array(weightData)));
return {modelArtifactsInfo};
} catch (err) {
// If saving failed, clean up all items saved so far.
this.asyncStorage.removeItem(this.keys.info);
this.asyncStorage.removeItem(this.keys.weightData);
this.asyncStorage.removeItem(this.keys.modelArtifactsWithoutWeights);
this.mmkvStore.delete(this.keys.info);
this.mmkvStore.delete(this.keys.modelArtifactsWithoutWeights);
this.mmkvStore.delete(this.keys.weightData);

throw new Error(
`Failed to save model '${this.modelPath}' to AsyncStorage.
Expand All @@ -129,8 +131,8 @@ class AsyncStorageHandler implements io.IOHandler {
* @returns The loaded model (if loading succeeds).
*/
async load(): Promise<io.ModelArtifacts> {
const info = JSON.parse(await this.asyncStorage.getItem(this.keys.info)) as
io.ModelArtifactsInfo;
const info = JSON.parse(
this.mmkvStore.getString(this.keys.info)) as io.ModelArtifactsInfo;
if (info == null) {
throw new Error(
`In local storage, there is no model with name '${this.modelPath}'`);
Expand All @@ -143,12 +145,11 @@ class AsyncStorageHandler implements io.IOHandler {
}

const modelArtifacts: io.ModelArtifacts =
JSON.parse(await this.asyncStorage.getItem(
this.keys.modelArtifactsWithoutWeights));
JSON.parse(this.mmkvStore.getString(
this.keys.modelArtifactsWithoutWeights));

// Load weight data.
const weightDataBase64 =
await this.asyncStorage.getItem(this.keys.weightData);
const weightDataBase64 = this.mmkvStore.getString(this.keys.weightData);
if (weightDataBase64 == null) {
throw new Error(
`In local storage, the binary weight values of model ` +
Expand Down
8 changes: 3 additions & 5 deletions tfjs-react-native/src/bundle_resource_io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import {io, util} from '@tensorflow/tfjs-core';
import {Asset} from 'expo-asset';
import {Platform} from 'react-native';
import {readFileRes, readFile} from '@dr.pogodin/react-native-fs'

import {fetch} from './platform_react_native';

Expand Down Expand Up @@ -87,9 +88,6 @@ class BundleResourceHandler implements io.IOHandler {
// with managed expo workflow. However the managed expo workflow should
// never hit this code path.

// tslint:disable-next-line: no-require-imports
const RNFS = require('react-native-fs');

const modelJson = this.modelJson;
const modelArtifacts: io.ModelArtifacts = Object.assign({}, modelJson);
modelArtifacts.weightSpecs = modelJson.weightsManifest[0].weights;
Expand All @@ -105,7 +103,7 @@ class BundleResourceHandler implements io.IOHandler {
// need to load the weights from the res/raw folder using this id.
const fileName = `${weightsAsset.uri}.${weightsAsset.type}`;
try {
base64Weights = await RNFS.readFileRes(fileName, 'base64');
base64Weights = await readFileRes(fileName, 'base64');
} catch (e) {
throw new Error(
`Error reading resource ${fileName}. Make sure the file is
Expand All @@ -114,7 +112,7 @@ class BundleResourceHandler implements io.IOHandler {
}
} else {
try {
base64Weights = await RNFS.readFile(weightsAsset.uri, 'base64');
base64Weights = await readFile(weightsAsset.uri, 'base64');
} catch (e) {
throw new Error(
`Error reading resource ${weightsAsset.uri}.`,
Expand Down
Loading