Node.js 线程你理解的可能是错的

本文代码运行环境 系统:MacOS High Sierra Node.js:10.3.0 复制代码

Node.js是单线程的,那么Node.js启动后线程数是1?

答案:Node.js启动后线程数并不是1,以下面代码为例

const http = require('http');  http.createServer((req, res) => {     res.end('hello'); }).listen(8000, () => {   console.log('server is listening: ' + 8000); }); 复制代码

通过Mac实用工具 > 活动监视器可以查看进程的线程数其实是6


Node.js启动的线程数不为1,是因为线程池?

答案:线程数不为1,不是因为线程池,而是因为V8。Node.js启动后会创建V8实例,V8实例是多线程的,V8中的线程有:

  • 主线程:获取代码、编译执行
  • 编译线程:主线程执行的时候,可以优化代码
  • Profiler线程:记录哪些方法耗时,为优化提供支持
  • 其他线程:用于垃圾回收清除工作,因为是多个线程,所以可以并行清除

Node.js线程池是预先创建好的?

答案:并不是,线程池中的线程是按需创建的。

const http = require('http'); const fs = require('fs');  http.createServer((req, res) => {   fs.readFile('./c.js', () => {});   res.end('hello'); }).listen(8000, () => {   console.log('server is listening: ' + 8000); }); 复制代码

上面代码启动后,线程数依然是6


通过ab模拟访问后

ab -n1000 -c20 'http://192.168.76.101:8000/' 复制代码

线程数才变成了10。之所以为10,是因为线程池中线程的默认值是4。

异步IO都要占用线程池?

答案:并不是,网络IO不会占用线程池

const http = require('http');  http.createServer((req, res) => {   http.get('http://192.168.1.100');   res.end('hello'); }).listen(8000, () => {   console.log('server is listening: ' + 8000); }); 复制代码

上面这段代码,使用ab压测

ab -n10000 -c20 'http://192.168.76.101:8000' 复制代码

无论多少次访问都不会创建线程,线程数永远为6。

文件IO一定会占用线程池?

答案:并不是,*Sync会阻塞主线程所以不会占用线程池,另外fs.FSWatcher也不会占用线程池。

虽然官方文档里面提到了fs.FSWatcher,但是其实并不能直接调用,关于FSWatcher访问 StackOverflow上有一个相关的提问stackoverflow.com/questions/3…

线程池只能用于异步IO?

答案:并不是,除了一些IO密集操作外,Node.js对一些CPU密集的操作也会放到线程池里面执行(Crypto、Zlib模块)


DNS查询也有可能占用线程池?

答案:是的,因为dns.lookup方法会涉及到读取本地文件(例如nsswitch.conf,resolv.conf以及 /etc/hosts)。而dns.resolve方法就不会占用线程池,这也是lookup和resolve的区别所在。

所以下面的代码,其实是会占用线程池的,因为http.get在dns解析的时候默认使用的是lookup方法。

const http = require('http');  http.createServer((req, res) => {   http.get('http://bj.meituan.com');   res.end('hello'); }).listen(8000, () => {   console.log('server is listening: ' + 8000); }); 复制代码

线程池只供Node.js核心模块内部使用?

答案:不是的,官方文档里面有如下描述

You can use the built-in Node Worker Pool by developing a C++ addon. On older versions of Node, build your C++ addon using NAN, and on newer versions use N-APInode-webworker-threads offers a JavaScript-only way to access Node's Worker Pool.

线程池内线程数可以为0吗,可以无限大吗?

答案:不可以为0,也不是无限大的。通过UV_THREADPOOL_SIZE可以修改线程池的线程数(默认为4),线程数最大值为128,最小值为1。

主线程任何时候都不会阻塞吗?

答案:不是的,主线程在特定的情况下是会阻塞的。Node.js的事件循环中有一个阶段是poll,poll阶段在特定情况下是会阻塞的。这就是下图服务启动起来没有任何用户请求的时候Event Loop执行一次的时间比有少量请求的时候还要长的原因。


图片来源:https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c

参考资料

