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

[js/rn] Implement blob exchange by JSI instead of use base64 #16094

Merged
merged 32 commits into from
Jun 16, 2023

Conversation

jhen0409
Copy link
Contributor

@jhen0409 jhen0409 commented May 25, 2023

Description

  • Create OnnxruntimeJSIHelper native module to provide two JSI functions
    • jsiOnnxruntimeStoreArrayBuffer: Store buffer in Blob Manager & return blob object (iOS: RCTBlobManager, Android: BlobModule)
    • jsiOnnxruntimeResolveArrayBuffer: Use blob object to get buffer
    • The part of implementation is reference to react-native-blob-jsi-helper
  • Replace base64 encode/decode
    • loadModelFromBlob: Rename from loadModelFromBase64EncodedBuffer
    • run: Use blob object to replace input.data & results[].data

For this context, it saved a lot of time and avoid JS thread blocking in decode return type, it is 3700ms -> 5~20ms for the case. (resolve function only takes 0.x ms)

Motivation and Context

It’s related to #16031, but not a full implementation for migrate to JSI.

It just uses JSI through BlobManager to replace the slow part (base64 encode / decode).

Rewriting it entirely in JSI could be complicated, like type convertion and threading. This PR might be considered a minor change.

/cc @skottmckay

@jhen0409
Copy link
Contributor Author

@microsoft-github-policy-service agree

@jhen0409 jhen0409 force-pushed the jhen-rn-use-blob branch from e037a60 to 7897572 Compare May 26, 2023 05:31
@fs-eire
Copy link
Contributor

fs-eire commented May 27, 2023

The typescript part looks good to me.

I don't know much details about JSI. I have 2 questions regarding the implementation:

  • is there a way to export jsiOnnxruntimeStoreArrayBuffer and jsiOnnxruntimeResolveArrayBuffer to the module object instead of global? In general exporting to global is not preferred.
  • is the lifecycle of the allocated ArrayBuffers correctly managed? I want to make sure that buffers are not released too early (otherwise a UB in memory may happen) or too late/never (a memory leak)

@jhen0409
Copy link
Contributor Author

jhen0409 commented May 27, 2023

  • is there a way to export jsiOnnxruntimeStoreArrayBuffer and jsiOnnxruntimeResolveArrayBuffer to the module object instead of global? In general exporting to global is not preferred.

It probably can't, because the install function is use RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD not a JSI function, so we can't use JSI object as argument or return type.

The official way is use Turbo Native Module, but it required new architecture enabled and currently not stable.

We can just delete it in global after installation, but not perfect.

  • is the lifecycle of the allocated ArrayBuffers correctly managed? I want to make sure that buffers are not released too early (otherwise a UB in memory may happen) or too late/never (a memory leak)

Currently the implementation is take the ArrayBuffer constructor from JS, so it should be managed by the JS runtime. Also it remove blob in blobManager after it becomes ArrayBuffer.

For iOS, the blob (NSData*) should dealloc by ARC. For Android, the bytes reference (jbyte*) should managed by Java.

UPDATE: I found some memory leak issue on load model with my examples, not sure if it is related to this PR (it seems fine by patch this to v1.14), will investigate this.

@jhen0409
Copy link
Contributor Author

jhen0409 commented May 27, 2023

UPDATE: I found some memory leak issue on load model with my examples, not sure if it is related to this PR (it seems fine by patch this to v1.14), will investigate this.

