So sánh net core và nodejs năm 2024

Ae backend nào chuyên sâu về ngôn ngữ khác mà tự tin mình có thể cân được mọi loại web thì giới thiệu cho mọi người cùng học với nhé.

Cũng chẳng có ai tự tin mà khẳng định như vậy. càng làm nhiều lại càng ko dám khẳng định điều đó

Mình phải công nhận 1 sự thật đó là các system lớn, performance cao họ thường dùng các ngôn ngữ bậc thấp (C, C++) hay các ngôn ngữ đã phát triển từ lâu đời và có hệ sinh thái cực khủng như Java, .NET. Hệ sinh thái của các ngôn ngữ đó (VD: Java Spring) vô cùng lớn mạnh, enterprise, gần như cái gì cũng có package/lib có thể giải quyết đc vấn đề của bạn, chả cần nghĩ ngợi nhiều, cái gì cũng có lib xử lý.

Mình đi làm từ đầu tới giờ hầu hết chỉ focus vào JS, React/vue/angular, backend thì NodeJS. Mình cũng công nhận là về thực tế "có vẻ" NodeJS hơi lép vế khi ta phải build system lớn hoặc các ứng dụng enterprise. bởi vì NodeJS sinh cũng sau hơn các ngôn ngữ khác (c, cpp, java...) hệ sinh thái về system/enterprise cũng chưa có nhiều (mặc dù số lượng npm packages cũng vô cùng kinh khủng). nhưng điều đó chẳng nói lên rằng NodeJS ko thể build đc các app lớn, mọi ngôn ngữ theo lý thuyết đều có thể làm được (theo mình nghĩ như vậy). Và đó là lí do mình vẫn làm NodeJS tới giờ, đó là cái mình focus chính, còn đi làm thì các cty muôn hình vạn trạng, cần backend gì thì mình làm cái đó. Mình đâu thể join vào cty và cứ đòi làm cái ngôn ngữ mình thích. Mình có quen mấy a chị làm ở FB, GG, Twitter họ bảo trong đó vẫn có đầy dự án lớn dùng NodeJS (trên blog engineering của các cty đó cũng có rất nhiều bài giới thiệu về các system/app của họ dùng Node)

Mình nghĩ vấn đề của bạn là bạn đang cố gắng tìm ra 1 thứ có thể cân cả thế giới, nếu ai cũng như vậy, thì chắc đã ko có sự tồn tại của NodeJS/Rust/Ruby/Python... hay Go (1 trong nhữ ngôn ngữ rất hot bây giờ), mọi người cứ tập trung cho C, Cpp hay Java... cho nó cực kì kinh khủng là được, và như thế thì thế giới lập trình cũng buồn chán đi bao nhiêu. Cộng thêm bạn có chắc chắn là bạn làm được 1 ngôn ngữ cả đời ko?

So sánh net core và nodejs năm 2024
, bạn có chắc công ty tiếp theo bạn apply họ thích ngôn ngữ mà bạn chọn (vì bạn nghĩ nó cân đc cả thế giới). Và nó có thể làm bạn lỡ đi rất nhiều cơ hội., cũng làm cho bản thân bạn (có thể) cũng kém sáng tạo đi rất nhiều, vì cái gì cũng có rồi, chả cần nghĩ nhiều nữa. Làm như vậy thì sẽ hình thành tâm lý "ko cần nodejs, python... Cứ phang ngôn ngữ X của tôi, đỡ phải nghĩ, có hết rồi" (nghe đã thấy tẻ nhạt rồi
So sánh net core và nodejs năm 2024
), 1 ví dụ thực tế là giờ rất nhiều người dùng React bởi vì nó to nhiều người dùng mà quên đi Vue + Angular cũng là những sự lựa chọn rất tuyệt vời, xong làm web nào cũng vậy ko cần biết app bé như con kiến hay app to, cứ phang React, bởi vì "quen" rồi.

