thảo luận node JS vẫn chưa thể lập trình đa luồng

chạy song song nhiều thread tất nhiên là nhanh hơn single thread rồi. Xử lý hàng trăm, hàng ngàn request thì vẫn không phải nhanh lắm đâu. Quan trọng là khối lượng tính toán cơ
 
chạy song song nhiều thread tất nhiên là nhanh hơn single thread rồi. Xử lý hàng trăm, hàng ngàn request thì vẫn không phải nhanh lắm đâu. Quan trọng là khối lượng tính toán cơ
Thì đúng nhưng design bt nodejs nó async IO chạy single thread vẫn nhanh cho các tác vụ web căn bản. Còn chủ thớt ở đây có vẻ muốn bàn vê việc xử lý nặng muốn spam thread để xử lý 2 công việc cùng lúc. Giống làm application hơn là web server :)
 
Cái vấn đề chính của nodejs đó là chỉ single thread nên dù event loop hay không thì vẫn bị đơ như thường nếu xử lý nặng.

Trên web thì có web worker. Hồi trước cũng có use case xài web worker. JS dù có event loop nhưng cái code trong hàng đợi vẫn phải tới lúc thuc thi ở mainthread. Lúc lôi nó ra chạy thì vẫn bị đứng đơ cái web.

Version 1
cái expensive() khi web chạy tới expensive() là đứng cứng ngắc 1 hồi.
JavaScript:
main() {
    normal()
    expensive()
    normal()
}


Version 2
Chơi ăn gian cho cái expensive() vào setTimeOut để force nó vào hàng đợi. Hồi đó ngu cữ nghĩ cho vào hàng đợi là nó chạy 1 cái thread khác xử lý. Nhưng dù vào hàng đợi hay ko nó vẫn bị main thread lôi ra xử lý nên lúc nó lôi expensive ra chạy là các task khác đều đứng vì phải chờ thằng expensive() xong.

JavaScript:
main() {
    normal()
   setTimeout(() => {    expensive() } )
    normal()
}

Về sau phải nhét cái expensive() xuống web worker chạy background rồi quay về mainthread mới ko bị lag, đơ web. Nodejs thì xài worker thread thôi, chắc đúng ý chủ thớt là muốn spam thread rồi.
 
Thím nào còn mong Nodejs nó muti-thread là éo bao giờ hiểu được bản chất của single thread lẫn miti-thread. Cứ nghĩ server phải muti-thread mới nhanh mới mạnh?

Có bao giờ não đặt câu hỏi tại sao thằng Nodejs tuy single thread nó lại có thể xử lý rất nhanh khi có cả trăm, cả ngàn request?

Tôi đánh dấu ở đây, tối rảnh sẽ giải thích. Chuẩn bị tan làm rồi, k muốn ráng ngồi lại cty.
Tối rồi thím ơi, lót dép :D
 
Thím nào còn mong Nodejs nó muti-thread là éo bao giờ hiểu được bản chất của single thread lẫn miti-thread. Cứ nghĩ server phải muti-thread mới nhanh mới mạnh?

Có bao giờ não đặt câu hỏi tại sao thằng Nodejs tuy single thread nó lại có thể xử lý rất nhanh khi có cả trăm, cả ngàn request?

Tôi đánh dấu ở đây, tối rảnh sẽ giải thích. Chuẩn bị tan làm rồi, k muốn ráng ngồi lại cty.
bác giải thích cho em với
 
Vậy học chưa tới ấy chứ. Thôi về nhà học bài tiếp đi.

Search google call stack, event loop js. Xem nó single thread mà sao vẫn làm webserver handle cả đống request được.

Mà nodejs cũng có worker thread đó thôi. Muốn spam thread thích thì cứ làm.

Btw thích lập trình optimize như tới từng core từng thread thì đừng xài js làm gì. Ví dụ làm game, chạy thuật toán,tool xử lý ảnh... thì người ta đương phải code mấy ngôn ngữ bậc thấp để optimize core thread. Nói chư ngay cả game giờ mới nhiều game chạy dc nhiều core. Chứ xưa game chay 2 core là ác chiến rồi.
dạ em còn kém, nên hỏi/cmt có thể sai, mong các bạn bỏ quá và chỉ ra chỗ nào em sai để e học ạ
 
