From 715b29357ae43db2cda58ca6700b0c76923e4174 Mon Sep 17 00:00:00 2001 From: Yulong Wang Date: Fri, 4 May 2018 12:27:09 -0700 Subject: [PATCH 01/17] Set 'this' reference to module.exports in module's top level code (#232) --- src/module/loader/javascript-module-loader.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/module/loader/javascript-module-loader.cpp b/src/module/loader/javascript-module-loader.cpp index 290d32f4..33329462 100644 --- a/src/module/loader/javascript-module-loader.cpp +++ b/src/module/loader/javascript-module-loader.cpp @@ -49,7 +49,16 @@ bool JavascriptModuleLoader::TryGet(const std::string& path, v8::Local wrappedSource = v8::String::Concat( + v8_helpers::MakeV8String(isolate, "(function(){"), + v8::String::Concat( + source, + v8_helpers::MakeV8String(isolate, "}).apply(module.exports);") + ) + ); + auto script = v8::Script::Compile(wrappedSource, &origin); if (script.IsEmpty() || tryCatch.HasCaught()) { tryCatch.ReThrow(); return false; From 0c621aa1131ac2006098573f5d73bc424e23cba0 Mon Sep 17 00:00:00 2001 From: Allen Yongshuang Wang Date: Wed, 9 May 2018 12:12:40 -0700 Subject: [PATCH 02/17] fix and re-enable builtin type transportation (#235) --- src/v8-extensions/deserializer.cpp | 32 +++++++++++++++++++++++++++++- src/v8-extensions/deserializer.h | 10 +++++++++- test/transport-test.ts | 7 +++---- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/v8-extensions/deserializer.cpp b/src/v8-extensions/deserializer.cpp index c24071af..c15a1056 100644 --- a/src/v8-extensions/deserializer.cpp +++ b/src/v8-extensions/deserializer.cpp @@ -26,6 +26,8 @@ MaybeLocal Deserializer::ReadValue() { return MaybeLocal(); } +#if !V8_VERSION_EQUALS_TO_OR_NEWER_THAN(6, 6) + uint32_t index = 0; Local key = v8_helpers::MakeV8String(_isolate, "_externalized"); for (const auto& contents : _data->GetExternalizedSharedArrayBufferContents()) { @@ -40,10 +42,38 @@ MaybeLocal Deserializer::ReadValue() { _deserializer.TransferSharedArrayBuffer(index++, sharedArrayBuffers); } +#endif + return _deserializer.ReadValue(context); } -Deserializer* Deserializer::NewDeserializer(v8::Isolate* isolate, std::shared_ptr data) { +#if V8_VERSION_EQUALS_TO_OR_NEWER_THAN(6, 6) + +MaybeLocal Deserializer::GetSharedArrayBufferFromId( + Isolate* isolate, uint32_t cloneId) { + if (_data && cloneId < _data->GetExternalizedSharedArrayBufferContents().size()) { + auto externalizedSharedArrayBufferContents = _data->GetExternalizedSharedArrayBufferContents().at(cloneId); + SharedArrayBuffer::Contents contents = externalizedSharedArrayBufferContents.first; + auto sharedArrayBuffer = SharedArrayBuffer::New(isolate, contents.Data(), contents.ByteLength()); + + // After deserialization of a SharedArrayBuffer from its SerializedData, + // set its '_externalized' property to a ShareableWrap of its ExternalizedContents. + // This extends the lifecycle of the ExternalizedContents + // by the lifetime of the restored SharedArrayBuffer object. + Local context = _isolate->GetCurrentContext(); + Local key = v8_helpers::MakeV8String(_isolate, "_externalized"); + auto shareableWrap = napa::module::binding::CreateShareableWrap(externalizedSharedArrayBufferContents.second); + sharedArrayBuffer->CreateDataProperty(context, key, shareableWrap); + return sharedArrayBuffer; + } + else { + return MaybeLocal(); + } +} + +#endif + +Deserializer* Deserializer::NewDeserializer(Isolate* isolate, std::shared_ptr data) { return new Deserializer(isolate, data); } diff --git a/src/v8-extensions/deserializer.h b/src/v8-extensions/deserializer.h index 38e9c4ee..406c40c2 100644 --- a/src/v8-extensions/deserializer.h +++ b/src/v8-extensions/deserializer.h @@ -24,7 +24,15 @@ namespace v8_extensions { v8::MaybeLocal ReadValue(); - static Deserializer* NewDeserializer(v8::Isolate* isolate, std::shared_ptr data); +#if V8_VERSION_EQUALS_TO_OR_NEWER_THAN(6, 6) + + v8::MaybeLocal GetSharedArrayBufferFromId( + v8::Isolate* isolate, uint32_t cloneId) override; + +#endif + + static Deserializer* NewDeserializer( + v8::Isolate* isolate, std::shared_ptr data); private: v8::Isolate* _isolate; diff --git a/test/transport-test.ts b/test/transport-test.ts index 924293f5..87bdbf2a 100644 --- a/test/transport-test.ts +++ b/test/transport-test.ts @@ -341,12 +341,11 @@ describe('napajs/transport', () => { let builtinTestGroup = 'Transport built-in objects'; let nodeVersionMajor = parseInt(process.versions.node.split('.')[0]); - - // TODO #223: Fix transportation support for builtin types, which is broken due to breaking changes of v8 introduced from node v10.0.0. - if (nodeVersionMajor == 9) { + + if (nodeVersionMajor >= 9) { describe(builtinTestGroup, transportBuiltinObjects); } else { describe.skip(builtinTestGroup, transportBuiltinObjects); - require('npmlog').warn(builtinTestGroup, 'This test group is skipped since it requires node v9.0.0 .'); + require('npmlog').warn(builtinTestGroup, 'This test group is skipped since it requires node v9.0.0 or above.'); } }); From 833b3840f19561feec9e76e20be9e4e73a55dbeb Mon Sep 17 00:00:00 2001 From: Yulong Wang Date: Fri, 18 May 2018 17:22:13 -0700 Subject: [PATCH 03/17] Fix assert.ifError() usage in test (#233) --- test/module-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/module-test.ts b/test/module-test.ts index 1a2e57e1..e809cd8b 100644 --- a/test/module-test.ts +++ b/test/module-test.ts @@ -177,7 +177,7 @@ describe('napajs/module', function () { var fs = require('fs'); assert(fs.existsSync(__dirname + '/module/jsmodule.js')); - assert.ifError(fs.existsSync(__dirname + '/non-existing-file.txt')); + assert(!fs.existsSync(__dirname + '/non-existing-file.txt')); }); }); From f337e2c6d24de112be31b3b636f4d7beac016fa2 Mon Sep 17 00:00:00 2001 From: Daniel Hegeman Date: Mon, 23 Jul 2018 02:02:54 -0500 Subject: [PATCH 04/17] Add cmake-js to devDependencies (#246) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index ba2314bc..a305c5b0 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "semver": "^5.5.0" }, "devDependencies": { + "cmake-js": "^3.7.3", "node-pre-gyp-github": "^1.3.1", "mocha": "^3.5.0", "typescript": "^2.4.2", From 8cb06f1922ec15b00633e145e9ba413d12af833d Mon Sep 17 00:00:00 2001 From: Josef Malacka Jr Date: Mon, 8 Oct 2018 20:21:03 +0200 Subject: [PATCH 05/17] Added periods to end of sentences in Features. Added periods to end of sentences in Features. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bd53f75f..64b6b57f 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ More examples: * [Synchronized loading](./examples/tutorial/synchronized-loading) ## Features -- Multi-threaded JavaScript runtime -- Node.js compatible module architecture with NPM support -- API for object transportation, object sharing and synchronization across JavaScript threads -- API for pluggable logging, metric and memory allocator -- Distributed as a Node.js module, as well as supporting embed scenarios +- Multi-threaded JavaScript runtime. +- Node.js compatible module architecture with NPM support. +- API for object transportation, object sharing and synchronization across JavaScript threads. +- API for pluggable logging, metric and memory allocator. +- Distributed as a Node.js module, as well as supporting embed scenarios. ## Documentation - [Napa.js Home](https://github.com/Microsoft/napajs/wiki) From 96dd2e530a741b074771e6c4b4ba897fc0bd30b0 Mon Sep 17 00:00:00 2001 From: Aman Kumar Gupta Date: Mon, 8 Oct 2018 23:52:06 +0530 Subject: [PATCH 06/17] Fixed grammatical errors. (#262) --- docs/api/metric.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/metric.md b/docs/api/metric.md index 115fa1db..abff44cf 100644 --- a/docs/api/metric.md +++ b/docs/api/metric.md @@ -23,9 +23,9 @@ A metric has its identity containing following information: - **Section**: The group or category of the metric. - **Name**: Name of the metric. Section/Name combination should be unique in the system. - **Type**: Type of the metric, which can be - - *Number*: A absolute number, e.g: PrivateBytes. + - *Number*: An absolute number, e.g: PrivateBytes. - *Rate*: A flowing volume in number, e.g: QueryPerSecond. - - *Percentile*: A absolute number that needs to be sampled by percentiles, e.g: SuccessLatency. + - *Percentile*: An absolute number that needs to be sampled by percentiles, e.g: SuccessLatency. - **Dimensions**: A metric can have multiple dimensions, each dimension can bind with a string value at runtime. e.g: IncomingRequestRate can have 2 dimensions: ['client-id', 'request-type']. Metrics are process-wise objects, which can be used across [zones](./zone.md#intro). @@ -40,7 +40,7 @@ Metrics are process-wise objects, which can be used across [zones](./zone.md#int Percentile, }; - /// Interface to represents a multi-dimensional metric with a maximum dimensionality of 64. + /// Interface to represent a multi-dimensional metric with a maximum dimensionality of 64. class Metric { public: From 69b6d889de5973b1a50e783c51205f490fe15fca Mon Sep 17 00:00:00 2001 From: Akshit Bhalla Date: Tue, 9 Oct 2018 00:00:41 +0530 Subject: [PATCH 07/17] Fix Markdown and grammar (#261) Corrected typos and grammar. Also made the Markdown lists more consistent. --- docs/design/transport-js-builtins.md | 66 ++++++++++++++-------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/docs/design/transport-js-builtins.md b/docs/design/transport-js-builtins.md index 84e1fd48..67ea48c4 100644 --- a/docs/design/transport-js-builtins.md +++ b/docs/design/transport-js-builtins.md @@ -1,22 +1,22 @@ # Transport JavaScript standard built-in objects ## Incentives -The abstraction of 'Transportable' lies in the center of napa.js to efficiently share objects between JavaScript VMs (napa workers). Except JavaScript primitive types, an object needs to implement 'Transportable' interface to make it transportable. It means [Javascript standard built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) are not transportable unless wrappers or equivalent implementations for them are implemented by extending 'Transportable' interface. Developing cost for all those objects is not trivial, and new abstraction layer (wrappers or equivalent implementations) will bring barriers for users to learn and adopt these new stuffs. Moreover, developers also need to deal with the interaction between JavaScript standards objects and those wrappers or equivalent implementations. +The abstraction of 'Transportable' lies in the center of Napa.js to efficiently share objects between JavaScript VMs (Napa workers). Except JavaScript primitive types, an object needs to implement 'Transportable' interface to make it transportable. It means [JavaScript standard built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) are not transportable unless wrappers or equivalent implementations for them are implemented by extending 'Transportable' interface. The development cost for these objects is not trivial, and new abstraction layer (wrappers or equivalent implementations) will create barriers for users to learn and adopt these new things. Moreover, developers also need to deal with the interaction between JavaScript standards objects and those wrappers or equivalent implementations. The incentive of this design is to provide a solution to make JavaScript standard built-in objects transportable with requirements listed in the Goals section. -At the first stage, we will focus on an efficient solution to share data between napa workers. Basically, it is about making SharedArrayBuffer / TypedArray / DataView transportable. +At the first stage, we will focus on an efficient solution to share data between Napa workers. Basically, it is about making SharedArrayBuffer / TypedArray / DataView transportable. ## Goals Make Javascript standard built-in objects transportable with -- an efficient way to share structured data, like SharedArrayBuffer, among napa workers -- consistent APIs with ECMA standards -- no new abstraction layers for the simplest usage -- the least new concepts for advanced usage -- a scalable solution to make all Javascript standard built-in objects transportable, avoiding to make them transportable one by one. +- An efficient way to share structured data, like SharedArrayBuffer, among Napa workers +- Consistent APIs with ECMA standards +- No new abstraction layers for the simplest usage +- The least new concepts for advanced usage +- A scalable solution to make all JavaScript standard built-in objects transportable, avoiding to make them transportable one by one. ## Example -The below example shows how SharedArrayBuffer object is transported across multiple napa workers. It will print the TypedArray 'ta' created from a SharedArrayBuffer, with all its elements set to 100 from different napa workers. +The below example shows how SharedArrayBuffer object is transported across multiple Napa workers. It will print the TypedArray 'ta' created from a SharedArrayBuffer, with all its elements set to 100 from different Napa workers. ```js var napa = require("napajs"); var zone = napa.zone.create('zone', { workers: 4 }); @@ -45,28 +45,28 @@ run(); ``` ## Solution -Here we just give a high level description of the solution. Its api will go to docs/api/transport. +Here we just give a high-level description of the solution. Its API will go to [docs/api/transport](https://github.com/Microsoft/napajs/blob/master/docs/api/transport.md). - V8 provides its value-serialization mechanism by ValueSerializer and ValueDeserializer, which is compatible with the HTML structured clone algorithm. It is a horizontal solution to serialize / deserialize JavaScript objects. ValueSerializer::Delegate and ValueDeserializer::Delegate are their inner class. They work as base classes from which developers can deprive to customize some special handling of external / shared resources, like memory used by a SharedArrayBuffer object. - napa::v8_extensions::ExternalizedContents -> 1. It holds the externalized contents (memory) of a SharedArrayBuffer instance once it is serialized via napa::v8_extensions::Utils::SerializeValue(). -> 2. Only 1 instance of ExternalizedContents wil be generated for each SharedArrayBuffer. If a SharedArrayBuffer had been externalized, it will reuse the ExternalizedContents instance created before in napa::v8_extensions::Utils::SerializeValue() + - It holds the externalized contents (memory) of a SharedArrayBuffer instance once it is serialized via napa::v8_extensions::Utils::SerializeValue(). + - Only 1 instance of ExternalizedContents wil be generated for each SharedArrayBuffer. If a SharedArrayBuffer had been externalized, it will reuse the ExternalizedContents instance created before in napa::v8_extensions::Utils::SerializeValue() - napa::v8_extensions::SerializedData -> 1. It is generated by napa::v8_extensions::Utils::SerializeValue(). It holds the serialized data of a JavaScript object, which is required during its deserialization. + - It is generated by napa::v8_extensions::Utils::SerializeValue(). It holds the serialized data of a JavaScript object, which is required during its deserialization. - BuiltInObjectTransporter -> 1. napa::v8_extensions::Serializer, derived from v8::ValueSerializer::Delegate -> 2. napa::v8_extensions::Deserializer, derived from v8::ValueDeserializer::Delegate -> 3. static std::shared_ptr v8_extensions::Utils::SerializeValue(Isolate* isolate, Local value); ->>> Generate the SerializedData instance given an input value. ->>> If any SharedArrayBuffer instances exist in the input value, their ExternalizedContents instances will be generated and attached to the ShareArrayBuffer instances respectively. -> 4. static MaybeLocal v8_extensions::Utils::DeserializeValue(Isolate* isolate, std::shared_ptr data); ->>> Restore a JavaScript value from its SerializedData instance generated by v8_extensions::Utils::SerializeValue() before. + - napa::v8_extensions::Serializer, derived from v8::ValueSerializer::Delegate + - napa::v8_extensions::Deserializer, derived from v8::ValueDeserializer::Delegate + - static std::shared_ptr v8_extensions::Utils::SerializeValue(Isolate* isolate, Local value) + - Generate the SerializedData instance given an input value. + - If any SharedArrayBuffer instances exist in the input value, their ExternalizedContents instances will be generated and attached to the ShareArrayBuffer instances respectively. + - static MaybeLocal v8_extensions::Utils::DeserializeValue(Isolate* isolate, std::shared_ptr data); + - Restore a JavaScript value from its SerializedData instance generated by v8_extensions::Utils::SerializeValue() before. -- Currently, napa relies on Transportable API and a registered constructor to make an object transportable. In [marshallTransform](https://github.com/Microsoft/napajs/blob/master/lib/transport/transport.ts), when a JavaScript object is detected to have a registered constructor, it will go with napa way to marshall this object with the help of a TransportContext object, otherwise a non-transportable error is thrown. +- Currently, Napa relies on Transportable API and a registered constructor to make an object transportable. In [marshallTransform](https://github.com/Microsoft/napajs/blob/master/lib/transport/transport.ts), when a JavaScript object is detected to have a registered constructor, it will go with Napa way to marshall this object with the help of a TransportContext object, otherwise a non-transportable error is thrown. -- Instead of throwing an Error when no registered constructor is detected, the above mentioned BuiltInObjectTransporter can jump in to help marshall this object. We can use a whitelist of object types to restrict this solution to those verified types at first. +- Instead of throwing an error when no registered constructor is detected, the BuiltInObjectTransporter can help handle this object. We can use a whitelist of object types to restrict this solution to those verified types at first. ```js export function marshallTransform(jsValue: any, context: transportable.TransportContext): any { if (jsValue != null && typeof jsValue === 'object' && !Array.isArray(jsValue)) { @@ -111,25 +111,23 @@ function unmarshallTransform(payload: any, context: transportable.TransportConte } ``` -- Life cycle of SharedArrayBuffer (SAB) -> 1. When a SAB participates transportation among napa workers, its life cycle will be extended till the last reference this SAB. The reference of a SAB could be ->>> 1) a SAB object in its original isolate. +#### Lifecycle of SharedArrayBuffer (SAB) +- When a SAB participates transportation among Napa workers, its life cycle will be extended till the last reference this SAB. The reference of a SAB could be: + - SAB object in its original isolate. + - Received SAB transported from another Napa workers, including node zone of Napa. + - TypedArray or DataView created from the original SAB or a received SAB. ->>> 2) a received SAB transported from another napa workers, including node zone of napa. +- The life cycle extension during transportation is achieved through the ExternalizedContents SharedPtrWrap of the SAB. + - When a SAB is transported for the first time, it will be externalized and its ExternalizedContents will be stored in its SerializedData. At the same time, the SharedPtrWrap of the ExternalizedContents will be set to the '_externalized' property of the original SAB. ->>> 3) a TypedArray or DataView created from the original SAB or a received SAB. + - When a SAB is transported for the second time or later, it wil skip externalization and find its ExternalizedContents from its '_externalized' property, and store it to its SerializedData. -> 2. The life cycle extension during transportation is achieved through the ExternalizedContents SharedPtrWrap of the SAB. ->>> 1) When a SAB is transported for the first time, it will be externalized and its ExternalizedContents will be stored in its SerializedData. At the same time, the SharedPtrWrap of the ExternalizedContents will be set to the '_externalized' property of the original SAB. + - When a Napa worker tries to restore a transported SAB, it will find the pre-stored ExternalizedContents, and create a SharedPtrWrap for it, then set it to the to-be-restored SAB. ->>> 2) When a SAB is transported for the second time or later, it wil skip externalization and find its ExternalizedContents from its '_externalized' property, and store it to its SerializedData. - ->>> 3) When a napa worker try to restored a transported SAB, it will find the pre-stored ExternalizedContents, and create a SharedPtrWrap for it, then set it to the to-be-restored SAB. - ->>> 4) The life cycle of the SharedArrayBuffer is extended by the SharedPtrWrap of its ExternalizedContents. + - The life cycle of the SharedArrayBuffer is extended by the SharedPtrWrap of its ExternalizedContents. ## Constraints The above solution is based on the serialization / deserialization mechanism of V8. It may have the following constraints. - Not all [JavaScripts standard built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) are supported by Node (as a dependency of Napa in node mode) or V8 of a given version. We only provide transporting solution for those mature object types. -- Up to present, Node does not explicitly support multiple V8 isolates. There might be inconsistency to transport objects between node zone and napa zones. Extra effort might be required to make it consistent. +- Presently, Node does not explicitly support multiple V8 isolates. There may be inconsistencies in transporting objects between Node zones and Napa zones. Extra effort might be required to make it consistent. From 7a6f354b24aa14042072a6ac53be1256d582a0c8 Mon Sep 17 00:00:00 2001 From: amiya-1998 Date: Tue, 23 Oct 2018 00:09:44 +0530 Subject: [PATCH 08/17] Started sentence with 'A' instead of 'a'. (#264) --- src/api/capi.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/api/capi.cpp b/src/api/capi.cpp index 2431c45a..83807b9e 100644 --- a/src/api/capi.cpp +++ b/src/api/capi.cpp @@ -25,7 +25,7 @@ using namespace napa; static std::atomic _initialized(false); static settings::PlatformSettings _platformSettings; -/// a simple wrapper around Zone for managing lifetime using shared_ptr. +/// A simple wrapper around Zone for managing lifetime using shared_ptr. struct napa_zone { std::string id; std::shared_ptr zone; @@ -40,7 +40,7 @@ napa_zone_handle napa_zone_create(napa_string_ref id) { napa_zone_handle napa_zone_get(napa_string_ref id) { NAPA_ASSERT(_initialized, "Napa wasn't initialized"); - + auto zoneId = NAPA_STRING_REF_TO_STD_STRING(id); std::shared_ptr zone; if (zoneId == "node") { @@ -105,7 +105,7 @@ napa_result_code napa_zone_release(napa_zone_handle handle) { napa_string_ref napa_zone_get_id(napa_zone_handle handle) { NAPA_ASSERT(_initialized, "Napa platform wasn't initialized"); NAPA_ASSERT(handle, "Zone handle is null"); - + return STD_STRING_TO_NAPA_STRING_REF(handle->id); } @@ -120,14 +120,14 @@ void napa_zone_broadcast(napa_zone_handle handle, FunctionSpec req; req.module = spec.module; req.function = spec.function; - + req.arguments.reserve(spec.arguments_count); for (size_t i = 0; i < spec.arguments_count; i++) { req.arguments.emplace_back(spec.arguments[i]); } req.options = spec.options; - + // Assume ownership of transport context req.transportContext.reset(reinterpret_cast(spec.transport_context)); @@ -137,7 +137,7 @@ void napa_zone_broadcast(napa_zone_handle handle, res.code = result.code; res.error_message = STD_STRING_TO_NAPA_STRING_REF(result.errorMessage); res.return_value = STD_STRING_TO_NAPA_STRING_REF(result.returnValue); - + // Release ownership of transport context res.transport_context = reinterpret_cast(result.transportContext.release()); @@ -156,14 +156,14 @@ void napa_zone_execute(napa_zone_handle handle, FunctionSpec req; req.module = spec.module; req.function = spec.function; - + req.arguments.reserve(spec.arguments_count); for (size_t i = 0; i < spec.arguments_count; i++) { req.arguments.emplace_back(spec.arguments[i]); } req.options = spec.options; - + // Assume ownership of transport context req.transportContext.reset(reinterpret_cast(spec.transport_context)); @@ -172,7 +172,7 @@ void napa_zone_execute(napa_zone_handle handle, res.code = result.code; res.error_message = STD_STRING_TO_NAPA_STRING_REF(result.errorMessage); res.return_value = STD_STRING_TO_NAPA_STRING_REF(result.returnValue); - + // Release ownership of transport context res.transport_context = reinterpret_cast(result.transportContext.release()); @@ -264,9 +264,9 @@ namespace { } // namespace void napa_allocator_set( - napa_allocate_callback allocate_callback, + napa_allocate_callback allocate_callback, napa_deallocate_callback deallocate_callback) { - + NAPA_ASSERT(allocate_callback != nullptr, "'allocate_callback' should be a valid function."); NAPA_ASSERT(deallocate_callback != nullptr, "'deallocate_callback' should be a valid function."); From aa3200e44dc60461a129b2e4ea452086b408716e Mon Sep 17 00:00:00 2001 From: Raphael Miedl Date: Mon, 22 Oct 2018 20:40:44 +0200 Subject: [PATCH 09/17] Fix small typo (#266) --- docs/design/transport-js-builtins.md | 4 ++-- examples/modules/async-number/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/design/transport-js-builtins.md b/docs/design/transport-js-builtins.md index 67ea48c4..4a60f950 100644 --- a/docs/design/transport-js-builtins.md +++ b/docs/design/transport-js-builtins.md @@ -50,7 +50,7 @@ Here we just give a high-level description of the solution. Its API will go to [ - napa::v8_extensions::ExternalizedContents - It holds the externalized contents (memory) of a SharedArrayBuffer instance once it is serialized via napa::v8_extensions::Utils::SerializeValue(). - - Only 1 instance of ExternalizedContents wil be generated for each SharedArrayBuffer. If a SharedArrayBuffer had been externalized, it will reuse the ExternalizedContents instance created before in napa::v8_extensions::Utils::SerializeValue() + - Only 1 instance of ExternalizedContents will be generated for each SharedArrayBuffer. If a SharedArrayBuffer had been externalized, it will reuse the ExternalizedContents instance created before in napa::v8_extensions::Utils::SerializeValue() - napa::v8_extensions::SerializedData - It is generated by napa::v8_extensions::Utils::SerializeValue(). It holds the serialized data of a JavaScript object, which is required during its deserialization. @@ -120,7 +120,7 @@ function unmarshallTransform(payload: any, context: transportable.TransportConte - The life cycle extension during transportation is achieved through the ExternalizedContents SharedPtrWrap of the SAB. - When a SAB is transported for the first time, it will be externalized and its ExternalizedContents will be stored in its SerializedData. At the same time, the SharedPtrWrap of the ExternalizedContents will be set to the '_externalized' property of the original SAB. - - When a SAB is transported for the second time or later, it wil skip externalization and find its ExternalizedContents from its '_externalized' property, and store it to its SerializedData. + - When a SAB is transported for the second time or later, it will skip externalization and find its ExternalizedContents from its '_externalized' property, and store it to its SerializedData. - When a Napa worker tries to restore a transported SAB, it will find the pre-stored ExternalizedContents, and create a SharedPtrWrap for it, then set it to the to-be-restored SAB. diff --git a/examples/modules/async-number/README.md b/examples/modules/async-number/README.md index 51ad06b4..6f6b6482 100644 --- a/examples/modules/async-number/README.md +++ b/examples/modules/async-number/README.md @@ -1,4 +1,4 @@ -# Asynchronus numbering +# Asynchronous numbering ## APIs From 4c8fd412f74a0989c87c161da231245e82a10227 Mon Sep 17 00:00:00 2001 From: Mason Date: Mon, 29 Oct 2018 16:32:43 -0400 Subject: [PATCH 10/17] Fix some small typos (#267) --- benchmark/README.md | 4 ++-- docs/api/module.md | 2 +- docs/api/store.md | 2 +- examples/modules/plus-number/README.md | 2 +- examples/tutorial/napa-runner/README.md | 8 ++++---- scripts/embedded.js | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/benchmark/README.md b/benchmark/README.md index 02d07edb..84d30a2d 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -11,7 +11,7 @@ We got this report on environment below: | Name | Value | |-------------------|---------------------------------------------------------------------------------------| -|**Processor** |Intel(R) Xeon(R) CPU L5640 @ 2.27GHz, 8 virtual procesors | +|**Processor** |Intel(R) Xeon(R) CPU L5640 @ 2.27GHz, 8 virtual processors | |**System Type** |x64-based PC | |**Physical Memory**|16.0 GB | |**OS version** |Microsoft Windows Server 2012 R2 | @@ -90,7 +90,7 @@ Average overhead is around 0.06ms to 0.12ms for `zone.execute`. ## Transport overhead The overhead of `transport.marshall` includes -1. overhead of needing replacer callback during JSON.stringify. (even empty callback will slowdown JSON.stringfiy significantly) +1. overhead of needing replacer callback during JSON.stringify. (even an empty callback will slow down JSON.stringify significantly) 2. traverse every value during JSON.stringify, to check value type and get `cid` to put into payload. - a. If value doesn't need special care. - b. If value is a transportable object that needs special care. diff --git a/docs/api/module.md b/docs/api/module.md index e5944a08..3fa3dfba 100644 --- a/docs/api/module.md +++ b/docs/api/module.md @@ -27,7 +27,7 @@ Napa.js follows [Node.js' convention](https://nodejs.org/api/modules.html) to su 4) API of creating C++ modules (addons) are similar. Napa.JS introduced macros that the same source code can be compiled to produce both Napa.js addon and Node.js addon. But there are also differences: -1) C++ module that is designed/implemented for Napa.js can run on Node.JS (need different compile flags to produce '.napa' and '.node'). But not vice versal. +1) C++ module that is designed/implemented for Napa.js can run on Node.JS (need different compile flags to produce '.napa' and '.node'). But not vice versa. 2) Napa.js doesn't support all Node.js API. Node API are supported [incrementally](./node-api.md) on the motivation of adding Node.js built-ins and core modules that are needed for computation heavy tasks. You can access full capabilities of Node exposed via [Node zone](./zone.md#node-zone). 3) Napa.js doesn't provide `uv` functionalities, thus built-ins and core modules have its own implementation. To write async function in addon, methods `DoAsyncWork`/`PostAsyncWork` are introduced to work for both Napa.js and Node.js. 4) Napa.js supports embed mode. C++ modules need separate compilation between Node mode and embed mode. diff --git a/docs/api/store.md b/docs/api/store.md index a4d7ee21..9c68e410 100644 --- a/docs/api/store.md +++ b/docs/api/store.md @@ -23,7 +23,7 @@ Though very convenient, it's not recommended to use store to pass values within Following APIs are exposed to create, get and operate upon stores. ### create(id: string): Store -It creates a store by a string identifer that can be used to get the store later. When all references to the store from all JavaScript VMs are cleared, the store will be destroyed. Thus always keep a reference at global or module scope is usually a good practice using `Store`. Error will be thrown if the id already exists. +It creates a store by a string identifier that can be used to get the store later. When all references to the store from all JavaScript VMs are cleared, the store will be destroyed. Thus always keep a reference at global or module scope is usually a good practice using `Store`. Error will be thrown if the id already exists. Example: ```js diff --git a/examples/modules/plus-number/README.md b/examples/modules/plus-number/README.md index f9a340d0..89d5fa5d 100644 --- a/examples/modules/plus-number/README.md +++ b/examples/modules/plus-number/README.md @@ -11,7 +11,7 @@ var obj = addon.createPlusNumber(); ## Wrapped class -*plus-number.h* declares ths class with one constructor and one method, *Add()*. +*plus-number.h* declares the class with one constructor and one method, *Add()*. ```h namespace napa { diff --git a/examples/tutorial/napa-runner/README.md b/examples/tutorial/napa-runner/README.md index 031ee408..0164e14e 100644 --- a/examples/tutorial/napa-runner/README.md +++ b/examples/tutorial/napa-runner/README.md @@ -2,15 +2,15 @@ Napa runner is an example to embed Napa.JS into a C++ program. It simply runs JavaScript with all Napa capability without Node dependency from command line. ## How to build -1. Go to napajs root directory, run "node build.js embed" to build napa library for embeded mode. +1. Go to napajs root directory, run "node build.js embed" to build napa library for embedded mode. -**NOTE**: This step may take about 30 mins, because it will build V8 libray from Node. We are using node v6.10.3, a stable version can build as a library. It is specified in [embedded.js](https://github.com/Microsoft/napajs/blob/master/scripts/embedded.js) and [napa-runner CMakeLists.txt](https://github.com/Microsoft/napajs/blob/master/examples/tutorial/napa-runner/CMakeLists.txt). Please update both of them if you want to use a different version of Node/V8. +**NOTE**: This step may take about 30 mins, because it will build V8 library from Node. We are using node v6.10.3, a stable version can build as a library. It is specified in [embedded.js](https://github.com/Microsoft/napajs/blob/master/scripts/embedded.js) and [napa-runner CMakeLists.txt](https://github.com/Microsoft/napajs/blob/master/examples/tutorial/napa-runner/CMakeLists.txt). Please update both of them if you want to use a different version of Node/V8. 2. Go to directory of "examples/tutorial/napa-runner", and run "cmake-js build" to build napa runner **NOTE**: Build solution of napa-runner is provided only for linux system so far. Windows / Mac OS support will come in near future. ## How to use -1. Run "npm install" to intall required npm modules -2. Run "./bin/napa-runner emstimate-PI.js" +1. Run "npm install" to install required npm modules +2. Run "./bin/napa-runner estimate-PI.js" diff --git a/scripts/embedded.js b/scripts/embedded.js index bba1f875..5c7f139c 100644 --- a/scripts/embedded.js +++ b/scripts/embedded.js @@ -47,7 +47,7 @@ exports.build = function (buildType) { } else { // TODO (asib): support other platforms - console.log("\x1b[1m\x1b[32m", "Napa build solution for embeded mode is not provided for ", os.platform(),'\x1b[0m'); + console.log("\x1b[1m\x1b[32m", "Napa build solution for embedded mode is not provided for ", os.platform(),'\x1b[0m'); return; } From 1546003223ecbc59e5d8a2884abf95b454827bfc Mon Sep 17 00:00:00 2001 From: Algram Date: Mon, 29 Oct 2018 21:33:26 +0100 Subject: [PATCH 11/17] Change var to const in the README.md (#268) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 64b6b57f..011151f0 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,8 @@ Other options can be found in [Build Napa.js](https://github.com/Microsoft/napaj ## Quick Start ```js -var napa = require('napajs'); -var zone1 = napa.zone.create('zone1', { workers: 4 }); +const napa = require('napajs'); +const zone1 = napa.zone.create('zone1', { workers: 4 }); // Broadcast code to all 4 workers in 'zone1'. zone1.broadcast('console.log("hello world");'); From 3e472ac55590ad7e92ca7de4f72c14658b611558 Mon Sep 17 00:00:00 2001 From: hemirt Date: Mon, 29 Oct 2018 21:34:56 +0100 Subject: [PATCH 12/17] Fix small typos (#269) * Fix typos * Fix typos * Fix typos * Fix typos * Fix typos * Fix typo * Fix typo --- examples/modules/README.md | 2 +- examples/modules/async-number/README.md | 12 ++++++------ examples/modules/async-number/napa/addon.cpp | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/modules/README.md b/examples/modules/README.md index 5ed3a76e..96d6fa1a 100644 --- a/examples/modules/README.md +++ b/examples/modules/README.md @@ -27,7 +27,7 @@ The source codes can be organized as the structure below. ## How to build and test ? For the module examples, node-gyp or cmake-js build solution is provided for your reference. -Please make sure [node-gyp](https://github.com/nodejs/node-gyp#installation) or [cmake-js](https://github.com/cmake-js/cmake-js#installation) has been set up correctly at your client, then you could follow the below steps to build and test the module examples. +Please make sure [node-gyp](https://github.com/nodejs/node-gyp#installation) or [cmake-js](https://github.com/cmake-js/cmake-js#installation) has been set up correctly at your client, then you could follow the steps below to build and test the module examples. ``` 1. go to the directory of a module example 2. run "npm install" to build the module diff --git a/examples/modules/async-number/README.md b/examples/modules/async-number/README.md index 6f6b6482..c9327ef1 100644 --- a/examples/modules/async-number/README.md +++ b/examples/modules/async-number/README.md @@ -69,7 +69,7 @@ namespace { std::atomic _now(0); } -/// It increases a number by a given parameter asynchronously and run a callback at the next execution loop. +/// It increases a number by a given parameter asynchronously and runs a callback at the next execution loop. void Increase(const FunctionCallbackInfo& args) { auto isolate = args.GetIsolate(); @@ -81,12 +81,12 @@ void Increase(const FunctionCallbackInfo& args) { napa::module::PostAsyncWork(Local::Cast(args[1]), [value]() { - // This runs at the separate thread. + // This runs in a separate thread. _now += value; return reinterpret_cast(static_cast(_now.load())); }, [](auto jsCallback, void* result) { - // This runs at the same thread as one Increase() is called. + // This runs in the same thread as the one Increase() is called in. auto isolate = Isolate::GetCurrent(); int32_t argc = 1; @@ -98,7 +98,7 @@ void Increase(const FunctionCallbackInfo& args) { ); } -/// It increases a number by a given parameter synchronously and run a callback at the next execution loop. +/// It increases a number by a given parameter synchronously and runs a callback at the next execution loop. void IncreaseSync(const FunctionCallbackInfo& args) { auto isolate = args.GetIsolate(); @@ -110,12 +110,12 @@ void IncreaseSync(const FunctionCallbackInfo& args) { napa::module::DoAsyncWork(Local::Cast(args[1]), [value](auto complete) { - // This runs at the same thread. + // This runs in the same thread. _now += value; complete(reinterpret_cast(static_cast(_now.load()))); }, [](auto jsCallback, void* result) { - // This runs at the same thread as one IncreaseSync() is called. + // This runs in the same thread as the one IncreaseSync() is called in. auto isolate = Isolate::GetCurrent(); int32_t argc = 1; diff --git a/examples/modules/async-number/napa/addon.cpp b/examples/modules/async-number/napa/addon.cpp index 06904e55..ead2f330 100644 --- a/examples/modules/async-number/napa/addon.cpp +++ b/examples/modules/async-number/napa/addon.cpp @@ -16,7 +16,7 @@ namespace { std::atomic _now(0); } -/// It increases a number by a given parameter asynchronously and run a callback at the next execution loop. +/// It increases a number by a given parameter asynchronously and runs a callback at the next execution loop. void Increase(const FunctionCallbackInfo& args) { auto isolate = args.GetIsolate(); @@ -28,12 +28,12 @@ void Increase(const FunctionCallbackInfo& args) { napa::zone::PostAsyncWork(Local::Cast(args[1]), [value]() { - // This runs at the separate thread. + // This runs in a separate thread. _now += value; return reinterpret_cast(static_cast(_now.load())); }, [](auto jsCallback, void* result) { - // This runs at the same thread as one Increase() is called. + // This runs in the same thread as the one Increase() is called in. auto isolate = Isolate::GetCurrent(); int32_t argc = 1; @@ -45,7 +45,7 @@ void Increase(const FunctionCallbackInfo& args) { ); } -/// It increases a number by a given parameter synchronously and run a callback at the next execution loop. +/// It increases a number by a given parameter synchronously and runs a callback at the next execution loop. void IncreaseSync(const FunctionCallbackInfo& args) { auto isolate = args.GetIsolate(); @@ -57,12 +57,12 @@ void IncreaseSync(const FunctionCallbackInfo& args) { napa::zone::DoAsyncWork(Local::Cast(args[1]), [value](auto complete) { - // This runs at the same thread. + // This runs in the same thread. _now += value; complete(reinterpret_cast(static_cast(_now.load()))); }, [](auto jsCallback, void* result) { - // This runs at the same thread as one IncreaseSync() is called. + // This runs in the same thread as the one IncreaseSync() is called in. auto isolate = Isolate::GetCurrent(); int32_t argc = 1; From ff42fcb3bc3e84ed224d16562cf93ac031a68910 Mon Sep 17 00:00:00 2001 From: Sunita Sen <36556702+sunitasen@users.noreply.github.com> Date: Tue, 30 Oct 2018 02:07:30 +0530 Subject: [PATCH 13/17] fixed typos (#270) --- docs/api/zone.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/zone.md b/docs/api/zone.md index f26c8d96..64f71feb 100644 --- a/docs/api/zone.md +++ b/docs/api/zone.md @@ -43,7 +43,7 @@ There are two types of zone: ### Zone operations There are two operations, designed to reinforce the symmetry of workers within a zone: - 1) **Broadcast** - run code that changes worker state on all workers, returning a promise for the pending operation. Through the promise, we can only know if the operation succeed or failed. Usually we use `broadcast` to bootstrap the application, pre-cache objects, or change application settings. Function `broadcastSync` is also offered as a synchronized version of broadcast operations. + 1) **Broadcast** - run code that changes worker state on all workers, returning a promise for the pending operation. Through the promise, we can only know if the operation succeeded or failed. Usually we use `broadcast` to bootstrap the application, pre-cache objects, or change application settings. Function `broadcastSync` is also offered as a synchronized version of broadcast operations. 2) **Execute** - run code that doesn't change worker state on an arbitrary worker, returning a promise of getting the result. Execute is designed for doing the real work. Zone operations are on a basis of first-come-first-serve, while `broadcast` takes higher priority over `execute`. From 02eb70c8b116aa7fc7971621eba71210ef60f911 Mon Sep 17 00:00:00 2001 From: Pujan Mehta Date: Tue, 30 Oct 2018 02:08:36 +0530 Subject: [PATCH 14/17] Made some fixes in transport-js-builtins.md (#271) * Update memory.md * Update transport-js-builtins.md * Update transport-js-builtins.md * Update transport-js-builtins.md * Update README.md --- README.md | 2 +- docs/api/memory.md | 2 +- docs/design/transport-js-builtins.md | 46 ++++++++++++++-------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 011151f0..cfa42bb0 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can contribute to Napa.js in following ways: * Contribute to core module compatibility with Node. * Contribute bug fixes. -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact opencode@microsoft.com with any additional questions or comments. +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact opencode@microsoft.com with any additional questions or comments. # License Copyright (c) Microsoft Corporation. All rights reserved. diff --git a/docs/api/memory.md b/docs/api/memory.md index fdfb7280..7ccab620 100644 --- a/docs/api/memory.md +++ b/docs/api/memory.md @@ -72,7 +72,7 @@ Memory allocation in C++ addon is tricky. A common pitfall is to allocate memory There are also advanced scenarios that user want to customize memory allocation. Napa.js provides APIs for customizing memory allocator as well. -### Recommended way of allocate memory. +### Recommended way of allocate memory TBD ### Customize memory allocation diff --git a/docs/design/transport-js-builtins.md b/docs/design/transport-js-builtins.md index 4a60f950..0e9c8d80 100644 --- a/docs/design/transport-js-builtins.md +++ b/docs/design/transport-js-builtins.md @@ -5,18 +5,18 @@ The abstraction of 'Transportable' lies in the center of Napa.js to efficiently The incentive of this design is to provide a solution to make JavaScript standard built-in objects transportable with requirements listed in the Goals section. -At the first stage, we will focus on an efficient solution to share data between Napa workers. Basically, it is about making SharedArrayBuffer / TypedArray / DataView transportable. +At the first stage, we will focus on an efficient solution to share data between Napa workers. Basically, it is about making *SharedArrayBuffer / TypedArray / DataView* transportable. ## Goals Make Javascript standard built-in objects transportable with -- An efficient way to share structured data, like SharedArrayBuffer, among Napa workers +- An efficient way to share structured data, like *SharedArrayBuffer*, among Napa workers - Consistent APIs with ECMA standards - No new abstraction layers for the simplest usage - The least new concepts for advanced usage - A scalable solution to make all JavaScript standard built-in objects transportable, avoiding to make them transportable one by one. ## Example -The below example shows how SharedArrayBuffer object is transported across multiple Napa workers. It will print the TypedArray 'ta' created from a SharedArrayBuffer, with all its elements set to 100 from different Napa workers. +The below example shows how *SharedArrayBuffer* object is transported across multiple Napa workers. It will print the TypedArray 'ta' created from a *SharedArrayBuffer*, with all its elements set to 100 from different Napa workers. ```js var napa = require("napajs"); var zone = napa.zone.create('zone', { workers: 4 }); @@ -48,25 +48,25 @@ run(); Here we just give a high-level description of the solution. Its API will go to [docs/api/transport](https://github.com/Microsoft/napajs/blob/master/docs/api/transport.md). - V8 provides its value-serialization mechanism by ValueSerializer and ValueDeserializer, which is compatible with the HTML structured clone algorithm. It is a horizontal solution to serialize / deserialize JavaScript objects. ValueSerializer::Delegate and ValueDeserializer::Delegate are their inner class. They work as base classes from which developers can deprive to customize some special handling of external / shared resources, like memory used by a SharedArrayBuffer object. -- napa::v8_extensions::ExternalizedContents - - It holds the externalized contents (memory) of a SharedArrayBuffer instance once it is serialized via napa::v8_extensions::Utils::SerializeValue(). - - Only 1 instance of ExternalizedContents will be generated for each SharedArrayBuffer. If a SharedArrayBuffer had been externalized, it will reuse the ExternalizedContents instance created before in napa::v8_extensions::Utils::SerializeValue() +- **napa::v8_extensions::ExternalizedContents** + - It holds the externalized contents (memory) of a SharedArrayBuffer instance once it is serialized via *napa::v8_extensions::Utils::SerializeValue()*. + - Only 1 instance of ExternalizedContents will be generated for each SharedArrayBuffer. If a SharedArrayBuffer had been externalized, it will reuse the ExternalizedContents instance created before in *napa::v8_extensions::Utils::SerializeValue()*. -- napa::v8_extensions::SerializedData - - It is generated by napa::v8_extensions::Utils::SerializeValue(). It holds the serialized data of a JavaScript object, which is required during its deserialization. +- **napa::v8_extensions::SerializedData** + - It is generated by *napa::v8_extensions::Utils::SerializeValue()*. It holds the serialized data of a JavaScript object, which is required during its deserialization. -- BuiltInObjectTransporter - - napa::v8_extensions::Serializer, derived from v8::ValueSerializer::Delegate - - napa::v8_extensions::Deserializer, derived from v8::ValueDeserializer::Delegate - - static std::shared_ptr v8_extensions::Utils::SerializeValue(Isolate* isolate, Local value) - - Generate the SerializedData instance given an input value. - - If any SharedArrayBuffer instances exist in the input value, their ExternalizedContents instances will be generated and attached to the ShareArrayBuffer instances respectively. - - static MaybeLocal v8_extensions::Utils::DeserializeValue(Isolate* isolate, std::shared_ptr data); - - Restore a JavaScript value from its SerializedData instance generated by v8_extensions::Utils::SerializeValue() before. +- **BuiltInObjectTransporter** + - **napa::v8_extensions::Serializer, derived from v8::ValueSerializer::Delegate** + - **napa::v8_extensions::Deserializer, derived from v8::ValueDeserializer::Delegate** + - **static std::shared_ptr\ v8_extensions::Utils::SerializeValue(Isolate\* isolate, Local\ value);** + - Generate the *SerializedData* instance given an input value. + - If any *SharedArrayBuffer* instances exist in the input value, their *ExternalizedContents* instances will be generated and attached to the *ShareArrayBuffer* instances respectively. + - **static MaybeLocal\ v8_extensions::Utils::DeserializeValue(Isolate\* isolate, std::shared_ptr\ data);** + - Restore a JavaScript value from its SerializedData instance generated by *v8_extensions::Utils::SerializeValue()* before. -- Currently, Napa relies on Transportable API and a registered constructor to make an object transportable. In [marshallTransform](https://github.com/Microsoft/napajs/blob/master/lib/transport/transport.ts), when a JavaScript object is detected to have a registered constructor, it will go with Napa way to marshall this object with the help of a TransportContext object, otherwise a non-transportable error is thrown. +- Currently, Napa relies on Transportable API and a registered constructor to make an object transportable. In [marshallTransform](https://github.com/Microsoft/napajs/blob/master/lib/transport/transport.ts), when a JavaScript object is detected to have a registered constructor, it will go with Napa way to marshall this object with the help of a **TransportContext** object, otherwise a non-transportable error is thrown. -- Instead of throwing an error when no registered constructor is detected, the BuiltInObjectTransporter can help handle this object. We can use a whitelist of object types to restrict this solution to those verified types at first. +- Instead of throwing an error when no registered constructor is detected, the **BuiltInObjectTransporter** can help handle this object. We can use a whitelist of object types to restrict this solution to those verified types at first. ```js export function marshallTransform(jsValue: any, context: transportable.TransportContext): any { if (jsValue != null && typeof jsValue === 'object' && !Array.isArray(jsValue)) { @@ -117,14 +117,14 @@ function unmarshallTransform(payload: any, context: transportable.TransportConte - Received SAB transported from another Napa workers, including node zone of Napa. - TypedArray or DataView created from the original SAB or a received SAB. -- The life cycle extension during transportation is achieved through the ExternalizedContents SharedPtrWrap of the SAB. - - When a SAB is transported for the first time, it will be externalized and its ExternalizedContents will be stored in its SerializedData. At the same time, the SharedPtrWrap of the ExternalizedContents will be set to the '_externalized' property of the original SAB. +- The life cycle extension during transportation is achieved through the *ExternalizedContents* *SharedPtrWrap* of the SAB. + - When a SAB is transported for the first time, it will be externalized and its ExternalizedContents will be stored in its *SerializedData*. At the same time, the *SharedPtrWrap* of the *ExternalizedContents* will be set to the '_externalized' property of the original SAB. - - When a SAB is transported for the second time or later, it will skip externalization and find its ExternalizedContents from its '_externalized' property, and store it to its SerializedData. + - When a SAB is transported for the second time or later, it will skip externalization and find its *ExternalizedContents* from its '_externalized' property, and store it to its *SerializedData*. - - When a Napa worker tries to restore a transported SAB, it will find the pre-stored ExternalizedContents, and create a SharedPtrWrap for it, then set it to the to-be-restored SAB. + - When a Napa worker tries to restore a transported SAB, it will find the pre-stored *ExternalizedContents*, and create a *SharedPtrWrap* for it, then set it to the to-be-restored SAB. - - The life cycle of the SharedArrayBuffer is extended by the SharedPtrWrap of its ExternalizedContents. + - The life cycle of the *SharedArrayBuffer* is extended by the *SharedPtrWrap* of its *ExternalizedContents*. ## Constraints From 7e934ecc125a02088c25e1a58a8eb1b6fad80f6d Mon Sep 17 00:00:00 2001 From: Ruturaj Gujar Date: Tue, 30 Oct 2018 02:11:12 +0530 Subject: [PATCH 15/17] Update READMEs for the examples and fixed some grammatical errors in transport.md (#272) * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Added capitalization for the points * Fixed some typos and grammatical errors in transport.md --- benchmark/README.md | 20 ++++++------- docs/api/transport.md | 30 +++++++++---------- .../estimate-pi-in-parallel/README.md | 6 ++-- .../tutorial/max-square-sub-matrix/README.md | 6 ++-- examples/tutorial/napa-runner/README.md | 8 ++--- .../tutorial/parallel-quick-sort/README.md | 6 ++-- .../tutorial/recursive-fibonacci/README.md | 6 ++-- .../tutorial/synchronized-loading/README.md | 6 ++-- 8 files changed, 44 insertions(+), 44 deletions(-) diff --git a/benchmark/README.md b/benchmark/README.md index 84d30a2d..ac250575 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -36,12 +36,12 @@ Please refer to [execute-scalability.ts](./execute-scalability.ts) for test deta ## Execute overhead The overhead of `zone.execute` includes -1. marshalling cost of arguments in caller thread. -2. queuing time before a worker can execute. -3. unmarshalling cost of arguments in target worker. -4. marshalling cost of return value from target worker. -5. queuing time before caller callback is notified. -6. unmarshalling cost of return value in caller thread. +1. Marshalling cost of arguments in caller thread. +2. Queuing time before a worker can execute. +3. Unmarshalling cost of arguments in target worker. +4. Marshalling cost of return value from target worker. +5. Queuing time before caller callback is notified. +6. Unmarshalling cost of return value in caller thread. In this section we will examine #2 and #5. So we use empty function with no arguments and no return value. @@ -132,12 +132,12 @@ Please refer to [transport-overhead.ts](./transport-overhead.ts) for test detail ## Store access overhead The overhead of `store.set` includes -1. overhead of calling `transport.marshall` on value. -2. overhead of put marshalled data and transport context into C++ map (with exclusive_lock). +1. Overhead of calling `transport.marshall` on value. +2. Overhead of put marshalled data and transport context into C++ map (with exclusive_lock). The overhead of `store.get` includes -1. overhead of getting marshalled data and transport context from C++ map (with shared_lock). -2. overhead of calling `transport.unmarshall` on marshalled data. +1. Overhead of getting marshalled data and transport context from C++ map (with shared_lock). +2. Overhead of calling `transport.unmarshall` on marshalled data. For `store.set`, numbers below indicates the cost beyond marshall is around 0.07~0.4ms varies per payload size. (10B to 18KB). `store.get` takes a bit more: 0.06~0.9ms with the same payload size variance. If the value in store is not updated frequently, it's always good to cache it in JavaScript world. diff --git a/docs/api/transport.md b/docs/api/transport.md index d212c691..e80c1270 100644 --- a/docs/api/transport.md +++ b/docs/api/transport.md @@ -40,7 +40,7 @@ Transportable types are: - JavaScript primitive types: undefined, null, boolean, number, string - Object (TypeScript class) that implement [`Transportable`](#transportable) interface - Function without referencing closures. --
JavaScript standard built-In objects in this whitelist. +- JavaScript standard built-in objects in this whitelist. * ArrayBuffer * Float32Array * Float64Array @@ -54,23 +54,23 @@ Transportable types are: - Array or plain JavaScript object that is composite pattern of above. ### Constructor ID (cid) -For user classes that implement [`Transportable`](#transportable) interface, Napa uses Constructor ID (`cid`) to lookup constructors for creating a right object from a string payload. `cid` is marshalled as a part of the payload. During unmarshalling, transport layer will extract the `cid`, create an object instance using the constructor associated with it, and then call unmarshall on the object. +For user classes that implement the [`Transportable`](#transportable) interface, Napa uses Constructor ID (`cid`) to lookup constructors for creating a right object from a string payload. `cid` is marshalled as a part of the payload. During unmarshalling, the transport layer will extract the `cid`, create an object instance using the constructor associated with it, and then call unmarshall on the object. -It's class developer's responsibility to choose the right `cid` for your class. To avoid conflict, we suggest to use the combination of module.id and class name as `cid`. Developer can use class decorator [`cid`](#decorator-cid) to register a user Transportable class automatically, when using TypeScript with decorator feature enabled. Or call [`transport.register`](#register) manually during module initialization. +It's the class developer's responsibility to choose the right `cid` for your class. To avoid conflict, we suggest to use the combination of module.id and class name as `cid`. Developer can use class decorator [`cid`](#decorator-cid) to register a user Transportable class automatically, when using TypeScript with decorator feature enabled. Or call [`transport.register`](#register) manually during module initialization. ### Transport context -There are states that cannot be saved or loaded in serialized form (like std::shared_ptr), or it's very inefficient to serialize (like JavaScript function). Transport context is introduced to help in these scenarios. TransportContext objects can be passed from one JavaScript VM to another, or stored in native world, so lifecycle of shared native objects extended by using TransportContext. An example of `Transportable` implementation using TransportContext is [`ShareableWrap`](./../../inc/napa/module/shareable-wrap.h). +There are states that cannot be saved or loaded in serialized form (like std::shared_ptr), or it's very inefficient to serialize (like JavaScript function). Transport context is introduced to help in these scenarios. TransportContext objects can be passed from one JavaScript VM to another, or stored in the native world, so lifecycle of shared native objects extended by using TransportContext. An example of the `Transportable` implementation using TransportContext is [`ShareableWrap`](./../../inc/napa/module/shareable-wrap.h). ### Transporting functions JavaScript function is a special transportable type, through marshalling its definition into a [store](./store.md#intro), and generate a new function from its definition on target thread. Highlights on transporting functions are: - For the same function, marshall/unmarshall is an one-time cost on each JavaScript thread. Once a function is transported for the first time, later transportation of the same function to previous JavaScript thread can be regarded as free. -- Closure cannot be transported, but you won't get error when transporting a function. Instead, you will get runtime error complaining a variable (from closure) is undefined when you can the function later. -- `__dirname` / `__filename` can be accessed in transported function, which is determined by `origin` property of function. By default `origin` property is set to current working directory. +- Closure cannot be transported, but you won't get an error when transporting a function. Instead, you will get runtime error complaining a variable (from closure) is undefined when you can the function later. +- `__dirname` / `__filename` can be accessed in transported function, which is determined by `origin` property of the function. By default, `origin` property is set to the current working directory. ### Transporting JavaScript built-in objects -JavaScript standard built-In objects in [the whitelist](#built-in-whitelist) can be transported among napa workers transparently. JavaScript Objects with properties in these types are also able to be transported. Please refer to [unit tests](./../../test/transport-test.ts) for detail. +JavaScript standard built-in objects in [the whitelist](#built-in-whitelist) can be transported among napa workers transparently. JavaScript Objects with properties in these types are also able to be transported. Please refer to [unit tests](./../../test/transport-test.ts) for detail. An example [Parallel Quick Sort](./../../examples/tutorial/parallel-quick-sort) demonstrated transporting TypedArray (created from SharedArrayBuffer) among multiple Napa workers for efficient data sharing. @@ -105,7 +105,7 @@ class B { assert(!transport.isTransportable(new B())); ``` ### register(transportableClass: new(...args: any[]) => any): void -Register a `Transportable` class before transport layer can marshall/unmarshall its instances. +Register a `Transportable` class before the transport layer can marshall/unmarshall its instances. User can also use class decorator [`@cid`](#cid-decorator) for class registration. Example: @@ -121,7 +121,7 @@ class A extends transport.AutoTransportable { transport.register(A); ``` ### marshall(jsValue: any, context: TransportContext): string -Marshall a [transportable](#transportable-types) JavaScript value into a JSON payload with a [`TransportContext`](#transport-context). Error will be thrown if the value is not transportable. +Marshall a [transportable](#transportable-types) JavaScript value into a JSON payload with a [`TransportContext`](#transport-context).An Error will be thrown if the value is not transportable. Example: ```js @@ -132,7 +132,7 @@ var jsonPayload = transport.marshall( console.log(jsonPayload); ``` ### unmarshall(json: string, context: TransportContext): any -Unmarshall an [transportable](#transportable-types) JavaScript value from a JSON payload with a [`TransportContext`](#transport-context). Error will be thrown if `cid` property is found and not registered with transport layer. +Unmarshall a [transportable](#transportable-types) JavaScript value from a JSON payload with a [`TransportContext`](#transport-context).An Error will be thrown if `cid` property is found and not registered with the transport layer. Example: ```js @@ -148,18 +148,18 @@ Save a shareable object in context. Load a shareable object from handle. ### context.sharedCount: number -Count of shareable objects saved in current context. +Count of shareable objects saved in the current context. ## Interface `Transportable` -Interface for Transportable object. +Interface for the Transportable object. ### transportable.cid: string -Get accessor for [Constructor ID](#constructor-id). It is used to lookup constructor for payload of current class. +Get accessor for [Constructor ID](#constructor-id). It is used to lookup constructor for the payload of the current class. ### transportable.marshall(context: TransportContext): object -Marshall transform this object into a plain JavaScript object with the help of [TransportContext](#transport-context). +Marshall transforms this object into a plain JavaScript object with the help of [TransportContext](#transport-context). ### transportable.unmarshall(payload: object, context: TransportContext): void -Unmarshall transform marshalled payload into current object. +Unmarshall transforms marshalled payload into current object. ## Abstract class `TransportableObject` TBD diff --git a/examples/tutorial/estimate-pi-in-parallel/README.md b/examples/tutorial/estimate-pi-in-parallel/README.md index 45ea9476..a910dd35 100644 --- a/examples/tutorial/estimate-pi-in-parallel/README.md +++ b/examples/tutorial/estimate-pi-in-parallel/README.md @@ -4,9 +4,9 @@ This example implements an algorithm to [estimate PI using Monte Carlo method](h In the implementation, multiple batches of points are evaluated simultaneously in a [napa zone](https://github.com/Microsoft/napajs/wiki/introduction#zone) of 4 workers. Results are aggregated to calculate the final PI after all batches finishes. ## How to run -1. Go to directory of "examples/tutorial/estimate-pi-in-parallel" -2. Run "npm install" to install napajs -3. Run "node estimate-pi-in-parallel.js" +1. Go to directory of `examples/tutorial/estimate-pi-in-parallel` +2. Run `npm install` to install napajs +3. Run `node estimate-pi-in-parallel.js` ## Program output The table below shows results of PI calculated under different settings, each setting emulates 4,000,000 points evaluated by a napa zone of 4 workers. diff --git a/examples/tutorial/max-square-sub-matrix/README.md b/examples/tutorial/max-square-sub-matrix/README.md index c48f7e4e..5ee8ae1f 100644 --- a/examples/tutorial/max-square-sub-matrix/README.md +++ b/examples/tutorial/max-square-sub-matrix/README.md @@ -6,9 +6,9 @@ In this implementation, all units to be evaluated were divided into 2 * size of Please note that this example is to demonstrate the programming paradigm, while itself is NOT performance efficient, since each worker does too little CPU operation and major overhead is on communication. ## How to run -1. Go to directory of "examples/tutorial/max-square-sub-matrix" -2. Run "npm install" to install napajs -3. Run "node max-square-sub-matrix.js" +1. Go to directory of `examples/tutorial/max-square-sub-matrix` +2. Run `npm install` to install napajs +3. Run `node max-square-sub-matrix.js` **Note**: This example uses 'async / await', so Node version that supports ES6 is required. (newer than v7.6.0). diff --git a/examples/tutorial/napa-runner/README.md b/examples/tutorial/napa-runner/README.md index 0164e14e..c42c1425 100644 --- a/examples/tutorial/napa-runner/README.md +++ b/examples/tutorial/napa-runner/README.md @@ -2,15 +2,15 @@ Napa runner is an example to embed Napa.JS into a C++ program. It simply runs JavaScript with all Napa capability without Node dependency from command line. ## How to build -1. Go to napajs root directory, run "node build.js embed" to build napa library for embedded mode. +1. Go to napajs root directory and run `node build.js embed` to build napa library for embeded mode. **NOTE**: This step may take about 30 mins, because it will build V8 library from Node. We are using node v6.10.3, a stable version can build as a library. It is specified in [embedded.js](https://github.com/Microsoft/napajs/blob/master/scripts/embedded.js) and [napa-runner CMakeLists.txt](https://github.com/Microsoft/napajs/blob/master/examples/tutorial/napa-runner/CMakeLists.txt). Please update both of them if you want to use a different version of Node/V8. -2. Go to directory of "examples/tutorial/napa-runner", and run "cmake-js build" to build napa runner +2. Go to directory of `examples/tutorial/napa-runner`, and run `cmake-js build` to build napa runner **NOTE**: Build solution of napa-runner is provided only for linux system so far. Windows / Mac OS support will come in near future. ## How to use -1. Run "npm install" to install required npm modules -2. Run "./bin/napa-runner estimate-PI.js" +1. Run `npm install` to intall required npm modules +2. Run `./bin/napa-runner emstimate-PI.js` diff --git a/examples/tutorial/parallel-quick-sort/README.md b/examples/tutorial/parallel-quick-sort/README.md index 269bad58..50df74b7 100644 --- a/examples/tutorial/parallel-quick-sort/README.md +++ b/examples/tutorial/parallel-quick-sort/README.md @@ -4,9 +4,9 @@ This example implements a parallel version of quicksort by napa.js, and compares 2. How does napa.js accelerate a computation heavy task by parallelization. ## How to run -1. Go to directory of "examples/tutorial/parallel-quick-sort" -2. Run "npm install" to install napajs -3. Run "node parallel-quick-sort.js" +1. Go to directory of `examples/tutorial/parallel-quick-sort`. +2. Run `npm install` to install napajs. +3. Run `node parallel-quick-sort.js`. **Note**: This example involves TypedArray and SharedArrayBuffer. It requires Node v9.0.0 or newer. diff --git a/examples/tutorial/recursive-fibonacci/README.md b/examples/tutorial/recursive-fibonacci/README.md index 75df8460..ca0771c0 100644 --- a/examples/tutorial/recursive-fibonacci/README.md +++ b/examples/tutorial/recursive-fibonacci/README.md @@ -6,9 +6,9 @@ Recursion is supported on a single thread by JavaScript language, how if we want Please note that this example is to demonstrate the programming paradigm, while itself is *NOT* performance efficient, since each worker does too little CPU operation (simply '+') and major overhead is on communication. ## How to run -1. Go to directory of "examples/tutorial/recursive-fibonacci" -2. Run "npm install" to install napajs -3. Run "node recursive-fibonacci.js" +1. Go to directory of `examples/tutorial/recursive-fibonacci` +2. Run `npm install`to install napajs +3. Run `node recursive-fibonacci.js` ## Program output Table below shows statistics of calculating Nth Fibonacci number by a napa zone with 4 workers. diff --git a/examples/tutorial/synchronized-loading/README.md b/examples/tutorial/synchronized-loading/README.md index e1acf60e..5160f042 100644 --- a/examples/tutorial/synchronized-loading/README.md +++ b/examples/tutorial/synchronized-loading/README.md @@ -4,9 +4,9 @@ This example implements a shared phone book component. The component will not lo The component is implemented using lazy-loading pattern with the use of [`napa.sync.Lock`](./../../../docs/api/sync.md#interface-lock). ## How to run -1. Go to directory of "examples/tutorial/synchronized-loading" -2. Run "npm install" to install napajs -3. Run "node synchronized-loading.js" +1. Go to directory of `examples/tutorial/synchronized-loading` +2. Run `npm install` to install napajs +3. Run `node synchronized-loading.js` ## Program output The output below shows one possible result. The sequence of the output may be different but the data loading will always run once only. From 73460d244438e91d302194ee02de2a911a9bb731 Mon Sep 17 00:00:00 2001 From: Rauf Islam <31735267+RauffIslam@users.noreply.github.com> Date: Mon, 29 Oct 2018 16:41:59 -0400 Subject: [PATCH 16/17] Update zone.md (#273) fixed one sentence because english --- docs/api/zone.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/zone.md b/docs/api/zone.md index 64f71feb..cd59e0f5 100644 --- a/docs/api/zone.md +++ b/docs/api/zone.md @@ -51,7 +51,7 @@ There are two operations, designed to reinforce the symmetry of workers within a ## API ### create(id: string, settings: ZoneSettings): Zone -It creates a Napa zone with a string id. If zone with the id is already created, error will be thrown. [`ZoneSettings`](#zone-settings) can be specified for creating zones. +It creates a Napa zone with a string id. If a zone with the id is already created, an error will be thrown. [`ZoneSettings`](#zone-settings) can be specified for creating zones. Example 1: Create a zone with id 'zone1', using default ZoneSettings. ```js From b38a2385c07699749ca693b64c79b6a8ca5a6403 Mon Sep 17 00:00:00 2001 From: Abhilash Tiwari Date: Tue, 30 Oct 2018 02:13:13 +0530 Subject: [PATCH 17/17] Fixed 8 typo errors in the log.md files (#274) --- docs/api/log.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/api/log.md b/docs/api/log.md index af5a95f4..46735f4a 100644 --- a/docs/api/log.md +++ b/docs/api/log.md @@ -17,7 +17,7 @@ ## Introduction Logging is a basic requirement for building services. `napajs` logging API enables developers to integrate their own logging capabilities in both JavaScript and C++ (addon) world. -A log row may contain following information: +A log row may contain the following information: - (Optional) Section: Useful field to filter log rows. Treatment is defined by logging providers. - (Optional) Trace ID: Useful field to join logs in the same transaction or request. - (Required) Message: Log message. @@ -54,7 +54,7 @@ void MyFunction() { ### log(message: string): void It logs a message. Using info level. -*`log` is a shortcut for `log.info`.* +* A `log` is a shortcut for `log.info`.* Example: ```js @@ -78,16 +78,16 @@ Example: napa.log('request', 'A1B2C3D4', 'request received'); ``` ### log.err(...) -It logs an error message. Three variation of arguments are the same with `log`. +It logs an error message. Three variations of arguments are the same with the `log`. ### log.warn(...) -It logs a warning message. Three variation of arguments are the same with `log`. +It logs a warning message. Three variations of arguments are the same with the `log`. ### log.info(...) -It logs an info message. Three variation of arguments are the same with `log`. +It logs an info message. Three variations of arguments are the same with the `log`. ### log.debug(...) -It logs a debug message. Three combinations of arguments are the same with `log`. +It logs a debug message. Three combinations of arguments are the same with the `log`. ## Using custom logging providers Developers can hook up custom logging provider by calling the following before creation of any zones: