[js/node] support manually dispose session (#18655)

### Description
support manually dispose session in onnxruntime-node

feature request: #16796
This commit is contained in:
Yulong Wang 2023-12-19 16:20:00 -08:00 committed by GitHub
parent 98510fb8fb
commit ffa6602686
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 2 deletions

View file

@ -20,7 +20,7 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler {
}
async dispose(): Promise<void> {
return Promise.resolve();
this.#inferenceSession.dispose();
}
readonly inputNames: string[];

View file

@ -28,6 +28,8 @@ export declare namespace Binding {
readonly outputNames: string[];
run(feeds: FeedsType, fetches: FetchesType, options: RunOptions): ReturnType;
dispose(): void;
}
export interface InferenceSessionConstructor {

View file

@ -31,6 +31,7 @@ Napi::Object InferenceSessionWrap::Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(
env, "InferenceSession",
{InstanceMethod("loadModel", &InferenceSessionWrap::LoadModel), InstanceMethod("run", &InferenceSessionWrap::Run),
InstanceMethod("dispose", &InferenceSessionWrap::Dispose),
InstanceAccessor("inputNames", &InferenceSessionWrap::GetInputNames, nullptr, napi_default, nullptr),
InstanceAccessor("outputNames", &InferenceSessionWrap::GetOutputNames, nullptr, napi_default, nullptr)});
@ -45,7 +46,7 @@ Napi::Object InferenceSessionWrap::Init(Napi::Env env, Napi::Object exports) {
}
InferenceSessionWrap::InferenceSessionWrap(const Napi::CallbackInfo &info)
: Napi::ObjectWrap<InferenceSessionWrap>(info), initialized_(false), session_(nullptr),
: Napi::ObjectWrap<InferenceSessionWrap>(info), initialized_(false), disposed_(false), session_(nullptr),
defaultRunOptions_(nullptr) {}
Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) {
@ -53,6 +54,7 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) {
Napi::HandleScope scope(env);
ORT_NAPI_THROW_ERROR_IF(this->initialized_, env, "Model already loaded. Cannot load model multiple times.");
ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed.");
size_t argsLength = info.Length();
ORT_NAPI_THROW_TYPEERROR_IF(argsLength == 0, env, "Expect argument: model file path or buffer.");
@ -129,6 +131,7 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) {
Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized.");
ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed.");
Napi::EscapableHandleScope scope(env);
return scope.Escape(CreateNapiArrayFrom(env, inputNames_));
@ -137,6 +140,7 @@ Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo &info)
Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized.");
ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed.");
Napi::EscapableHandleScope scope(env);
return scope.Escape(CreateNapiArrayFrom(env, outputNames_));
@ -145,6 +149,7 @@ Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo &info)
Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized.");
ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed.");
ORT_NAPI_THROW_TYPEERROR_IF(info.Length() < 2, env, "Expect argument: inputs(feed) and outputs(fetch).");
ORT_NAPI_THROW_TYPEERROR_IF(!info[0].IsObject() || !info[1].IsObject(), env,
"Expect inputs(feed) and outputs(fetch) to be objects.");
@ -209,6 +214,18 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo &info) {
}
}
Napi::Value InferenceSessionWrap::Dispose(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized.");
ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed.");
this->defaultRunOptions_.reset(nullptr);
this->session_.reset(nullptr);
this->disposed_ = true;
return env.Undefined();
}
Napi::Value InferenceSessionWrap::ListSupportedBackends(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Napi::EscapableHandleScope scope(env);

View file

@ -55,6 +55,14 @@ private:
*/
Napi::Value Run(const Napi::CallbackInfo &info);
/**
* [sync] dispose the session.
* @param nothing
* @returns nothing
* @throw nothing
*/
Napi::Value Dispose(const Napi::CallbackInfo &info);
// private members
// persistent constructor
@ -62,6 +70,7 @@ private:
// session objects
bool initialized_;
bool disposed_;
std::unique_ptr<Ort::Session> session_;
std::unique_ptr<Ort::RunOptions> defaultRunOptions_;