GeezerVison is showing github.com — node-api: add property keys benchmark · nodejs/node@f755d31
File treeExpand file treeCollapse file tree Open diff view settings benchmark/napi/property_keys
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +build/ |
Collapse file Copy file name to clipboard +111Lines changed: 111 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +#include <node_api.h> | | 2 | +#include <stdio.h> | | 3 | +#include <stdlib.h> | | 4 | + | | 5 | +#define NODE_API_CALL(call) \ | | 6 | + do { \ | | 7 | + napi_status status = call; \ | | 8 | + if (status != napi_ok) { \ | | 9 | + fprintf(stderr, #call " failed: %d\n", status); \ | | 10 | + abort(); \ | | 11 | + } \ | | 12 | + } while (0) | | 13 | + | | 14 | +#define ABORT_IF_FALSE(condition) \ | | 15 | + if (!(condition)) { \ | | 16 | + fprintf(stderr, #condition " failed\n"); \ | | 17 | + abort(); \ | | 18 | + } | | 19 | + | | 20 | +static napi_value Runner(napi_env env, | | 21 | + napi_callback_info info, | | 22 | + napi_value property_key) { | | 23 | + napi_value argv[2], undefined, js_array_length, start, end; | | 24 | + size_t argc = 2; | | 25 | + napi_valuetype val_type = napi_undefined; | | 26 | + bool is_array = false; | | 27 | + uint32_t array_length = 0; | | 28 | + napi_value* native_array; | | 29 | + | | 30 | + // Validate params and retrieve start and end function. | | 31 | + NODE_API_CALL(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); | | 32 | + ABORT_IF_FALSE(argc == 2); | | 33 | + NODE_API_CALL(napi_typeof(env, argv[0], &val_type)); | | 34 | + ABORT_IF_FALSE(val_type == napi_object); | | 35 | + NODE_API_CALL(napi_is_array(env, argv[1], &is_array)); | | 36 | + ABORT_IF_FALSE(is_array); | | 37 | + NODE_API_CALL(napi_get_array_length(env, argv[1], &array_length)); | | 38 | + NODE_API_CALL(napi_get_named_property(env, argv[0], "start", &start)); | | 39 | + NODE_API_CALL(napi_typeof(env, start, &val_type)); | | 40 | + ABORT_IF_FALSE(val_type == napi_function); | | 41 | + NODE_API_CALL(napi_get_named_property(env, argv[0], "end", &end)); | | 42 | + NODE_API_CALL(napi_typeof(env, end, &val_type)); | | 43 | + ABORT_IF_FALSE(val_type == napi_function); | | 44 | + | | 45 | + NODE_API_CALL(napi_get_undefined(env, &undefined)); | | 46 | + NODE_API_CALL(napi_create_uint32(env, array_length, &js_array_length)); | | 47 | + | | 48 | + // Copy objects into a native array. | | 49 | + native_array = | | 50 | + static_cast<napi_value*>(malloc(array_length * sizeof(napi_value))); | | 51 | + for (uint32_t idx = 0; idx < array_length; idx++) { | | 52 | + NODE_API_CALL(napi_get_element(env, argv[1], idx, &native_array[idx])); | | 53 | + } | | 54 | + | | 55 | + // Start the benchmark. | | 56 | + napi_call_function(env, argv[0], start, 0, nullptr, nullptr); | | 57 | + | | 58 | + for (uint32_t idx = 0; idx < array_length; idx++) { | | 59 | + NODE_API_CALL( | | 60 | + napi_set_property(env, native_array[idx], property_key, undefined)); | | 61 | + } | | 62 | + | | 63 | + // Conclude the benchmark. | | 64 | + NODE_API_CALL( | | 65 | + napi_call_function(env, argv[0], end, 1, &js_array_length, nullptr)); | | 66 | + | | 67 | + free(native_array); | | 68 | + | | 69 | + return undefined; | | 70 | +} | | 71 | + | | 72 | +static napi_value RunPropertyKey(napi_env env, napi_callback_info info) { | | 73 | + napi_value property_key; | | 74 | + NODE_API_CALL(node_api_create_property_key_utf16( | | 75 | + env, u"prop", NAPI_AUTO_LENGTH, &property_key)); | | 76 | + return Runner(env, info, property_key); | | 77 | +} | | 78 | + | | 79 | +static napi_value RunNormalString(napi_env env, napi_callback_info info) { | | 80 | + napi_value property_key; | | 81 | + NODE_API_CALL( | | 82 | + napi_create_string_utf16(env, u"prop", NAPI_AUTO_LENGTH, &property_key)); | | 83 | + return Runner(env, info, property_key); | | 84 | +} | | 85 | + | | 86 | +NAPI_MODULE_INIT() { | | 87 | + napi_property_descriptor props[] = { | | 88 | + {"RunPropertyKey", | | 89 | + nullptr, | | 90 | + RunPropertyKey, | | 91 | + nullptr, | | 92 | + nullptr, | | 93 | + nullptr, | | 94 | + static_cast<napi_property_attributes>(napi_writable | napi_configurable | | | 95 | + napi_enumerable), | | 96 | + nullptr}, | | 97 | + {"RunNormalString", | | 98 | + nullptr, | | 99 | + RunNormalString, | | 100 | + nullptr, | | 101 | + nullptr, | | 102 | + nullptr, | | 103 | + static_cast<napi_property_attributes>(napi_writable | napi_configurable | | | 104 | + napi_enumerable), | | 105 | + nullptr}, | | 106 | + }; | | 107 | + | | 108 | + NODE_API_CALL(napi_define_properties( | | 109 | + env, exports, sizeof(props) / sizeof(*props), props)); | | 110 | + return exports; | | 111 | +} |
Collapse file Copy file name to clipboard +9Lines changed: 9 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +{ | | 2 | + 'targets': [ | | 3 | + { | | 4 | + 'target_name': 'binding', | | 5 | + 'sources': [ 'binding.cc' ], | | 6 | + 'defines': [ 'NAPI_EXPERIMENTAL' ], | | 7 | + } | | 8 | + ] | | 9 | +} |
Collapse file Copy file name to clipboard +15Lines changed: 15 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../../common.js'); | | 4 | + | | 5 | +const binding = require(`./build/${common.buildType}/binding`); | | 6 | + | | 7 | +const bench = common.createBenchmark(main, { | | 8 | + n: [5e6], | | 9 | + implem: ['RunPropertyKey', 'RunNormalString'], | | 10 | +}); | | 11 | + | | 12 | +function main({ n, implem }) { | | 13 | + const objs = Array(n).fill(null).map((item) => new Object()); | | 14 | + binding[implem](bench, objs); | | 15 | +} |
Collapse file Copy file name to clipboardExpand all lines: tools/build_addons.py +8-4Lines changed: 8 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -66,6 +66,7 @@ def node_gyp_rebuild(test_dir): | 66 | 66 | print(stdout.decode()) | 67 | 67 | if stderr: | 68 | 68 | print(stderr.decode()) | | 69 | + return return_code | 69 | 70 |
| 70 | 71 | except Exception as e: | 71 | 72 | print(f'Unexpected error when building addon in {test_dir}. Error: {e}') | @@ -86,7 +87,8 @@ def node_gyp_rebuild(test_dir): | 86 | 87 | test_dirs.append(full_path) | 87 | 88 |
| 88 | 89 | with ThreadPoolExecutor() as executor: | 89 | | - executor.map(node_gyp_rebuild, test_dirs) | | 90 | + codes = executor.map(node_gyp_rebuild, test_dirs) | | 91 | + return 0 if all(code == 0 for code in codes) else 1 | 90 | 92 |
| 91 | 93 | def get_default_out_dir(args): | 92 | 94 | default_out_dir = os.path.join('out', args.config) | @@ -131,17 +133,19 @@ def main(): | 131 | 133 | if not args.out_dir: | 132 | 134 | args.out_dir = get_default_out_dir(args) | 133 | 135 |
| | 136 | + exit_code = 1 | 134 | 137 | if args.headers_dir: | 135 | | - rebuild_addons(args) | | 138 | + exit_code = rebuild_addons(args) | 136 | 139 | else: | 137 | 140 | # When --headers-dir is not specified, generate headers into a temp dir and | 138 | 141 | # build with the new headers. | 139 | 142 | try: | 140 | 143 | args.headers_dir = tempfile.mkdtemp() | 141 | 144 | generate_headers(args.headers_dir, unknown_args) | 142 | | - rebuild_addons(args) | | 145 | + exit_code = rebuild_addons(args) | 143 | 146 | finally: | 144 | 147 | shutil.rmtree(args.headers_dir) | | 148 | + return exit_code | 145 | 149 |
| 146 | 150 | if __name__ == '__main__': | 147 | | - main() | | 151 | + sys.exit(main()) |
|