ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core
-
Upload
itcamp -
Category
Technology
-
view
409 -
download
5
Transcript of ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
A deep dive into bridging
NodeJS with NET Core
Raffaele Rialdi
@raffaeler
https://www.linkedin.com/in/raffaelerialdi/
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Many thanks to our sponsors & partners!
GOLD
SILVER
PARTNERS
PLATINUM
POWERED BY
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Who am I?
• I am Raffaele Rialdi, Senior Software Architect in Vevy Europe – Italy
• I am also consultant in many industries
– manufacturing, racing, healthcare, financial, …
• But also Speaker in italian and international conferences
– Trainer as well
• And very proud to have been awarded as a Microsoft MVP
– Since 2003
@raffaeler
github.com/raffaeler
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
NodeJS and .NET? What do you mean?
• We do NOT want to serialize the data across processes– Too easy ☺
– Poor performance
• All the code in the sameprocess–Hard way ☺☺
–Good performance ☺
NodeJSProcess
Json SerializeC#
Process
One Process
NodeJSCode
C#Code
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
.NET Code
Introducing xcore
Javascript / Typescript code
xcorexcore C++ xcore .NET
.NET Core
V8
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
xcore in action
• Load and initialize xcore
• Load the .net metadata
– Just the first needed class
• Create an instance
• Call methods
• Walk the graph
– new metadata is
loaded automatically
• Asynchronous calls
(and much more!)
var xcore = require('bindings')('xcore');xcore.initialize(__dirname + "\\Sample",
"SampleLibrary.dll", "SampleLibrary.Initializer");
xcore.loadClass("SampleLibrary.OrderSample.OrderManager, SampleLibrary");
var om = new xcore.OrderManager("raf");
console.log(om.Add("Hello, ", "world"));
console.log(om.SelectedOrder.Name);
om.AddAsync(2, 3, function(res){console.log(res);
});
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
• Node.js® is a well-known runtime environment for javascript
• It leverages the power of "V8", the engine of Google Chrome– V8 conforms to the ECMAScript 262 standard
– runs cross-platforms
• NodeJs has a vivid ecosystem with tons of 3rd party libraries
• V8 can be extended with native addons (C++):– When you need more performance
– To access operating system's resources and services
– To interoperate with external systems / hardware
Node.JS and V8 https://nodejs.org
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
• Including the libraries
• Declare the Entry-Point using
the NODE_MODULE macro
• Implement the entry-point and
declare javascript-friendly
methods
• The "Method" will be available
as "hello" to javascript
The basic structure of a C++ V8 addon
#include <node.h>#include <v8.h>
NODE_MODULE(addon, init)
void init(Local<Object> exports){
NODE_SET_METHOD(exports, "hello", Method);}
void Method(const FunctionCallbackInfo<Value>& args){
Isolate* isolate = args.GetIsolate();args.GetReturnValue().Set(
String::NewFromUtf8(isolate, "world"));}
// javascript codeconst addon = require('./myAddon');console.log(addon.hello()); // 'world'
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
V8 Object Wrapping
• By deriving the ObjectWrap class, we can expose objects to JS
• Object members are added dynamically
– Constructors, methods, properties, indexers
– Just set the members spcifying the class name
• All member are static void functions
– Their input parameter is a "const FunctionCallbackInfo<Value>& args"
• The args contain the runtime values of the arguments
– The wrapper instance is get using ObjectWrap:Unwrap
– The return value is set using "args.GetReturnValue().Set(…);"
exports->Set(v8className, constructorTemplate->GetFunction());
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
• LibUV is the threading library used by NodeJs and V8
• The JS code must be always executed in the main thread
• .NET methods returning Task<T> must to be marshalled back to the
main thread
• The LibUV library gives a very basic support for enqueuing
messages in its threads
Threading and the libuv threading library
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Demo: a simple V8 plugin
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Hosting the CoreCLR
• What does it mean hosting the CLR?– A native (C++) application can load the CLR, some assemblies and
run managed (.NET) code
– SQL Server is a great example of native application hosting the CLR
– You can do it too!
• The CLR in .NET Framework could be hosted only on Windows– It is based on the COM infrastructure
• Net Core can be hosted as well but cross-platform– It mimics the COM interfaces, but the infrastructure is not COM-
dependent
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Demo: loading the CLR
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
XCORE WRAP UP
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
• Metadata for the CLR type is loaded
–The C++ layer dynamically add the class definition to V8
• A member is invoked
–The C++ layer gets the arguments of the call
–A Reverse PInvoke is done to C#
–The instance identifier is retrieved from a global table
– If not available, the marshaller code is generated
–The code is invoked
xcore execution flow
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
• The call was synchronous
–The return value is marshalled back to C++ and V8
• The call was asynchronous
– In C++ the return value is queued in LibUV main thread
• The call was an exception
– It is propagated to the caller
xcore execution flow
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Performance profile
• There are still many possible improvements
• The add use-case is not realistic
– it just measures infrastructure and marshalling
– 4 marshalling involved: (JS C++ .NET C++ JS)
1 Million callsjs: 6.156 ms
c++: 56.352 ms.net: 1294.254 ms
console.time("net");for(var i=0; i<loop; i++){
om.NetAdd(i, i);}console.timeEnd("net");
console.time("c++");for(var i=0; i<loop; i++){
xcore.add(i, i);}console.timeEnd("c++");
console.time("js");for(var i=0; i<loop; i++){
LocalAdd(i, i);}console.timeEnd("js");
js: 6.156ms c++: 56.352ms .net: 1294.254ms
var om = new xcore.OrderManager();
om.Add(2, 2); // jittingLocalAdd(2,2); // jittingxcore.add(2, 2); // jittingvar loop = 1000000; // 1 Million
function LocalAdd(x, y){ return x + y; }
prepare the benchmark local javascript C++ only xcore + C#
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Use-cases
1. Node.js applications
2. UI created with the Electron framework
– Ability to create .NET ViewModels for Angular (by Google)
3. Using JS to script Windows Powershell
4. Nativescript Mobile applications
– Nativescript is a project by Progress Software Corporation
https://www.nativescript.org/
5. Anything else based on V8
http://electron.atom.io
@ITCAMPRO #ITCAMP17Community Conference for IT Professionals
Questions?
Thank you!