bác chưa hiểu vấn đề rồi, có bài toán như chat chit cần realtime thì nó cần không có khoảng thời gian chết, còn bài toán cần tính toán nặng thì cần phải bật đa luồng, bật đa luồng ở đây là 2 đoạn code được thi song song, đó mới là ý nghĩa, chứ không phải đa luồng là nhiều core ở cpu, mình ko rõ bên phần cứng sẽ như nào, ví dụ bên python/c#/java vì hiện mình có thể bật thỏa mái số thread được mà nhỉ, đâu phải cpu 2 nhân thì chỉ bật được 2 thread.
Thím mới là người không hiểu vấn đề ấy, cái async await không phải là dừng thread mà nó chỉ là cách viết khác của Promise mà thôi, tức là đống code phía dưới async sẽ được nhét vào callback khi resolve ấy.
Khi xử lí các request thím phải đánh giá nhiều khía cạnh xem thực chất nó nghẽn ở đâu. Nó có thể nghẽn ở database, nó có thể nghẽn ở đường truyền... Việc của CPU trong phần lớn các service viết bằng nodejs là serialize/deserialize dữ liệu rồi ném cho thằng khác xử lí. Khi số lượng request nhiều lên thì cái card mạng nó còn nghẽn trước cả CPU ấy (chưa kể đến nghẽn db nhé). Các thím đừng đánh giá thằng Nodejs yếu vì nó chỉ chạy single thread, bởi vì đơn giản các task nó xử lí tốt thì việc 1 core mạnh là quá thừa, các task khác cần đến multithread (tính toán nhiều, mã hóa ....) thì họ không dùng js nữa đâu.
 
Thím mới là người không hiểu vấn đề ấy, cái async await không phải là dừng thread mà nó chỉ là cách viết khác của Promise mà thôi, tức là đống code phía dưới async sẽ được nhét vào callback khi resolve ấy.
Khi xử lí các request thím phải đánh giá nhiều khía cạnh xem thực chất nó nghẽn ở đâu. Nó có thể nghẽn ở database, nó có thể nghẽn ở đường truyền... Việc của CPU trong phần lớn các service viết bằng nodejs là serialize/deserialize dữ liệu rồi ném cho thằng khác xử lí. Khi số lượng request nhiều lên thì cái card mạng nó còn nghẽn trước cả CPU ấy (chưa kể đến nghẽn db nhé). Các thím đừng đánh giá thằng Nodejs yếu vì nó chỉ chạy single thread, bởi vì đơn giản các task nó xử lí tốt thì việc 1 core mạnh là quá thừa, các task khác cần đến multithread (tính toán nhiều, mã hóa ....) thì họ không dùng js nữa đâu.
Bạn giải thích dễ hiểu quá. Đọc cả cái thớt hiểu được mỗi comment của bạn. Vỡ ra bao nhiêu kiến thức.
 
Thím mới là người không hiểu vấn đề ấy, cái async await không phải là dừng thread mà nó chỉ là cách viết khác của Promise mà thôi, tức là đống code phía dưới async sẽ được nhét vào callback khi resolve ấy.
Khi xử lí các request thím phải đánh giá nhiều khía cạnh xem thực chất nó nghẽn ở đâu. Nó có thể nghẽn ở database, nó có thể nghẽn ở đường truyền... Việc của CPU trong phần lớn các service viết bằng nodejs là serialize/deserialize dữ liệu rồi ném cho thằng khác xử lí. Khi số lượng request nhiều lên thì cái card mạng nó còn nghẽn trước cả CPU ấy (chưa kể đến nghẽn db nhé). Các thím đừng đánh giá thằng Nodejs yếu vì nó chỉ chạy single thread, bởi vì đơn giản các task nó xử lí tốt thì việc 1 core mạnh là quá thừa, các task khác cần đến multithread (tính toán nhiều, mã hóa ....) thì họ không dùng js nữa đâu.
bạn có thể thấy đoạn code get request kia, nó phải có kết quả mới chạy đến dòng if, tức là nó đã chờ có kết quả, như vậy là mình gọi là dừng thread.
nếu không dùng await, thì có cách khác dùng callback, nếu dùng callback thì đoạn phía phía sau được thực thi mà không cần chờ kết quả-khi đó sẽ hiệu quả hơn do cpu được dùng ngay ko phải chờ
1637246664630.png
 
Multi thread không phải lúc nào cũng tốt đâu bạn. Nếu sinh quá nhiều thread thì sẽ xảy ra hiện tiện thời gian để chuyển context của thread sẽ nhiều hơn so với thời gian xử lý thread đó, nên giờ những thằng như golang sẽ có kiểu chạy trên 1 vài main thread còn còn lại là thread ảo do đó thread ( goroutine ) của golang nhẹ hơn đáng kể so với java, còn như nodejs thì luồng điều khiển của js là đơn luồng nhưng luồng thực thi là đa luồng.
 
