内存管理技术的具体实现介绍

要理解为什么将ArrayBuffer和SharedArrayBuffer添加到JavaScript中,你需要了解一些关于内存管理的内容。

你可以将设备中的内存看作一堆盒子,这么说吧,就像你的邮箱或储蓄抽屉。

如果你由于某些目的,需要留下一些东西,你可以把它放在这个抽屉里。

1.png

在每一抽屉旁边,都会标记一个数字,这是一个内存地址,就相当于你告诉某人在哪里可以找到你为他们留下的东西。

其中这些盒子中的每一个的尺寸大小都是相同的,并且可以容纳一定量的信息。盒子的尺寸是则根据设备而异。这个大小就被称为字大小,它通常是32位或64位。但是为了使其更容易显示,我将使用8位的字大小。

2.png

如果我们想把数字2放在这些盒子之一,我们可以很容易地做到这一点。数字很容易用二进制表示。

3.png

如果我们想要的东西不是数字怎么办?用字母可以吗?

所以,我们需要用一种方法来代表我们要表示的内容。为了做到这一点,我们就需要一种编码,像UTF-8。我们需要一些工具比如一个编码器环(encoder ring)把它变成类似于UTF-8的形式,然后我们才可以存储它。

4.png

当我们想让它开箱即用时,我们必须将其通过解码器翻译过来。

自动内存管理

当你在使用JavaScript时,实际上并不需要考虑这个内存。由于它已被单独进行处理,所以这意味着你不要直接触摸内存。

相反,JS引擎会充当中介的角色,为你管理内存。

5.png

所以让我们介绍一些JS代码,如React,以方便创建一个变量。

6.png

JS引擎的作用是通过编码器运行该值以获得值的二进制表示。

7.png

它将在内存中找到可以将二进制表示放入的空间。这个过程称为分配内存。

8.png

然后,引擎将跟踪该变量,看其是否仍然可以从程序中的任何地方访问。如果该变量无法再到达,则内存将被回收,以便JS引擎可以将新值放在那里。

9.png

这个观察变量字符串,对象和其他类型的内存值的过程称为垃圾收集。像JavaScript这样不直接处理内存的语言的代码被称为内存管理语言。

这种自动内存管理虽然可以使开发人员更轻松,但它也增加了一些运行内耗,而这种内耗有时会使性能不可预测。

手动内存管理

手动管理内存的语言则与自动内存管理不同,例如,我们来看看React如何使用C语言写入内存(现在可以通过WebAssembly来实现)。

C语言没有JavaScript在内存上的抽象层,而是直接在内存上运行。你既可以从内存加载东西,也可以将内容存储到内存中。

10.png

当你将C语言或其他语言编译到WebAssembly时,你使用的工具将在WebAssembly中添加一些帮助程序代码。例如,它会添加编码和解码字节的代码。该代码就被称为运行时的环境。运行时的环境将帮助处理JS引擎所做的一些事情。

11.png

但是对于手动管理的语言来说,该运行时将不包括垃圾回收。

即使在手动内存管理的语言中,通常会从语言运行时获得一些帮助。例如,在C语言中,运行时将跟踪哪些内存地址会在空闲列表中打开。

12.png

你可以使用函数malloc(内存分配的简写)来要求运行时找到一些可以适应数据的内存地址,并将这些地址从免费列表中删除。完成这些数据后,你必须随意释放内存。那么这些地址将被添加回免费列表。

你必须弄清楚何时调用这些函数,这就是为什么它被称为手动内存管理,即你自己管理内存。

作为一名开发人员,弄清楚何时清除不同部分的内存可能很难。如果你在错误的时间进行操作,可能会导致错误,甚至导致安全漏洞。如果你不这样做,你的内存就会耗尽。

这就是为什么许多现代语言会使用自动内存管理的原因,就是为了避免人为错误。但这是以性能为代价的,我将在下一篇文章中为你进一步解释这一点。