Confirmed it is not related to this PR, looks like some load model behaviors are changed from v1.14, and it's bug I think. I'll open another issue or PR. (#16131)

fs-eire
fs-eire previously approved these changes May 27, 2023
Copy link
Contributor

@fs-eire fs-eire left a comment

Choose a reason for hiding this comment

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

I think it is good for the typescript part and my concerns are resolved. Please wait for @skottmckay review the android/ios part.

Copy link
Contributor

@YUNQIUGUO YUNQIUGUO left a comment

Choose a reason for hiding this comment

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

thanks for the contribution!

@skottmckay
Copy link
Contributor

/azp run Windows ARM64 QNN CI Pipeline,Windows CPU CI Pipeline,Windows GPU CI Pipeline,Windows GPU TensorRT CI Pipeline,ONNX Runtime Web CI Pipeline,Linux CPU CI Pipeline,Linux CPU Minimal Build E2E CI Pipeline,Linux GPU CI Pipeline,Linux GPU TensorRT CI Pipeline,Linux OpenVINO CI Pipeline

@skottmckay
Copy link
Contributor

/azp run Linux QNN CI Pipeline,MacOS CI Pipeline,orttraining-amd-gpu-ci-pipeline,orttraining-linux-ci-pipeline,orttraining-linux-gpu-ci-pipeline,orttraining-ortmodule-distributed,onnxruntime-python-checks-ci-pipeline,onnxruntime-binary-size-checks-ci-pipeline

@azure-pipelines
Copy link

Azure Pipelines successfully started running 7 pipeline(s).

@azure-pipelines
Copy link

Azure Pipelines successfully started running 10 pipeline(s).

@jhen0409
Copy link
Contributor Author

C:\a\_work\1\s\js\react_native\lib\backend.ts
  126:18  error  This assertion is unnecessary since it does not change the type of the expression  @typescript-eslint/no-unnecessary-type-assertion

✖ 1 problem (1 error, 0 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

Sorry about that, it doesn't happened in my environment, but it's the obvious part that can be corrected so I'll fix it.

@skottmckay
Copy link
Contributor

/azp run Windows ARM64 QNN CI Pipeline,Windows CPU CI Pipeline,Windows GPU CI Pipeline,Windows GPU TensorRT CI Pipeline,ONNX Runtime Web CI Pipeline,Linux CPU CI Pipeline,Linux CPU Minimal Build E2E CI Pipeline,Linux GPU CI Pipeline,Linux GPU TensorRT CI Pipeline,Linux OpenVINO CI Pipeline

@skottmckay
Copy link
Contributor

/azp run Linux QNN CI Pipeline,MacOS CI Pipeline,orttraining-amd-gpu-ci-pipeline,orttraining-linux-ci-pipeline,orttraining-linux-gpu-ci-pipeline,orttraining-ortmodule-distributed,onnxruntime-python-checks-ci-pipeline,onnxruntime-binary-size-checks-ci-pipeline

@azure-pipelines
Copy link

Azure Pipelines successfully started running 7 pipeline(s).

@azure-pipelines
Copy link

Azure Pipelines successfully started running 10 pipeline(s).

@skottmckay
Copy link
Contributor

/azp run Windows ARM64 QNN CI Pipeline,Windows CPU CI Pipeline,Windows GPU CI Pipeline,Windows GPU TensorRT CI Pipeline,ONNX Runtime Web CI Pipeline,Linux CPU CI Pipeline,Linux CPU Minimal Build E2E CI Pipeline,Linux GPU CI Pipeline,Linux GPU TensorRT CI Pipeline,Linux OpenVINO CI Pipeline

@skottmckay
Copy link
Contributor

/azp run Linux QNN CI Pipeline,MacOS CI Pipeline,orttraining-amd-gpu-ci-pipeline,orttraining-linux-ci-pipeline,orttraining-linux-gpu-ci-pipeline,orttraining-ortmodule-distributed,onnxruntime-python-checks-ci-pipeline,onnxruntime-binary-size-checks-ci-pipeline

@azure-pipelines
Copy link

Azure Pipelines successfully started running 7 pipeline(s).

@azure-pipelines
Copy link

Azure Pipelines successfully started running 10 pipeline(s).

@skottmckay
Copy link
Contributor

Sorry - the PR to fix the broken CI pipeline needed a second fix. That is now checked in and the pipeline has been passing for the last day. Could you please update to the latest main one more time? Apologies for the inconvenience.

@jhen0409
Copy link
Contributor Author

Sorry - the PR to fix the broken CI pipeline needed a second fix. That is now checked in and the pipeline has been passing for the last day. Could you please update to the latest main one more time? Apologies for the inconvenience.

OK, updated.

@skottmckay
Copy link
Contributor

/azp run Windows ARM64 QNN CI Pipeline,Windows CPU CI Pipeline,Windows GPU CI Pipeline,Windows GPU TensorRT CI Pipeline,ONNX Runtime Web CI Pipeline,Linux CPU CI Pipeline,Linux CPU Minimal Build E2E CI Pipeline,Linux GPU CI Pipeline,Linux GPU TensorRT CI Pipeline,Linux OpenVINO CI Pipeline

@skottmckay
Copy link
Contributor

/azp run Linux QNN CI Pipeline,MacOS CI Pipeline,orttraining-amd-gpu-ci-pipeline,orttraining-linux-ci-pipeline,orttraining-linux-gpu-ci-pipeline,orttraining-ortmodule-distributed,onnxruntime-python-checks-ci-pipeline,onnxruntime-binary-size-checks-ci-pipeline

@azure-pipelines
Copy link

Azure Pipelines successfully started running 7 pipeline(s).

@azure-pipelines
Copy link

Azure Pipelines successfully started running 10 pipeline(s).

@skottmckay skottmckay merged commit ea1a5cf into microsoft:main Jun 16, 2023
@jhen0409 jhen0409 deleted the jhen-rn-use-blob branch June 16, 2023 10:12
@YUNQIUGUO
Copy link
Contributor

Did we manually run the ONNX Runtime React Native CI pipeline on this pr before? I think this change breaks the react native E2E test again...

siweic0 pushed a commit to siweic0/onnxruntime-web that referenced this pull request May 9, 2024
…ft#16094)

### Description
<!-- Describe your changes. -->

- Create `OnnxruntimeJSIHelper` native module to provide two JSI
functions
- `jsiOnnxruntimeStoreArrayBuffer`: Store buffer in Blob Manager &
return blob object (iOS: RCTBlobManager, Android: BlobModule)
  - `jsiOnnxruntimeResolveArrayBuffer`: Use blob object to get buffer
- The part of implementation is reference to
[react-native-blob-jsi-helper](https://github.com/mrousavy/react-native-blob-jsi-helper)
- Replace base64 encode/decode
  - `loadModelFromBlob`: Rename from `loadModelFromBase64EncodedBuffer`
  - `run`: Use blob object to replace input.data & results[].data

For [this
context](microsoft#16031 (comment)),
it saved a lot of time and avoid JS thread blocking in decode return
type, it is 3700ms -> 5~20ms for the case. (resolve function only takes
0.x ms)

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

It’s related to microsoft#16031, but not a full implementation for migrate to
JSI.

It just uses JSI through BlobManager to replace the slow part (base64
encode / decode).

Rewriting it entirely in JSI could be complicated, like type convertion
and threading. This PR might be considered a minor change.

/cc @skottmckay
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.

4 participants