Không có ngôn ngữ nào là giải pháp tốt nhất để giải quyết mọi vấn đề nhưng mình không cần tốt nhất, miễn làm được ra sản phẩm là được. Dù gì người dùng cũng chẳng quan tâm mình sử dụng công nghệ nào.

Chính xác, chẳng user nào người ta biết được tới bạn dùng công nghệ nào để phát triển

So sánh net core và nodejs năm 2024
nhưng bạn nói thế này thì ....

Câu chuyện chọn ngôn ngữ nào luôn là vấn đề muôn thuở mà mình thấy các bạn mới rất hay băn khoăn và mất thời gian vì nó. Chẳng ai dám tự tin khẳng định cái này hoặc cái kia tốt hơn mọi thứ, nó có thể góp phần tác động vào quan điểm/định hướng của người khác và làm cộng đồng kém phát triển đi. Bạn hãy chọn lấy 1 cái và làm nó, theo đuổi, kiên trì làm nó thật tốt nâng cao giá trị của bản thân, thay vì tự hỏi tìm ra 1 thứ vi diệu 1 cho tất cả.

(Rất tiếc là mình ko đưa code cũng như hình ảnh minh hoạ vào đây vì hạn chế status của FB, có lẽ hẹn anh em 1 bài blog sau).

— NodeJS bá đạo như vậy, nhưng các bạn vẫn luôn cần lựa chọn một cách khôn ngoan, và các bạn cần biết NodeJS phù hợp nhất với những ứng dụng gì.

Câu trả lời đơn giản là: Viết các chương trình JS để giao tiếp với networks, file systems, hay các I/O resources khác (như input/output, reading/writing). Chỉ vậy thôi, mục đích của NodeJS chính là 1 I/O platform giúp bạn xây dựng được những ứng dụng đòi hỏi tốc độ nhanh và xử lý được lượng connection lớn. Ở những mức thấp hơn là những network programs sử dụng HTTP, TCP, UDP, DNS, SSL, các chương trình đọc viết dữ liệu tới file hệ thống hay bộ nhớ cục bộ…

Một vài ví dụ: Websockets, HTTP + JSON, Files (image resizer, video editor, internet radio), caching proxy, Facebook/Twitter API, RedisDB, MongoDB, CouchDB…

Và, quan trọng không kém, đừng hiểu lầm Nodejs là 1 trong những thứ sau: 1. A web framework (đếch giống Rails hay Django hay Laravel…đâu nhé). 2. A programming language (nó dùng Javascript, Node ko có ngôn ngữ riêng).

Tuy bây giờ với sức mạnh của Express và nhiều module khác NodeJS có thể làm được “mọi thứ” mà một web framework khác được (như 1 CRUD web app chả hạn), cá nhân mình cho rằng nhưng ứng dụng nặng về CRUD thì cứ Rails hay Django hay Laravel mà phang cho nhanh!

Có rất nhiều điều để nói về bài viết này nhưng kết luận đầu tiên của mình là nó không giúp cho người đọc “hiểu hơn”, mà khiến cho người đọc “hiểu sai”. Tác giả đề cập đến khá nhiều khái niệm, Process, Thread-Thread pool, nonblocking, performance… tuy nhiên hầu hết kiến thức đưa ra đều nhầm lẫn hoặc sai lệch, khiến cho kết luận cũng sai theo.

Trong bài viết dưới đây, mình sẽ đề cập đến vài vấn đề được nêu ra trong post nói trên, vừa nhằm mục đích phản biện, vừa nhằm phổ biến kiến thức.

Lưu ý: bài viết này nhằm mục đích phản biện khoa học chứ không nhắm đến bất cứ cá nhân hay cộng đồng nào. Nếu bạn là người không chịu được chỉ trích thì tốt nhất không nên đọc

Thứ nhất, trong bài, người viết có đề cập đến việc “Nodejs nhanh”, và đưa 2 lý do chủ yếu:

1. Nodejs sử dụng Single-thread và event loop(asynchronous I/O).

2. Nodejs sử dụng Javascript engine v8 của Google.

