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

Use node-api instead of NAN #6452

Merged
merged 23 commits into from
Nov 16, 2022
Merged

Use node-api instead of NAN #6452

merged 23 commits into from
Nov 16, 2022

Conversation

SiarheiFedartsou
Copy link
Member

@SiarheiFedartsou SiarheiFedartsou commented Nov 11, 2022

Issue

closes #4118

The problem is that with nan we have to rebuild binary for each major node version, e.g. it is one of the reasons why we have no support for Node 18 on Windows(we could add one more job though on CI, but it requires a lot of boilerplate etc). After migration to Node-API our binaries will become "forward compatible", i.e. they will work with any new Node version which support NAPI version it was built with. Besides that node-api(to be precise its C++ wrapper node-addon-api we use here) has less verbose and more readable API rather than NAN.

Tasklist

Requirements / Relations

Link any requirements here. Other pull requests this PR is based on?

@SiarheiFedartsou
Copy link
Member Author

SiarheiFedartsou commented Nov 11, 2022

I was a bit afraid that it could cause some drop of performance, but I benchmarked it with quite simple script available in PR and it seems there are no any issues with this(it seems that Node API version is even slightly faster).

Result of benchmark.js(see code in PR) on this branch(numbers are in microseconds):

➜  osrm-backend git:(sf-node-api) ✗ sh bench.sh
Histogram {
  min: 5420,
  max: 9095,
  mean: 5616.318,
  exceeds: 0,
  stddev: 311.16782429422227,
  count: 1000,
  percentiles: SafeMap(12) [Map] {
    0 => 5420,
    50 => 5496,
    75 => 5624,
    87.5 => 5824,
    93.75 => 6140,
    96.875 => 6324,
    98.4375 => 6768,
    99.21875 => 7100,
    99.609375 => 7692,
    99.8046875 => 7992,
    99.90234375 => 9088,
    100 => 9088
  }
}
➜  osrm-backend git:(sf-node-api) ✗ sh bench.sh
Histogram {
  min: 5416,
  max: 7163,
  mean: 5512.436,
  exceeds: 0,
  stddev: 129.44126816436867,
  count: 1000,
  percentiles: SafeMap(12) [Map] {
    0 => 5416,
    50 => 5468,
    75 => 5516,
    87.5 => 5588,
    93.75 => 5656,
    96.875 => 5824,
    98.4375 => 6012,
    99.21875 => 6136,
    99.609375 => 6380,
    99.8046875 => 6576,
    99.90234375 => 7160,
    100 => 7160
  }
}
➜  osrm-backend git:(sf-node-api) ✗ sh bench.sh
Histogram {
  min: 5436,
  max: 8367,
  mean: 5692.902,
  exceeds: 0,
  stddev: 334.17535276558027,
  count: 1000,
  percentiles: SafeMap(12) [Map] {
    0 => 5436,
    50 => 5520,
    75 => 5828,
    87.5 => 6028,
    93.75 => 6268,
    96.875 => 6440,
    98.4375 => 6792,
    99.21875 => 7008,
    99.609375 => 7460,
    99.8046875 => 8048,
    99.90234375 => 8360,
    100 => 8360
  }
}

On master:

➜  osrm-backend git:(master) ✗ sh bench.sh
Histogram {
  min: 5500,
  max: 8639,
  mean: 5884.29,
  exceeds: 0,
  stddev: 271.74253973200445,
  count: 1000,
  percentiles: SafeMap(12) [Map] {
    0 => 5500,
    50 => 5820,
    75 => 6004,
    87.5 => 6104,
    93.75 => 6284,
    96.875 => 6532,
    98.4375 => 6780,
    99.21875 => 6932,
    99.609375 => 7304,
    99.8046875 => 7480,
    99.90234375 => 8632,
    100 => 8632
  }
}
➜  osrm-backend git:(master) ✗ sh bench.sh
Histogram {
  min: 5492,
  max: 7891,
  mean: 5854.16,
  exceeds: 0,
  stddev: 246.93598846664702,
  count: 1000,
  percentiles: SafeMap(12) [Map] {
    0 => 5492,
    50 => 5804,
    75 => 5976,
    87.5 => 6060,
    93.75 => 6172,
    96.875 => 6436,
    98.4375 => 6664,
    99.21875 => 6808,
    99.609375 => 7232,
    99.8046875 => 7636,
    99.90234375 => 7888,
    100 => 7888
  }
}
➜  osrm-backend git:(master) ✗ sh bench.sh
Histogram {
  min: 5456,
  max: 9703,
  mean: 5886.806,
  exceeds: 0,
  stddev: 271.55144331047114,
  count: 1000,
  percentiles: SafeMap(12) [Map] {
    0 => 5456,
    50 => 5852,
    75 => 6008,
    87.5 => 6092,
    93.75 => 6172,
    96.875 => 6384,
    98.4375 => 6696,
    99.21875 => 6996,
    99.609375 => 7272,
    99.8046875 => 7712,
    99.90234375 => 9696,
    100 => 9696
  }
}

