【问题标题】:Relationship between event loop,libuv and v8 engine事件循环、libuv和v8引擎的关系
【发布时间】:2018-09-23 11:05:27
【问题描述】:

我正在学习 Node.js 的架构。我有以下问题。

  1. 事件循环是 libuv 还是 v8 的一部分?
  2. 事件队列是事件循环的一部分吗?事件队列是由 libuv 或 v8 引擎还是事件循环本身生成的?
  3. libuv 和 v8 引擎有什么联系?
  4. 如果事件循环是单线程的,libuv 是否可以创建多个线程来处理文件 I/O?
  5. 浏览器有事件循环机制还是只有 Node.js 有?

【问题讨论】:

  • 对于 2. 循环只是将事物拉出队列并执行它们。如果队列为空并且没有后台线程可能会向队列添加工作,则循环结束。

标签: javascript node.js v8 libuv


【解决方案1】:
  1. 事件循环首先是一个高级概念,它是 JavaScript 编程模型的基本组成部分。实际上,每个 V8 嵌入器都需要实现一个事件循环。 V8 提供了一个默认实现,嵌入器可以替换或扩展它。

  2. 我不明白这个问题。 (我猜答案是“是”,但“事件循环”和“事件队列”有什么区别?)

  3. 无。 (除了 Node.js 两者都使用。)

  4. 是的,事件循环是单线程的。

  5. 是的,浏览器也有事件循环(参见问题 1)。

【讨论】:

【解决方案2】:

这实际上并不像选择作为答案的帖子中给出的那么简单。我希望我的发言会更准确一些。希望我在关于 Node 事件循环的演讲中正确理解了 Sam Roberts (IBM)。

要亲自观看演讲,您可以访问此处:https://www.youtube.com/watch?v=P9csgxBgaZ8

这是对@jmrk 给出的答案的补充

Libuv 将任务委托给底层操作系统。然后,操作系统负责在您正在收听的事件发生时发送通知。它为您在 Node.js 中执行的许多操作执行此操作。比如:套接字(net/dgram/http/tls/https/child_process 管道、stdin、out、err)、超时和间隔。

但是,并非所有内容都可以像这样委托给底层操作系统。有时需要创建一个线程(默认情况下有 4 个胎面,但您可以使用 UV_THREADPOOL_SIZE 更改它)。不可轮询的是文件系统操作、dns.lookup() 和一些加密函数。

【讨论】:

    【解决方案3】:

    V8 项目和 libuv 项目是 NodeJS 最重要的两个依赖项。

    我认为在进入节点事件循环之前对什么是线程有一个基本的了解是很重要的。

    因此,让我们将线程视为需要由 CPU 执行的指令的待办事项列表,CPU 将从上到下一个接一个地运行这些线程。单个进程内部可以有多个线程。

    要了解线程,还必须了解一个称为调度的概念,因为您的 CPU 每秒只能处理这么多指令。

    现在V8libuvEvent Loop之间是什么关系?

    嗯,我建立的V8libuv都是NodeJS的依赖,这使得JavaScript可以在浏览器之外运行。每当我们在计算机上启动 Node 程序时,Node 会自动启动一个线程并在该线程内执行一些代码。在单个线程内部有一个称为事件循环的东西,可以将其视为一种控制结构,它决定我们的一个线程在任何时间点应该做什么。

    它是任何Node程序的绝对核心,每个Node程序都有一个Event Loop

    所以:

    事件循环是 libuv 还是 v8 的一部分?

    是的,事件循环来自 Node 启动的进程,该进程具有 V8libuv 作为依赖项。

    事件队列是事件循环的一部分吗?事件队列是由 libuv 或 v8 引擎还是事件循环本身生成的?

    事件队列,如果我理解这个问题更多地归结为您的操作系统调度程序。它决定哪些是最紧急的任务并首先运行。

    libuv和v8引擎有什么联系?

    嗯,它们都是 NodeJS 的依赖项,都是用 C++ 编写的,V8 是 70% C++,libuv 是 100% C++。

    如果事件循环是单线程的,libuv 是否可以创建多个线程来处理文件 I/O?

    所以这可能会造成混淆,Node 事件循环 是单线程的,但一些 Node 标准库 模块和一些框架不是单线程的。

    libuv 库使 Node 能够访问您的操作系统。 libuv 模块和 C++ 端使用线程池。它可用于运行计算量大的任务。

    默认情况下,libuv 在线程池中创建四个线程。除了事件循环中使用的线程之外,还有四个其他线程可用于卸载需要在应用程序内部进行的昂贵计算。

    Node 标准库中的许多函数都使用了这个线程池。所以是的,libuv 出现在图片中以创建一个由四个线程组成的线程池。因此,libuv 提供了一个线程池,用于卸载需要在非常昂贵的函数调用上完成的工作。

    浏览器有事件循环机制还是只有 Node.js 有?

    我只知道 NodeJS 内部的事件循环机制。

    总之,我们有一台 2015 年的双核 MacBook Pro。想象一下,您运行两个计算量大的函数,第一个在线程池内的第一个线程上运行,它通过 OS 调度程序 并到达第一个 CPU 核心。然后第二个函数被分配给池中的第二个线程,并被分配给第二个 CPU 内核。所以线程池发生在 libuv 内部。

    有一点很重要,如果您正在发出http 请求,libuv 会看到这一点,并且 libuv 和 Node 都没有任何代码来处理所有超低级别涉及网络请求的操作。而是 libuvhttp 请求委托给底层操作系统。

    在这种情况下,libuv 用于向操作系统发出请求,并等待操作系统发出返回请求的响应。因此,因为 libuv 将此委托给您的操作系统,所以由您的操作系统决定是否添加新线程。这是一个 http 请求,我们不受 libuv 的四线程线程池的限制。所有的工作都由操作系统自己完成,我们根本没有接触线程池。

    【讨论】:

      【解决方案4】:

      通过这些点:-

      1. V8 发动机是火车车厢的发动机。它有一定的职责,包括提供事件循环来运行异步任务。

      2. 事件循环是执行异步任务的核心。一旦 C++ Web API 完成一个函数(任务),就会调用回调。它被移动到事件队列并等待直到堆栈变空。因此,事件队列是事件循环的一部分,由事件循环生成。

      3. V8 引擎用于执行我们编写的 javascript 代码,而 libuv 是一个库,用于在 Nodejs 中提供多线程功能以执行长时间运行的进程。

      4. 事件循环是单线程的,但 Nodejs 不是单线程的,因为它在运行时有一个 libuv 线程池,负责多线程。

      5. 浏览器 API 也提供事件循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-31
        • 2021-10-30
        • 2018-10-11
        • 1970-01-01
        • 2017-04-13
        • 2020-04-06
        相关资源
        最近更新 更多