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

node-api: run finalizers directly from GC #42651

Closed
wants to merge 10 commits into from

Conversation

vmoroz
Copy link
Member

@vmoroz vmoroz commented Apr 8, 2022

The issue

Currently Reference finalizers are run inside of SetImmediate.
In case if user code creates a lot of native objects in the main script, it could cause a significant memory pressure, even if the objects are properly released. This is because they are "collected" only inside of SetImmediate that follows the script run.
See the issue: nodejs/node-addon-api#1140

In the a74a6e3 commit the processing of finalizers was moved from the GC second pass to the SetImmediate because:

  • finalizers may run some arbitrary JS code while some other JS code being executed.
  • finalizers may throw JavaScript exceptions which can affect behavior of other functions.

The solution

In this PR we are introducing new experimental behavior where the finalizers are run directly from the GC but they are not allowed to run JS code and must only call native code. Since the finalizers cannot affect the running JS code in any way, they are safe to run at any point.

  • When the finalizers run from GC, we disable running JS code and any Node-API that may run JS code.
  • Any unhandled Node-API error or JS exception will cause the process abort.

If a finalizer must run JS code, then it can do it by calling the new node_api_post_finalizer method which schedules the finalizer run in SetImmediate as it was before. The main difference is that previously we always scheduled finalizer runs in SetImmediate implicitly, and now code must do it explicitly.

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/node-api

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Apr 8, 2022
@mhdawson mhdawson added the node-api Issues and PRs related to the Node-API. label Apr 8, 2022
@KevinEady
Copy link
Contributor

Hi @nodejs/node-api ,

Can team members take a look at this PR and provide feedback to @vmoroz so he can understand if this approach works well before he continues going through unit tests and other implementation details? Thanks.

@vmoroz
Copy link
Member Author

vmoroz commented Apr 22, 2022

As we discussed today in Node-API meeting, one of the changes in this PR is the grouping of parameters inside of a new node_api_native_data struct. This struct should allow us to evolve the set of parameters that can be associate with native data. I had also mentioned that we must be able to create a C++ template function that converts C++ lambda to that struct. Such conversion would be difficult to do if the native data and finalizers are passed as function parameters. I am going to add a unit test to demo it.

@KevinEady
Copy link
Contributor

We discussed this in the 20 May Node-API meeting. This PR should be rebased and revalidated after #36510 has been merged since both PRs touch finalizer code.

@legendecas
Copy link
Member

legendecas commented Aug 9, 2022

As discussed in the last node-api meeting, it would be worth exploring the possibility of introducing behavior flags to the initialization of an addon to invoke the finalizers in a more eager manner and disallow JavaScript evaluations in the finalizers. In this way, users can still have one single type of finalizer and don't need to distinguish them. We also don't need to introduce a bunch of new apis just for different finalizers.

@KevinEady
Copy link
Contributor

We discussed in the 7 Oct Node API meeting that this PR is dependent on the feature-flags implementation inside #42557. Instead of adding the new methods (in PRs first post), we would be able to modify existing API behavior for object finalization.

Copy link
Contributor

@gabrielschulhof gabrielschulhof left a comment

Choose a reason for hiding this comment

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

As currently implemented, AFAICT this change is not dependent on feature flags, since it implements all new APIs. LGTM.

@gabrielschulhof gabrielschulhof dismissed their stale review May 13, 2023 22:08

I forgot that we were gonna force finalizers to be eager with a behaviour change and then provide an API to execute the JS portions immediately.

@vmoroz vmoroz changed the title node-api: split finalizers into two different types node-api: run finalizers directly from GC Jun 23, 2023
@vmoroz
Copy link
Member Author

vmoroz commented Jun 23, 2023

The latest commit changes the PR based on the latest discussions that we had in Node-API meetings:

  • In the new experimental version all finalizers are invoked directly from GC without access to JS.
  • New node_api_post_finalizer method is added to run finalizer code as a part of SetImmediate where it can access GC.

@vmoroz vmoroz marked this pull request as draft June 23, 2023 15:07
@vmoroz vmoroz changed the title node-api: run finalizers directly from GC node-api: (DRAFT) run finalizers directly from GC Jun 23, 2023
@vmoroz
Copy link
Member Author

vmoroz commented Jun 23, 2023

Changed status to DRAFT until I have the full set of tests and changes for the docs.
Otherwise, the rest of the code is in a relative good shape abd very close to the final change.

@vmoroz vmoroz changed the title node-api: (DRAFT) run finalizers directly from GC node-api: run finalizers directly from GC Jul 21, 2023
@vmoroz vmoroz marked this pull request as ready for review July 21, 2023 15:16
Copy link
Member

@mhdawson mhdawson left a comment

Choose a reason for hiding this comment

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

LGTM

@mhdawson mhdawson added the request-ci Add this label to start a Jenkins CI on a PR. label Sep 29, 2023
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Sep 29, 2023
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

mhdawson pushed a commit that referenced this pull request Oct 3, 2023
PR-URL: #42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
@mhdawson
Copy link
Member

mhdawson commented Oct 3, 2023

Landed in b38e312

@mhdawson mhdawson closed this Oct 3, 2023
@KevinEady
Copy link
Contributor

Congrats @vmoroz on getting this PR landed! This has been a long time in the making with several users wanting this type of functionality 😄

alexfernandez pushed a commit to alexfernandez/node that referenced this pull request Nov 1, 2023
PR-URL: nodejs#42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
targos pushed a commit that referenced this pull request Nov 11, 2023
PR-URL: #42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
targos pushed a commit that referenced this pull request Nov 27, 2023
PR-URL: #42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
debadree25 pushed a commit to debadree25/node that referenced this pull request Apr 15, 2024
PR-URL: nodejs#42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
sercher added a commit to sercher/graaljs that referenced this pull request Apr 25, 2024
PR-URL: nodejs/node#42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
sercher added a commit to sercher/graaljs that referenced this pull request Apr 25, 2024
PR-URL: nodejs/node#42651
Reviewed-By: Gabriel Schulhof <gabrielschulhof@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. node-api Issues and PRs related to the Node-API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants