node-ffi เรียก functions ใน dll ด้วย JavaScript กันตรงๆ

จากความเดิมตอนที่แล้วผมเคยเขียนเรื่องการสร้าง Node.js Module ด้วย C++ มาทีนึงแล้ว แต่ถึงอย่างนั้นถ้าเรา
– มี C++ Library อยู่แล้วล่ะ
– หรืออยากทำให้ Node สามารถเรียกใช้งานพวก System API โดยที่ไม่อยากศึกษาการเขียน Node Module แบบ Native
ผมก็ไปเจอว่ามี Community ที่ได้พัฒนา Framework มาตัวนึงซึ่งวันนี้เราจะมาพูดถึงกัน นั่นก็คือ Node-ffi ซึ่งย่อมาจาก Foreign Function Interface

Node-ffi นั้นเป็น Module ที่ทำหน้าที่เป็นตัวกลางในการทำการติดต่อระหว่าง JavaScript Code ไปที่ C++ Library โดยที่เราไม่ต้องเขียน Native Module เอง ประมาณรูป Diagram ด้านล่างครับ

ffi.png

เรามาลองดูการใช้งานกันดีกว่าครับ

ก่อนอื่นเรามี C++ Library ที่เป็น DLL ที่ต้องการจะเรียก ซึ่งผมลองเขียนมาแบบง่ายๆคือ dll ที่มี function ในการ ดึงค่า Version ของ OS

extern "C" DLLIMPORT int getVersion()
{
 DWORD dwVer = ::GetVersion();
 DWORD majorVer = (DWORD)(LOBYTE(LOWORD(dwVer)));
 return majorVer;
};

ซึ่ง API ::GetVersion นั้นเป็นของ Windows SDK ครับ ซึ่งสำหรับฝั่ง C++ ผมได้ทำการ  Compile ออกมาเป็น dll ชื่อ dev.dll

ทีนี้มาลองดูส่วนที่สำคัญของเราก็คือฝั่ง JavaScript

var ffi = require('ffi');

var devModule = ffi.Library('dev', {
 'getVersion': [ 'int', [] ]
});
console.log('Windows version : ' + devModule.getVersion());