Trong bài viết mình sẽ lần lượt bàn đến các vấn đề:

1. Nodejs có thực sự “nhanh”

2. Single threaded, async i/o đóng góp thế nào trong performance.

1. Nodejs chạy nhanh?

Đây là một kết luận “bí hiểm” mà rất nhiều lập trình viên Nodejs mặc định cho là đúng. Trước hết, “nhanh” là một khái niệm mang tính so sánh, chúng ta cần phải hiểu xem Nodejs “nhanh” so với những công nghệ nào tương đương?

Đây là một kết luận “bí hiểm” mà rất nhiều lập trình viên Nodejs mặc định cho là đúng. Trước hết, “nhanh” là một khái niệm mang tính so sánh, chúng ta cần phải hiểu xem Nodejs “nhanh” so với những công nghệ nào?

Trên thực tế khi đem so sánh với những framework, platform khác, nodejs HOÀN TOÀN không nhanh (như bạn có thể vẫn nghĩ). Tất nhiên, khi chúng ra nói đến performance, không thể chỉ dựa vào võ đoán mà cần có số liệu đo đạc cụ thể. Khi đo đạc, chúng ta cũng cần xác định cụ thể xem mình đang đo đạc những gì, và số liệu đo được có cho chúng ta ý nghĩ thực sự hay không.

Có 2 thứ mà chúng ta có thể đo ở đây

  1. Xét về hiệu năng tính toán và xử lý (những tác vụ cần làm việc nhiều với CPU và RAM), Nodejs thua kém hoàn toàn so với các ngôn ngữ được biên soạn (như Java, .NET, Go…). Bạn có thể tham khảo qua bài test CombSort:

Đối với các bạn lười đọc, kết quả tóm tắt là:

* C++ (G++ 4.9.2): CPU: 0.05s Real: 0.12s RAM: 19428KB

* PHP 5.6.4: CPU: 102.69s Real: 104.20s RAM: 2497508KB

* Ruby 2.2.0 : CPU: 52.87s Real: 53.02s RAM: 87892KB

* Node 0.10.35: CPU: 2.64s Real: 2.64s RAM: 92240KB

* Go 1.4.1 : CPU: 0.14s Real: 0.17s RAM: 31568KB

* Java 1.7: CPU: 1.05s Real: 0.73s RAM: 65952KB

* Python 3.4.2: CPU: 90.47s Real: 90.83s RAM: 403192KB

* C# Mono: CPU: 0.44s Real: 0.47s RAM: 45908KB

Các bạn có thể thấy Nodejs có hiệu năng tỏ ra tương đối vượt trội so với các nền tảng sử dụng interpreter khác ( như PHP, Ruby, Python…) tuy nhiên thua kém so với các ngôn ngữ được biên soạn (Go, C#, Java). Dĩ nhiên ở đây C++ vẫn cho thấy hiệu năng cao nhất. Lý do sẽ được giải thích trong phần 2.

  1. Xét về khả năng xử lý I/O (các tác vụ liên quan đến truy xuất dữ liệu từ đĩa, networking…), vốn là điều mà Nodejs tỏ ra khá tự hào về hiệu năng ( dựa trên khái niệm non-blocking I/O mà nhiều người vẫn hiểu lầm), Nodejs cũng không thực sự được xếp hạng cao. Mình sẽ làm thử một bài benchmark để đo khả năng xử lý http request (ứng dụng I/O có thể nói là cơ bản và phổ biến nhất) của Nodejs so với .NET. ( Bạn có thể tiến hành bài đo tương tự với các http framework mà bạn muốn)

Để đo đạc mình sẽ sử dụng Wrk, công cụ benchmark webserver vốn được dùng rất phổ biến. Nodejs server được viết như sau:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

var http = require('http'); var fs = require('fs'); var cluster = require('cluster'); var numCPUs = require('os').cpus().length; const message = "Hello world!"; const contentType = "text/plain"; if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', function (worker, code, signal) { console.log('worker ' + worker.process.pid + ' died'); }); } else { http.createServer(function (request, response) { response.writeHead(200, { 'Content-Type': contentType }); response.end(message); }).listen(5000, '127.0.0.1'); } console.log('Server running at ;)