bạn có thể thấy đoạn code get request kia, nó phải có kết quả mới chạy đến dòng if, tức là nó đã chờ có kết quả, như vậy là mình gọi là dừng thread.
nếu không dùng await, thì có cách khác dùng callback, nếu dùng callback thì đoạn phía phía sau được thực thi mà không cần chờ kết quả-khi đó sẽ hiệu quả hơn do cpu được dùng ngay ko phải chờ
View attachment 875443
Nếu bác muốn chạy ngay sang dòng if thì có thể ko dùng await nữa, kệ nó tự chạy

( giả sử tác vụ in chẳng hạn, ko cần quan tâm kết quả trả về ntn, lỗi sẽ có try catch handle )

Ví dụ của bác là cần chờ nó chạy xong gửi kq về để làm tiếp thì mới dùng await ở đó

Await là bắt nó dừng lại đợi, ko await thì nó vẫn chạy thôi,

Còn vụ bác bảo callback chạy luôn, ko chờ kq nghe cứ sai sai, nó vẫn phải có kq mới chạy đến cái callback chứ

Async callbacks

Async callbacks are functions that are specified as arguments when calling a function which will start executing code in the background. When the background code finishes running, it calls the callback function to let you know the work is done, or to let you know that something of interest has happened. Using callbacks is slightly old-fashioned now, but you'll still see them in use in a number of older-but-still-commonly-used APIs.
 
Last edited:
bạn có thể thấy đoạn code get request kia, nó phải có kết quả mới chạy đến dòng if, tức là nó đã chờ có kết quả, như vậy là mình gọi là dừng thread.
nếu không dùng await, thì có cách khác dùng callback, nếu dùng callback thì đoạn phía phía sau được thực thi mà không cần chờ kết quả-khi đó sẽ hiệu quả hơn do cpu được dùng ngay ko phải chờ
View attachment 875443
Bạn đọc thêm nhiều sách/bài viết về javascript thì bạn mới hiểu bản chất. Bây giờ bạn thử đặt 1 cái setTimeout trước cái await ấy, xong xem cái body của setTimeout thực thi trước hay cái if else phía dưới thực thi trước là hiểu. Javascript là single thread, nếu wait cái request này (theo như giải thích của bạn) thì body của setTimeout sẽ chạy sau cái if else.
 
bạn có thể thấy đoạn code get request kia, nó phải có kết quả mới chạy đến dòng if, tức là nó đã chờ có kết quả, như vậy là mình gọi là dừng thread.
nếu không dùng await, thì có cách khác dùng callback, nếu dùng callback thì đoạn phía phía sau được thực thi mà không cần chờ kết quả-khi đó sẽ hiệu quả hơn do cpu được dùng ngay ko phải chờ
View attachment 875443
Callback nó được thực hiện ngay sau khi cái hàm gọi callback xử lý xong nha bác.
 
Cứ hiểu Nodejs nó như mấy e nhân viên nhận order khách ở kfc ấy. Cái khoảng thời gian làm đồ ăn mới lâu thì nó đẩy cho nhà bếp làm rồi, mấy e chỉ có nhiệm vụ nhận order từ khách, khi nào đồ xong thì mang ra. Việc xử lý order của từng khách 1 khá là nhanh, khi nào bếp xong thì sẽ trả về cho khách. Nodejs cũng thế nó nhận request rồi đẩy xuống mấy thread ở background, cùng xử lý 1 lúc (đa luồng ở đây). Những cái nó đẩy đi dc là http request, database request, file.. Còn những tác vụ tính toán thì vẫn phải tự xử lý, nên k phù hợp với những cái nặng tính toán như xử lý ảnh, crypto. Cũng có cái worker thread sinh ra để hỗ trợ mấy cái này, nhưng mà tốt nhất right tool for right job, k có ngôn ngữ nào phù hợp với tất cả nhu cầu. Tùy làm gì mà chọn thôi.

Sent from Xiaomi Redmi 5 Plus using vozFApp
 
Giờ tôi mới rảnh. Tạm giải thích thế này:

