ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

19
@ITCAMPRO #ITCAMP17 Community Conference for IT Professionals A deep dive into bridging NodeJS with NET Core Raffaele Rialdi @raffaeler [email protected] https://www.linkedin.com/in/raffaelerialdi/

Transcript of ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

Page 1: 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

[email protected]

https://www.linkedin.com/in/raffaelerialdi/

Page 2: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Many thanks to our sponsors & partners!

GOLD

SILVER

PARTNERS

PLATINUM

POWERED BY

Page 3: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

[email protected]

github.com/raffaeler

Page 4: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 5: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

.NET Code

Introducing xcore

Javascript / Typescript code

xcorexcore C++ xcore .NET

.NET Core

V8

Page 6: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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);

});

Page 7: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 8: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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'

Page 9: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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());

Page 10: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 11: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Demo: a simple V8 plugin

Page 12: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 13: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Demo: loading the CLR

Page 14: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

XCORE WRAP UP

Page 15: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 16: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 17: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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#

Page 18: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@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

Page 19: ITCamp 2017 - Raffaele Rialdi - A Deep Dive Into Bridging Node-js with .NET Core

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Questions?

Thank you!