Trong webserver này, Nodejs sẽ tạo ra một cluster bao gồm 1 số các process con trùng với số nhân CPU của bạn. Mục đích là để Nodejs có thể tận dụng hết được các nhân CPU (do mặc định Nodejs chỉ có thể hoạt động trên 1 thread).

.NET webserver được viết như sau:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

using System; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; namespace ConsoleApplication { public static class Program { const string Message = "Hello world!"; const string ContentType = "text/plain"; public static void Main(String[] args) { var host = new WebHostBuilder() .UseKestrel() .UseUrls("http://*:5000") .Configure(app => { app.Use(d => async c => { c.Response.Headers["Content-Type"] = ContentType; await c.Response.WriteAsync(Message); }); }) .Build(); host.Run(); } } }

Webserver được sử dụng trong benchmark này là Kestrel được viết bằng C#. Điều thú vị ở bài test này là Kestrel và httpServer của Nodejs sử dụng chung một thư viện networking có tên là libuv. Điều này sẽ cho chúng ta sự so sánh chính xác hơn về hiệu năng giữa 2 platform.

Bạn có thể thấy là bài đo của chúng ta khá đơn giản, webserver chỉ trả về “Hello world” mà thôi. Mục đích của bài đo này là kiểm tra khả năng xử lý nhiều request, do đó chúng ta chỉ nên tập trung vào tình huống đơn giản nhất

Cấu hình máy:

– CPU: Intel Core i5 – 6600 3.30GHz x 4

– RAM: 8GB

– OS: Ubuntu 16.04 x64

Câu lệnh mà mình thưc hiện đo là:

./wrk -t4 -c100 -d20s http://localhost:5000/

Câu lệnh này sẽ gửi liên tục các request đến webserver trong khoảng thời gian 20s (-d20s), sử dụng 4 threads (-t4) và giữ tối đa là 100 connections (-c100). Kết quả như sau:

Kestrel, .NET Core 1.0.0 : 291747 request/ giây

So sánh net core và nodejs năm 2024

httpServer, Nodejs 6.3.1: 104796 request/ giây

So sánh net core và nodejs năm 2024

Bạn có thể thấy rằng .NET xử lý được lượng request gấp hơn 2.5 lần so với Nodejs.

Nếu như bạn vẫn chưa thoả mãn với những phép đo này thì bạn có thể tham khảo những phép đo có hệ thống hơn tại benchmark. Nếu như trước giờ bạn là một trong số những người cho rằng “Nodejs cực kì nhanh”, bạn có thể sẽ ngạc nhiên với xếp hạng của Node ở trong những bài đo này

Nhầm lẫn 1: Nodejs nhanh do chạy bởi engine Google V8

Vậy tại sao Nodejs không nhanh (như bạn tưởng)?Trở lại bài viết phía đầu bài khi người viết cho rằng V8 là một trong những lý do khiến Nodejs nhanh (V8 là javascript engine của Google chrome). Bỏ qua việc V8 chưa hẳn đã là Engine javascript nhanh nhất, có một điều chúng ta phải công nhận là v8 là một engine JS có hiệu năng tốt. Tuy nhiên một Engine Javascript tốt thì vẫn chỉ là 1 engine javascript, và hiệu năng của nó luôn bị giới hạn bởi đặc trưng của ngôn ngữ. Một ví dụ đơn giản nhất là cách javascript lưu trữ dữ liệu trong các object. Trong javascript, mỗi object lưu và đọc dữ liệu của mình bằng một bảng “Hash” chứ không lưu trực tiếp giá trị như Java, hay C#. Bạn hoàn toàn có thể làm một phép thử đơn giản:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

var person = { name: "Foo", age: 30 }; console.log(person.name === person["name"]); //true console.log(person.age === person["age"]); //true