NodeJS là single-threaded và nó sử dụng single CPU core. Vậy bài toán đặt ra là NodeJS làm thế nào để xử lý hàng ngàn kết nối đồng thời? Chính là cơ chế Non blocking I/O. Cơ chế này hoạt động theo kiểu yêu cầu thực thi I/O operation ᴠà trả ᴠề ngaу lập tức (timeout = 0). Nếu operation chưa ѕẵn ѕàng để thực hiện thì thử lại ѕau. Nghĩa là Nodejs sử dụng tất cả các thời gian rảnh của CPU, mà các bạn phải hiểu rằng server single CPU core ngày nay nó xử lý 1 triệu phép tính/s => Với những request I/O từ client không phải là xử lý dữ liệu lớn thì nó đồng thời response ngay cho cả ngàn request trên cùng một thời điểm. Tôi đã test với server single CPU core có 4GB RAM, đạt 2000 connections realtime.

Với những ứng dụng lớn, hàng vài chục ngàn, vài trăm ngàn conn/s thì họ sẽ chạy Nodejs trên một multi-core server sử dụng cluster module để vừa giải quyết quá tải kết nối và xử lý các request nặng vừa vừa. Nặng quá hàng trăm, hàng GB thì là câu chuyện khác :D

Với những request nặng như kiểu xử file lý ảnh, file text nặng như kiểu PDF, Docs... và cả file video từ client gửi lên server thì lúc này là lúc Nodejs gọi ra các module được viết bằng C/C++.

Nhìn chung thì Nodejs là đơn luồng, dever muốn nó xử lý theo phong cách đa luồng thì nó có đủ trò để làm đấy. Vấn đề cốt yếu vẫn là hiểu biết và khả năng lập trình của bạn mà thôi. Đặc tả một website là tuần tự, lập trình đa luồng khá phức tạp. Nên kể cả dever Java, PHP cũng tránh Multithreading
 
Last edited:
Mà tôi nói rồi, NodeJS sử dụng single CPU core. Bởi vì bản chất tại một thời điểm 1 core CPU chỉ có thể xử lý một tác vụ. CPU ngày nay nó xử lý hàng triệu phép tính/s => nhiều khi nó xử lý hàng trăm task/s thành ra con người không cảm nhận được sự chênh lệch thời gian về xử lý tuần tự. Người ta đặt ra khái niệm dealing (phân chia xử lý) để nói đến khái niệm concurrency (xử lý đồng thời) thành ra dever non tay nhiều ông còn nhập nhèm giữa mutithread với lại muti process. Nhầm nốt mutithread với lại muti process của OS, của CPU, của VM. Nguyên nhân phần lớn đến từ "Học nhanh 9 tháng 10 ngày" đi làm dev mà ra.

Ngoài ra thì còn vấn đề làm cái cũng sử dụng framework, làm gì cũng có lib, có docs sẵn hết rồi. Không cần đào sâu tầng dưới làm gì nên cứ gọi lib, FW ra sài auto ngon nên khi gặp bài toán phức tạp là chết ngay. Tôi ngày nay đi code embedded cũng vậy, cái đéo gì tôi cũng có FW, Lib, docs tận răng nên tôi cũng lười suy nghĩ. Ráp lib vào code, chạy ngon nghẻ, sếp gật gù tăng lương là tôi quên cm nó nguyên tắc muốn code có chiều sâu thì phải mò vào tầng phía dưới.

Lần này thì tôi đã ngộ ra và bắt đầu lôi lại tập vở ngày xưa học hồi ĐH để học lại chính những gì mình đã cặm cụi dùi mài khi xưa để ôn lại.
 
Last edited:
bạn có thể thấy đoạn code get request kia, nó phải có kết quả mới chạy đến dòng if, tức là nó đã chờ có kết quả, như vậy là mình gọi là dừng thread.
nếu không dùng await, thì có cách khác dùng callback, nếu dùng callback thì đoạn phía phía sau được thực thi mà không cần chờ kết quả-khi đó sẽ hiệu quả hơn do cpu được dùng ngay ko phải chờ
View attachment 875443
Thím vẫn hiểu sai, như thím kia nói thì async/await chẳng qua là cách viết khác của promise. Còn promise thực chất là cách thay thế cho callback để sử dụng các asynchronous operation, nhằm giải quyết vấn đề callback hell của JS ngày xưa.

Cú pháp await khiến cho một hàm async (hoặc promise) chạy xong rồi mới chạy đoạn code phía dưới không có nghĩa là nó block event loop. Thím đã hiểu tại sao cú pháp await chỉ được dùng trong async function chưa :sneaky:
 
Back
Top