三分钟了解内存管理

本文由 六不准 翻译。
原文出处:A crash course in memory management

此篇文章是以下系列文章中的第一篇:

如果你想了解 Javascript 引入 ArrayBuffer 和 SharedArrayBuffer 的原因,那么你最好知道一些内存管理的知识。

你可以把内存想象成一些盒子。它们可以是办公室里面的快递箱,也可以是小宝贝们装玩具的盒子。

如果你想把玩具留给其他小朋友玩,那么你可以先把这个玩具放进这个盒子里。

image

每个盒子有一个编号,那就是内存地址。有了这个编号,其他人就可以根据它来找到这个盒子。

这些盒子都一样大小,可以存储一定容量的信息。盒子的大小是根据计算机来确定的,平时我们称它为字长。通常字长为 32-bits or 64-bits。在这篇文章,为了更直观的展示,我用 8-bits(位)来表示。

image

如果我们想把数字 2 存到这些盒子里,非常简单,把数字转换成二进制即可。

image

那么问题来了,如果我们想把一个字母存进区,比如字母H,该怎么办呢?

答案是,我们可以用数字的方式来代表字母,所以我们需要用 UTF-8 等编码格式对字母进行编码。然后,再转换成相应的数字,原理就像下面的编码转盘一样。这样我们就可以存储一个字母啦。
image

当我们想把已编码的 H 从盒子里面取出来的时候,得需要一个解码器将其转换回字母 H 。

自动化的内存管理

一般情况下,当你写 JavaScript 代码的时候,你并不需要考虑到内存,更不需要直接操作内存,那谁在帮你完成呢?答案是:JS引擎。它会在你和内存之间搭起一座桥梁,帮助你管理内存。

image

举个例子,当我们用 React 来创建一个变量的时候。

image

JS 引擎会将变量进行编译,将其转化成二进制方式。

image

并且 JS 引擎会在内存中找到一个区域用来存储编译好的变量。通常这个过程叫内存分配。

image

内存分配结束以后,JS 引擎还会持续监听这个变量访问情况。如果这个变量不再被访问,那么内存会将这个变量占有的空间清空,清空以后的空间可以用来存放新的变量。

image

JS 引擎处理将各种类型的变量(字符串,对象和其他类型的值)分配进内存,当这些变量不再被访问并且将其从内存中清空的过程,我们称之为垃圾回收。

像 JavaScript 不直接操作内存的这类语言,通常我们称它们为内存自动管理语言。

这种自动化的内存管理的机制对开发者来说更为简单方便。但是这种方式也有不足的地方,那就是会加大内存开销,有时候而这些开销会对代码性能产生不可预知的影响。

手动内存管理

手动调度和自动管理内存的语言有较大区别。举个例子,让我们来看下,如果用 C 语言编写的话,React会如何工作?(现在可以WebAssembly来实现哟)

C 语言没有 JavaScript 在内存中的抽象层。相反,你直接操作内存,比如读写操作。

image

当你编译 C 或者 WebAssembly 语言的时候,我们使用的工具会加入一些辅助代码。比如,用来编码或者解码。这些代码我们通常称之为运行环境。运行环境对于 C 或者 WebAssembly 的作用类似于 JS 引擎对 Javascript 作用.

image

手动调度内存的语言,有一个特性,那就是运行环境不包含垃圾回收机制。

但是不要太担心,那并不是意味着开发者只能靠自己,什么事情都得亲历亲为。事实上,你仍然可以从运行环境中得到一些帮助。比如,C 语言中,开发环境会一直监控内存的使用状态,将空闲的空间提供给新的变量。

image

在代码过程中,你可以使用 函数 malloc (memory allocate 简称),要求运行环境从内存空闲列表中找到适合存储你数据的地址。内存空闲列表会把刚占用的区域地址删除掉。当这些数据使用完毕,你又可以调用 deallocate 方法,将占用的内存释放。这个时候内存空闲列表又会加上刚刚占用的区域。

写代码过程中,什么时候调用分配以及回收内存这些函数,因为都是开发者自己决定的,所以我们称之为手动内存管理。

作为开发者,搞清楚什么时候去清理内存不同区域是一件很困难的事情。如果你在错误的阶段去清理,很有可能会导致 bug 甚至一些安全漏洞。反过来,要是不清理,又会导致内存泄漏。

这就是为什么很多现代语言都用自动化内存管理来避免一些人为的错误。但是这种方式会产生额外开销影响到性能。这个点会在下一篇文章来详细介绍。

关于作者 Lin Clark

Lin 是 Mozilla 的一名工程师。她的工作领域有:JavaScript,WebAssembly,Rust,和 Servo,当然还会画一些可爱形象的关于代码的漫画。

code-cartoons.com

@linclark

作者的更多文章…