Điều này có nghĩa là mỗi lần lưu (hay đọc) dữ liệu từ object, thay vì truy cập trực tiếp, Javascript phải tiến hành “hash” tên của trường cần truy cập. Cách lưu dữ liệu này rất phổ biến trong các ngôn ngữ sử dụng dynamic typing (Python, Ruby…), và Google v8 thực sự cho thấy hiệu năng vượt trội ( như chúng ta thấy trong bài test CombSort ở phần 1). Tuy nhiên, so với các ngôn ngữ sử dụng static typings (Java, C#, Go…) thì javascript khó có thể so bằng được. (lưu ý: mình nói khó, không phải “không thể”)

Nhầm lẫn 2: Nodejs chạy nhanh do có Single-threaded, Non-blocking I/O, Event loop … blah blah…

Để hiểu được Event loop hay Non-blocking I/O là cả một chủ đề dài (mà mình hy vọng sẽ có dịp viết về nó). Tuy nhiên có hai điều mình muốn chỉ ra từ bài viết trên:

– Cho rằng Non-blocking i/o là lý do khiến Nodejs nhanh là hoàn toàn sai lầm. Lý do? Non blocking i/o là thứ có trên hầu hết(nếu như không muốn nói là tất cả) các platform/ framework hiện đại. Những ứng dụng Java sử dụng Future interface, .NET với TPL (Task parralel library), hay Python sử dụng IO loop (như trong Tornado framework) đều có thể thực hiện Non-blocking I/O như Nodejs. Trên thực tế, nếu bạn là lập trình viên .NET sử dụng TPL với async/await, bạn có thể viết các ứng dụng non-blocking mà không cần phải “callback” như trong nodejs. Async/await cũng đang là tính năng được dự trù trong ES7.Đối với Nodejs, sự khác biệt duy nhất là nonblocking i/o trở thành ý tưởng chủ đạo trong việc lập trình.

– Cho rằng việc sử dụng Thread-pool là “lãng phí tài nguyên” và hệ điều hành phải “nai lưng” ra quản lý thread chứng tỏ tác giả không có hiểu biết thực sự về thread pool. Thread pool là một dạng “Cache” để lưu trữ các thread đã qua sử dụng. Trong mô hình Thread pool, bạn trả những thread đã sử dụng xong về Threadpool, để Thread đó có thể được tái sử dụng mà không mất công tạo lại từ đầu. Đây là một kĩ thuật giúp cho việc sử dụng nhiều thread trở nên hiệu quả mà không gây nên gánh nặng cho hệ điều hành. Trong benchmark tại phần 1, Kestrel cũng sử dụng Thread pool và chúng ta có thể thấy kết quả tương đối rõ ràng.

Nếu Nodejs không nhanh (như bạn tưởng), vậy bạn có nên đầu tư sử dụng nó hay không

Từ trước đến giờ, performance luôn là chủ đề gây tranh cãi. Benchmark chỉ là benchmark và nó cũng chỉ phản ánh được 1 khía cạnh mà thôi. Hầu hết những framework/platform hiện đại đều đáp ứng được về vấn đề hiệu năng và những sự khác biệt (nếu có) đều có thể được lấp đầy bằng cách nâng cấp phần cứng. Vậy nên theo mình, khi lựa chọn 1 platform/framework để đầu tư, chúng ta cần xem xét 2 yếu tố:

1. Nó có giúp bạn đạt được mục đích hay không.

2. Bạn có thông thạo/thoải mái khi sử dụng nó hay không.

Điều quan trọng nhất là người sử dụng một công nghệ nào đó cần có hiểu biết và khái niệm đúng về những gì bạn đang làm. Performance của ứng dụng của bạn sẽ phụ thuộc nhiều vào cách bạn tổ chức, thiết kế hệ thống của mình, và bạn nên dành nhiều thời gian cho việc đó. Điều cuối cùng là khi nói đến hiệu năng, đừng bao giờ chỉ nói mồm, mà hãy đo đạc cụ thể.