In both cases OSRM was built as cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=ON .. && ninja

Full code of benchmark(route from Gdansk to Krakow, i.e. ~600km):

REGION=poland-latest

mkdir -p $REGION
cd $REGION
wget http://download.geofabrik.de/europe/$REGION.osm.pbf
../build/osrm-extract --profile ../profiles/car.lua $REGION.osm.pbf
../build/osrm-partition ./$REGION
../build/osrm-customize ./$REGION
cd ..


node test/nodejs/benchmark.js $REGION/$REGION.osrm "18.638306,54.372158;19.944544,50.049683"

Node Version which was used:

➜  osrm-backend git:(master) ✗ node --version
v18.7.0

Hardware:

Macbook Pro with Apple M1 Pro and 32 gb RAM

},
"main": "lib/index.js",
"binary": {
"napi_versions": [8],
Copy link
Member Author

Choose a reason for hiding this comment

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

Version 8 is the latest and it is compatible with any Node version we currently support:
Screenshot 2022-11-12 at 11 57 08
https://nodejs.org/api/n-api.html#node-api-version-matrix

"module_name": "node_osrm",
"module_path": "./lib/binding/",
"module_path": "./lib/binding_napi_v{napi_build_version}/",
Copy link
Member Author

Choose a reason for hiding this comment

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

node-pre-gyp is designed to support multiple NAPI versions, that's why they require NAPI version to be part of module_path(as I understand it may be needed if you want to use some features from new versions of NAPI, but still provide builds for older Node versions which do not support this new version of NAPI) https://github.com/mapbox/node-pre-gyp#the-napi_versions-array-property

@@ -21,6 +25,14 @@ set_target_properties(node_osrm PROPERTIES CXX_CLANG_TIDY "")
target_no_warning(node_osrm suggest-destructor-override)
target_no_warning(node_osrm suggest-override)

# https://github.com/cjntaylor/node-cmake/issues/53#issuecomment-842357457
Copy link
Member Author

Choose a reason for hiding this comment

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

We could use https://github.com/cmake-js/cmake-js here which is recommended by Node API docs, but it would require much more refactoring in the way how we build our binaries: they force us to use their own node script to run cmake commands what is not very convenient.

}
}

inline bool IsUnsignedInteger(const Napi::Value &value)
Copy link
Member Author

Choose a reason for hiding this comment

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

Node API doesn't distinguish integers and floats, so I had to add this to be compatible with some input parameter checks we had before.

npm run nodejs-tests
- name: Use Node 18
Copy link
Member Author

Choose a reason for hiding this comment

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

Paranoia check that resulting binary is compatible with any Node version we currently support. I am going to revisit it and probably try to do it in more elegant and less verbose way(probably we can use nvm instead of GitHub actions in order to switch Node versions)

@SiarheiFedartsou
Copy link
Member Author

Hi @mjjbell @DennisOSRM
I believe there are some things to be polished in this PR, but lets may be have preliminary review/discussion and the finish it :) Do you see any red flags with this PR?

@SiarheiFedartsou SiarheiFedartsou marked this pull request as ready for review November 12, 2022 11:18
@@ -264,83 +264,7 @@ jobs:
CXXCOMPILER: g++-8
CXXFLAGS: -Wno-cast-function-type

- name: conan-macos-x64-release-node-16
Copy link
Member Author

@SiarheiFedartsou SiarheiFedartsou Nov 12, 2022

Choose a reason for hiding this comment

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

This PR allowed to get rid from this extra jobs, but at the same time we can now be compatible with more Node versions.

@DennisOSRM
Copy link
Collaborator

Hi @mjjbell @DennisOSRM
I believe there are some things to be polished in this PR, but lets may be have preliminary review/discussion and the finish it :) Do you see any red flags with this PR?

No red flags from my side.

@SiarheiFedartsou SiarheiFedartsou merged commit 18dcd27 into master Nov 16, 2022
mattwigway pushed a commit to mattwigway/osrm-backend that referenced this pull request Jul 20, 2023
@DennisOSRM DennisOSRM deleted the sf-node-api branch May 3, 2024 12:30
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.

Eventually switch node-osrm to Node.js's ABI stable N-API
2 participants