จาก Code นี้ก็มี 3 ส่วนหลักๆครับ

  1. require module ‘ffi’
  2. ประกาศการทำ function binding
    ffi.Library('dev', {
      'getVersion': [ 'int', [] ]

    2.1 ทำการ binding กับไฟล์ library ชื่อ dev.dll
    2.2 ทำการ binding กับ function ชื่อ getVersion โดยมี ‘int’ เป็น Type ของ Return Value
    2.3 Function getVersion นี้ไม่มี parameter เลยใส่เป็น []

  3. เรียกใช้ ffi ด้วย  devModule.getVersion()

ผลของการรันก็เป็นดังนี้ครับคือได้ค่า ’10’ มาจาก getVersion

ffi_run.png

นอกจากนี้เรายังสามารถประกาศการทำ binding ทีละหลายๆ function ก็ได้เหมือนกันครับ(ขออนุญาติไม่โชว์ Code ฝั่ง C++ ที่เขียนเพิ่มเพื่อดึงค่า Minor,Build Version) เช่น

var devModule = ffi.Library('dev', {
 'getVersion': [ 'int', [] ] ,
 'getMinorVersion' : [ 'int', [] ],
 'getBuildVersion' : [ 'int', [] ]
});
console.log('Windows version : ' + devModule.getVersion());
console.log('Minor version : ' + devModule.getMinorVersion());
console.log('Build version : ' + devModule.getBuildVersion());

ผลการรันก็ดูดีครับและตรงกับ System Info จริงๆนะ 🙂

ffi_run2.png

สรุป : node-ffi น่าจะเป็นอีกหนึ่งทางเลือกสำหรับคนที่เขียน Node.Js ด้วย Context บางอย่างที่ต้องติดต่อกับ System หรือ OS ระดับ Low Level (เหมือนผม..) โดยที่เรานั้นไม่ต้องมาการเรียนรู้การเขียน Node Module แบบ Native ที่อาจจะมีความซับซ้อนกว่าทั้งในแง่การทำ Mapping พวก Data Types รวมถึงการมานั่งศึกษา V8 API  ซึ่งผมคิดว่า node-ffi อาจจะมีผลกระทบกับ Performance ในการ call function บ้าง แต่ผมก็ยังไม่ได้ลองวัด ทั้งนี้ทั้งนั้นใครมีข้อมูลเพิ่มก็แชร์กันได้ครับ

npm แล้วช้ามาลองใช้ yarn จาก facebook กัน

yarn-kitten-full

ทุกๆท่านที่เขียน Node.js ก็ต้องคุ้นเคยกับ npm กันอยู่แล้วนะครับ ซึ่งบางทีเรามักจะเจอว่า มัน install นาน รวมถึงเวลาเน็ตมีปัญหาแล้วมัน install ไม่ได้ มาวันนี้ Facebook ได้ประกาศ Open Source ตัว package manager ตัวใหม่ที่ทำงานบนพื้นฐานของ npm ซึ่งชื่อของมันก็คือ Yarn

ทาง Facebook ได้พูดถึงจุดเด่นหลักๆได้ประมาณนี้ครับ

  1. เร็ว – เพราะมีระบบการ Cache ถ้า pkg ไหนโหลดมาแล้วก็ไม่ต้องโหลด
  2. เชื่อถือได้ – ใช้ในการติดตั้ง package ได้เหมือนเจ้าอื่น
  3. ปลอดภัย – ทำการ check sum ซึ่งเป็นการตรวจเช็คว่าการ install นั้นถูกต้อง

ความสามารถหลักๆของมันคือเช่น

  • Offline Mode ถ้าเคย insatll package มาแล้วครั้งนึง ก็ไม่ต้องใช้ internet ในการ install แล้ว
  • ใช้ประโยชน์จาก Network อย่างเต็มที่ทำให้การ install นั้นเร็วขึ้น
  • ใช้ได้ทั้งกับ npm และ Bower
  • ทำการ retry ถ้าหากว่ามีปัญหาตอน install

อ่านรายละเอียดได้ที่ https://github.com/yarnpkg/yarn และ https://code.facebook.com/posts/1840075619545360 สำหรับ Architure และที่มาที่ไปของ Project นี้ครับ

เกริ่นมาพอแล้ว เรามาลองเล่นกันดีกว่าครับ

ก่อนอื่นก็

npm install -g yarnpkg

แล้วก็ลองเช็คดูครับว่าลงได้

yarnv.png

ที่นี้เดี๋ยวผมลอง install module เล่นๆ เอาเป็น socket.io ละกันครับ ดังนั้นผมสร้าง package.json ง่ายๆมาก่อน

{
“dependencies”: {
“socket.io”: “^1.5.0”
}
}

package.json

ที่นี้ลองรัน “yarn” ซึ่งเทียบเท่ากับ “npm install”

จะเห็นว่าเราจะได้ node_modules มารวมถึงเวลาที่ใช้ไป 3.61s

yarn_install.png

ทีนี้ผมลองลบ folder ‘node_modules’ ทิ้งเพื่อจะดูว่ามัน Offline install ได้จริงเปล่าแล้วก็ทำการ yarn อีกที ผลที่ได้คือ !!! 0.77s

yarn_reinstall

จะเห็นได้ว่า yarn นั้นทำการ cached ตัว package ที่เคยโหลดมาแล้วไว้ที่ Local Machine ซึ่งผมลองไปคุ้ยๆ Folder ดูก็เจอว่ามันไปเก็บไว้ที่  %localappdata%/yarn นี่เองสำหรับบน Windows

local_yarn.png

สรุป ผมว่า Tool ตัวนี้น่าสนใจครับ เดี๋ยวว่าจะเอาไปลองใช้ใน Production บ้าง โดยเฉพาะช่วงเน็ตช้าและต้องงานหลายๆ repo ที่อาจจะมีการใช้ npm package ซ้ำๆกันบ่อยๆ…

Node.js – LoopBack กับการต่อ Database

ความเดิมตอนแรกสุดเลยนั้น ผมใช้ datasources เป็น memory เพราะว่าใช้ในการ Development ที่นี้เนื่องจากว่าผมอยากใช้ database เป็น NoSQL ผมก็เลยลองหาวิธีการดู ซึ่งก็ไม่ผิดหวังครับ LoopBack นั้นจัดการให้เราได้อย่างง่ายๆเช่นเคย

บทความก่อนหน้าเพื่อความเข้าใจพื้นฐานมากขึ้น

Node.js เขียน REST API ด้วย LoopBack
Node.js – LoopBack มาต่อกันที่การเพิ่ม REST API กับ Query กัน

ที่นี้เปิดดูไฟล์ datasources.json กันก่อนครับ จะเห็นว่าเป็นการ define ว่าใช้ memory

{
  "db": {
    "name": "db",
    "connector": "memory"
  }
}

แก้ datasources.json
ผมก็แค่เปลี่ยน configuration ในนี้ให้เป็น  ‘mongodb’ ซึ่งผมทดสอบกับ Azure DocumentDB service นะครับ ไม่ได้ตั้ง mongoDB เอง

nosql.png

ที่นี้เราลองมารัน LoopBack กันอีกรอบนึงครับ ปรากฎว่ารันไม่ผ่าน เพราะ LoopBack ไม่รู้จัก configuration นี้

no-connector.png

ติดตั้ง Connector
สิ่งที่เราต้องทำคือการ install mongodb connector ครับ ด้วย npm command ข้างบน

npm install loopback-connector-mongodb

เมื่อ install เสร็จก็จะสามารถรันได้แล้วครับ เช่นเดิมคือ port เบอร์ 3000

has-connector.png

ทดสอบ
ที่นี้เราลอง POST เพื่อใส่ข้อมูลกัน ผม POST  – anurocha กับ destiny ไปครับ

post-db.png

ที่นี้ลอง Query ดูใน Azure Dashboard ก็จะเห็นว่าลองใช้ Query Explore บน Azure ดูก็ได้ค่าที่ POST ไปจาก localhost ที่เราต่อกับ mongoDB บน Azure ถูกต้อง

azure-db.png

จะเห็นได้ว่า LoopBack นั้นช่วยให้เรา Connect ไปที่ Database ได้โดยที่ผมยังไม่ได้เขียน Code หรือ SQL เลยโดยที่ datasource ที่ LoopBack นั้นมี Connector ก็ดูได้ตามนี้ครับ (Database connectors) ซึ่งคร่าวๆก็มีครบหมดครับสำหรับตัวยอดนิยม MongoDB, MySQL, Oracle, PostgreSQL, Redis, SQL Server, SQL Lite และอื่นๆ

เป็นไงครับ POWER FUL มากๆ…

Node.js – LoopBack มาต่อกันที่การเพิ่ม REST API กับ Query กัน

หลังจากที่ผมพูดถึงความสามารถเบื้องต้นของ LoopBack ไปแล้วนั้นใน Node.js เขียน REST API ด้วย LoopBack ซึ่งจะเห็นได้ว่าเราสามารถสร้าง REST API ได้ง่ายมาก แต่ทีนี้ถ้าเราต้องการที่เพิ่ม API ล่ะจะทำได้ยังไง

เรากลับมาดูที่ไฟล์ user.js กันก่อนครับ ซึ่งเป็นไฟล์ว่างๆ

'use strict';

module.exports = function(User) {

};

สิ่งที่ผมอยากจะได้ก็คือถ้าเราต้องการ API เพื่อที่จะเอาค่าของ User 4 คนที่ได้คะแนนสูงสุดจะต้องทำยังไงบ้าง
สิ่งที่เราต้องทำคือการเพิ่ม remoteMethod (ซึ่งทาง LoopBack Framework จะทำการ Route มาเข้า Method ของเราครับ

'use strict';

module.exports = function(User) {
User.getTopUsers = function(cb){
cb(null, "getTopUsers Response");
};

User.remoteMethod (
'getTopUsers',
{
http: {path: '/gettopusers', verb: 'get'},
returns: {arg: 'users', type: 'string'}
}
);
};

จะเห็นว่า Code User.remoteMethod นั้นทำการ define ว่าถ้ามี HTTP Request ที่เป็น GET เข้ามาที่ Path /gettopusers นั้นจะทำการเรียก Method User.getTopUsers นั่นเอง

และใน Method ที่ชื่อ User.getTopUsers นั้นตอนนี้ผมลองให้ส่งค่ากลับไปว่า getTopUsers Response ที่นี้ลองรันดู LoopBack เพื่อเป็น Server ดูครับ

ลองเช็คกับ API Explorer ก็จะเห็นว่า API ที่เราเพิ่งเพิ่มเข้าไปมาแล้ว

new-api.png

เนื่องจากเป็น GET ผมลองเรียกผ่าน Browser ครับก็ได้ Response มาแบบนี้ ตามที่เขียนไว้

new-api-response.png

ที่นี้จาก API ที่ผมต้องการนั้น ผมอยากได้ User ที่คะแนนสูงสุด ซึ่งทาง LoopBack นั้นก็มี Build-in API ให้เราใช้ในการ Query ข้อมูลจาก Model ได้ครับ (Querying data) เช่น

'use strict';

module.exports = function(User) {
User.getTopUsers = function(cb){
User.find({
order: 'score DESC',
limit : 4
}, (err, instances)=>{
cb(null, instances);
});
};

User.remoteMethod (
'getTopUsers',
{
http: {path: '/gettopusers', verb: 'get'},
returns: {arg: 'users', type: 'string'}
}
);
};

ซึ่งจาก Code ข้างบนนี้จะเป็นการใช้ User.find ซึ่งเป็นการ Query หา Model โดยมี Filter ว่า หา ‘score’ ที่มีค่าสูงสุด 4 entries แรก

ที่นี้ลองทดสอบกันอีกทีครับ

ผมลองใส่ ข้อมูลไปแบบนี้ตาม Order

[
{
“name”: “alpha”,
“score”: 70,
“id”: 1
},
{
“name”: “beta”,
“score”: 45,
“id”: 2
},
{
“name”: “catto”,
“score”: 39,
“id”: 3
},
{
“name”: “delta”,
“score”: 86,
“id”: 4
},
{
“name”: “sigma”,
“score”: 34,
“id”: 5
},
{
“name”: “fanta”,
“score”: 12,
“id”: 6
}
]

ทีนี้ลองเรียกผ่าน API /gettopusers ดูครับ

result.png

เราก็จะได้ Response ที่ทำการ Order มาแล้วตาม score โดยที่ delta(80), alpha(70), beta(45), catto(39) ตามลำดับที่เราได้ทำ Query ไว้อย่างง่ายดาย

มาถึงตรงนี้เราก็จะได้เห็นความ Powerful ของ LoopBack ไปอีกหนึ่งเรื่องนะครับ 🙂

powered-by-lb-med

Node.js เขียน REST API ด้วย LoopBack

powered-by-LB-med.png

เนื่องจากผมอยากลองเขียน REST ง่ายๆเอาไว้ลองกับงาน Side Project ดูครับ ส่วนตัวแล้วเคยจับ Express มาบ้างแบบน้อยนิด ซึ่งปกติก็ต้องมานั่งเขียน Route กันเองแล้วมาเช็ค Path เลยหา Framework อื่นดู ก็เจอว่ามีทั้ง Sails, Restify และอื่นๆ แต่ลองนึกดูเคยมีคนพูดถึง LoopBack ให้ผมฟัง ผมเลยลองมาใช้ตัวนี้ดีกว่า เพราะเห็นว่า IBM เป็นผู้สนับสนุนรายใหญ่ซึ่งจริงๆแล้วพัฒนาโดย StrongLoop

ก่อนอื่นเข้าไป official site https://loopback.io/ ก่อนเลย ก็เจอว่า Get Started ไม่มี Code ตัวอย่างเลยครับ งั้นมันทำงานยังไงกันนี่ เรามาลองดูกัน

ก่อนอื่นเท่าที่ผมเข้าใจ LoopBack เนี่ยจะใช้แนวคิดเรื่อง Model มากกว่าการ Route ซึ่งหมายความว่าการที่เราจะเพิ่ม API เข้าไป ก็จะเป็นการทำงานเกี่ยวข้องกับ Model (เหมือนกับการเขียน function handler ของ Model) เพราะหน้าที่การ Route นั้น LoopBack จัดการให้เราหมดแล้ว ผ่าน Express นั่นแหละ….

เริ่มแรกเราต้อง Install ตัว LoopBack ก่อนครับ (เป็น commandline interface – CLI)

$ npm install -g strongloop

หลักจากนั้นเราจะต้องทำการสร้าง Project จาก Template ครับด้วย

$ slc loopback

จากนั้นเราจะต้องทำการตั้งชื่อ Project เลือก Directory รวมถึงเลือก LoopBack version

create-proj.png
ผมตั้งชื่อว่า loopback-aro

สิ่งที่ได้คือ Folders และ ไฟล์ต่างๆหน้าตาแบบนี้โดยผมสร้าง Project แบบ api-server ฉะนั้นส่วนที่จะต้องแก้น่าจะทำใน Folder ชื่อ server

folder-struct.png

หลังจากนั้นเราก็ลองทำการสร้าง Model กันครับ เพราะอย่างที่ผมบอกไปข้างต้นว่า loopback นั้นใช้ Model driven ในการพัฒนา REST API

 

$ slc loopback:model

ผมจะสร้าง Model ง่ายๆใช้สำหรับเก็บข้อมูล user ละกันครับ ตัว CLI มันก็จะให้เราตอบไปว่าจะใช้ Feature อะไรของ LoopBack บ้าง เช่น

  • จะใช้ data-source แบบไหน (ค่าปกติคือ memory ซึ่งใช้สำหรับการ Dev เพราะไม่งั้นเราปิด server แล้วค่าจะถูกลบทิ้งครับ เพราะ memory ถูกคืนให้ OS)
  • ใช้ PersistedModel เพื่อทำใช้สามารถเก็บ Model เข้า database ได้ง่าย
  • ทำการเปิด REST API สำหรับ Model ตัวนี้
  • และ อื่นๆ

create-model.png

ที่นี้ผมก็จะสร้าง properties หรือ attibutes ของ user ครับ โดยที่มี

  • name เป็น string
  • score เป็น number

create-prop.png

เมื่อสร้างเสร็จแล้วเราก็จะเห็น Folder ชื่อ common ถูกสร้างขึ้นมารวมทั้งมี Subfolder ชื่อ Model ที่มีไฟล์ user.js/json ซึ่งตรงกับที่เราสร้างข้างต้น

common-folder.png

เราจะเห็นว่า

  • user.js คือ code javascript เปล่าๆ (ที่เอาไว้ให้เราเขียน logic สำหรับ expose REST API เพิ่ม)
  • user.json นั้นจะเป็นการประกาศพวก Properties ต่างๆ (หมายความว่าเราไม่ต้องใช้ CLI ในการสร้าง Model ก็ได้ถ้าเรารู้จักโครงสร้างของ Framework)

model-files.png

ที่นี้เราลองมารันดูครับ

node .

run.png

ลองเข้าผ่าน localhost:3000/explorer ดูก็จะพบว่ามี API Tool (หน้าตาเหมือน Swagger ให้เลยครับ)

explorer

เรามาลอง POST เพื่อสร้าง Model object ดีกว่า

anurocha-80.png

จะเห็นว่าหลังจากกดปุ่ม Try it out! ก็จะทำการยิง http request ไปที่ /api/user และได้รับ message ตอบรับว่า 200 และได้รับ id:1 เป็นค่า key

anurocha-res.png

ดังนั้นถ้าผมลอง GET ด้วย id :1 เราควรจะได้ object นี้กลับมากนะครับ ลองผ่าน Postman (ซึ่งเป็น Tool ที่ใช้ได้การส่ง HTTP request) กันดีกว่า

ได้ response ตามคาด!

get-postman.png

จะเห็นว่าการสร้าง REST API แบบง่ายๆด้วย LoopBack นี่ไม่ต้องเขียน Code เลยซักบรรทัด

แต่ความสามารถของ LoopBack ยังมีอีกเยอะ เช่นการ Extend API ให้ซับซ้อนยิ่งขึ้น การติดต่อกับ Data-source แบบอื่นๆเช่น MySQL หรือ MongoDB เจอกันคราวหน้าครับ 🙂
Notes:

เพิ่ม API อ่านต่อได้เลย

รัน Typescript ผ่าน Node ตรงๆด้วย ts-node

ปกติแล้ว Node.js นั้นจะทำการ execute JavaScript เท่านั้น ซึ่งถ้า Developer นั้นอยากเขียน Project ด้วย TypeScript ก็จะต้องทำการ compile จาก .ts ให้เป็น .js ก่อน

พอดีเห็น GitHub มีโปรเจคหน้าสนใจชื่อว่า ts-node ซึ่งทำให้เราสามารถรัน .ts ไฟล์ได้ตรงๆเลยครับ
Link: https://github.com/TypeStrong/ts-node

การใช้งานก็คือรัน commandline นี้เพื่อทำการรัน Node

ts-node main.ts

มาลุยกันครับ

เริ่มจากเรามี TypeScript file (.ts) ที่สั่งสร้าง http server ชื่อ main.ts

import * as http from "http";

class HttpServer {
private server : http.Server;
public start(){
this.server = http.createServer( (request, response) => {
response.write('Hello...!');
response.end();
});

this.server.listen(8080);
console.log("start server...");
}

public stop(){
this.server.close(()=>{}
);
}
}

let serv = new HttpServer();
serv.start();

ทีนี้เราก็ลอง install ts-node ก่อนครับ

npm install ts-node

เรามาลองรันกันดูครับ

ts-node main.ts

เวิร์คดี!!

runable.png

ถ้าเรามาลองดู Process Tree เราก็จะพบว่าจริงๆแล้วตัว ts-node นั้นก็ทำการรัน node process และทำการรัน bin.js ซึ่งเป็น code ของ ts-node เพื่อให้มันสามารถรัน main.ts ได้

process_tree.png

สรุปแล้วผมคิดว่าโปรเจคนี้น่าสนใจนะครับ เพราะช่วยลดขั้นตอนการ compile ไป JavaScript ไป 🙂
ทั้งนี้ทั้งนั้นต้องทดสอบว่าถ้าเป็นโปรเจคที่ซับซ้อนจะเป็นยังไงบ้าง…

Node.js – Profiling เพื่อดูว่า Code เรากิน CPU รึเปล่า

สิ่งที่จะทำให้เรายกระดับการเป็น Developer ขึ้นไปอีก ก็คือเราต้องรู้ว่า Code ที่ตัวเองเขียนไปนั้น Perform ยังไงตรงตามที่คาดคิดไว้รึเปล่า รวมถึงมีไอเดียที่จะปรับปรุงให้มันทำงานได้ดียิ่งขึ้น

ซึ่งขั้นตอนที่ขาดไม่ได้สำหรับการวัดประสิทธิภาพของ Code ก็คือ สิ่งที่เรียกว่า Profiling

ซึ่งทาง Node.js Tools for Visual Studio ก็มีเครื่องมือนี้มาให้ด้วย ซึ่งปกติเครื่องมือช่วยการทำ Profiling เราก็เรียกง่ายๆว่า Profiler  (Features อื่นๆ อ่านเพิ่มเติมจาก link นะครับ)

ถ้าผมมี Code ตัวอย่าง JavaScript ประมาณนี้

console.log('Hello world');

for (let i = 0; i < 50; ++i){
    let rand = getRandomNum(10000000);
    print(rand, calSum(rand), findDivideBy5(rand));
}

function getRandomNum(max) {
    return Math.floor((Math.random() * max) + 1);
}

function calSum(num) {
    let sum = 0;
    for (let i = 0; i <= num; ++i) {
        sum += i;
    }
    return sum;
}

function findDivideBy5(num) {
    let n = 0;
    for (let i = 0; i <= num; ++i) {
        if (i % 5 == 0) {
            n++;
        }
    }
    return n;
}

function print(rand, sum, count5) {
    console.log("number : " + rand);
    console.log("Sum of 0 to " + rand + " is " + sum);
    console.log("Can divide by 5 count of 0 to " + rand + " is " + count5);
    console.log("----------------------");
}

 

Code นี้ทำอะไรบ้าง?

เป็นการสุ่มค่ามาค่านึง (N) แล้วก็
1. หาผลรวมของ 0 ถึง N – function calSum()
2. หาจำนวนของตัวเลขระหว่าง 0 ถึง N ที่หารด้วย 5 ลงตัว – function findDivideby5()
3. แสดงผล – function print()

คำถามคือ Code ตรงไหนช้าที่สุด…เรามาดูกัน

เราสามารถเริ่มการทำ Profiling จากเมนูนี้

menu

เมื่อ app ทำงานจบหรือเราหยุดการทำงานก่อน Visual Studio ก็จะทำการสร้าง Report มาให้เราอย่างละเอียด

fullreport

เรามาดู Hi-light ที่สำคัญกันครับ

  1. Code นี้ใช้พลัง CPU ไป ~20% ซึงเครื่องผมมี 4 Cores แล้วว่าทำงานไปเต็มๆ 1 Corecpu_usage
  2. มาดูระดับ Function กันครับ ปรากฎว่า app.calSum เป็นผู้ชนะไป (หมายความว่าแย่สุด เพราะใช้ CPU ไปเยอะที่สุด)function_usage
  3. นอกจากนี้ยังสามารถดู Call Tree เพื่อที่จะได้รู้ว่าแต่ละ Function ถูกเรียกมาได้ยังไง รวมถึงใช้ CPU ไปมากน้อยเท่าไหร่
    เช่น จากตัวอย่าง Top level (หรือ Global) นั้นได้ทำการเรียก function calSum() กับ app.fineDivideby5()call_tress

จากตัวอย่างนี้จะเป็นว่าการทำ Profiling นั้น ช่วยให้เราสามารถวิเคาะห์ปัญหาเกี่ยวกับการใช้งาน CPU ได้สะดวกยิ่งขึ้น แต่ทั้งนี้ทั้งนั้น นอกจากการใช้งาน CPU แล้ว สิ่งที่ควรจะทำการ Profile ก็ควรจะมีทั้ง Memory รวมถึง HTTP Resource หรือ Disk I/O ด้วย (แต่เหมือน Visual Studio ยังไม่ Support สำหรับ Node.js มั้งครับ ผมหาไม่เจอ 55)