https://nodejs.org/en/docs/guides/dont-block-the-event-loop/ https://medium.freecodecamp.org/what-exactly-is-node-js-ae36e97449f5 https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c https://jsblog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810

nodejs v8引擎的更多相关文章

  1. Nodejs V8引擎 fast property lookup

    前言 之所以会研究这个东西,是我在网上找了一下各个语言的执行效率比较.好吧,我承认这是个无聊的东西,不过看看总是无妨,然而我惊讶的发现,有些测试声称Java,C,Nodejs是处在同一个效率级别参见链 ...

  2. nodejs v8引擎c++编译版本号升级教程

    原GCC版本号:4.4.7. 目标:升级GCC到4.8.2.以支持C++11. yum install gcc-c++ 获取GCC 4.8.2包:wget http://gcc.skazkaforyo ...

  3. 深入出不来nodejs源码-V8引擎初探

    原本打算是把node源码看得差不多了再去深入V8的,但是这两者基本上没办法分开讲. 与express是基于node的封装不同,node是基于V8的一个应用,源码内容已经渗透到V8层面,因此这章简述一下 ...

  4. 浅谈V8引擎中的垃圾回收机制

    最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...

  5. google v8引擎常见问题

    最近在项目中使用v8来进行扩展,下面简单说一下使用v8过程中遇到的一些问题.   v8的多线程调用 最初调研v8的测试代码是单线程的,后来一个项目在多线程中使用,出现了一些问题,后来看到参考3中的才恍 ...

  6. V8引擎——详解

    前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...

  7. Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略

    V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 一.前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存.垃圾 ...

  8. v8引擎详解

    引用网址: https://blog.csdn.net/swimming_in_it_/article/details/78869549 前言 JavaScript绝对是最火的编程语言之一,一直具有很 ...

  9. Node.js和Chrome V8 引擎了解

    说起Node就不得不先介绍一个Chrome V8 引擎. 随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScr ...

随机推荐

  1. 拦截chrome的console.log输出

    console.log = function(){}; 这样 console.log(123) 将不会在输出任何调试信息

  2. 【BZOJ3935】Rbtree 树形DP

    [BZOJ3935]Rbtree Description 给定一颗 N 个点的树,树上的每个点或者是红色,或者是黑色. 每个单位时间内,你可以任选两个点,交换它们的颜色. 出于某种恶趣味,你希望用最少 ...

  3. 电力项目十八--DOM对象的ajax

    Ajax操作的核心对象:xmlreq = new XMLHttpRequest(); 第一步:在dictionaryIndex.jsp中添加: <script type="text/j ...

  4. python 对文件的操作

    观看的技术文来源:http://www.cnblogs.com/alex3714/articles/5717620.htmlimport sys# data = open("yesterda ...

  5. php 常用的系统函数

    字符串函数 strlen:获取字符串长度,字节长度 substr_count 某字符串出现的次数 substr:字符串截取,获取字符串(按照字节进行截取) mb_strlenmb_substr str ...

  6. PHP 的“魔术常量”

    名称 说明 __LINE__ 文件中的当前行号. __FILE__ 文件的完整路径和文件名.如果用在被包含文件中,则返回被包含的文件名.自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路 ...

  7. 浅谈Lambda表达式详解

    lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者 “成为”.运算符将表达式分为两部分,左边指定 ...

  8. Python实现进程同步和通信

    转自:https://blog.csdn.net/u014556057/article/details/66974452

  9. MongDb的安装

    MongoDB是一个基于分布式文件存储的数据库,由c++语言编写,为WEB应用提供可扩展的高性能数据存储解决方案.MongoDB属于非关系数据库,也不能说完全属于,更像是介于关系数据库和非关系数据库之 ...

  10. 表单(下)-EasyUI Spinner 微调器、EasyUI Numberspinner 数值微调器、EasyUI Timespinner 时间微调器、EasyUI Slider 滑块

    EasyUI Spinner 微调器 扩展自 $.fn.validatebox.defaults.通过 $.fn.spinner.defaults 重写默认的 defaults. 微调器(spinne ...