You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JVM(Java/Scala/Groovy/Kotlin), JavaScript, C#, Golang, OCaml, and Ruby are some of the languages that use Garbage collection for memory management by default.
现在主流的内存管理方式可以归纳为以下几种
手动内存管理
语言本身不进行内存管理,开发者需要手动进行内存管理,例如 c,c++
垃圾回收 ♻️(GC)
垃圾回收是指自动进行内存分配以及回收操作。垃圾回收是现代语言中最常见的内存管理机制,一般以固定的时间间隔来运行该过程,垃圾回收本身会产生较小的开销,称之为暂停时间
Mark & Sweep GC (标记&扫描内存回收)
也称之为追踪 GC,通常包含两步操作
alive
alive
的内存引用计数
在这种方法中,每个对象都获得一个引用计数,该引用计数随对它的引用的更改而增加或减少,并且当计数变为零时将进行垃圾回收。
在初始化获取资源 RAII
内存跟对象的生命周期绑定到一起,在构造时申请,在析构时释放。
自动引用计数(ARC)
跟引用计数类似,但会在编译时插入对应的
retain
和release
指令。该方式也不能解决循环引用计数的问题,需要开发者进行规避。v8 内存管理
V8 memory structure
由于 js 是单线程的,所以 v8 在每个 js 的上下文中使用一个进程,因此如果你使用了 Service Worker,v8 将为每一个 Service Worker 生成一个新的 v8 进程。
堆内存
V8 在此处存储对象或动态数据。这是最大的内存区域,这是垃圾回收(GC)发生的地方。
新空间(年轻代)
新对象暂存的地方,空间很小,又被分为了两个半空间(
semi-space
),该空间由“ Scavenger(Minor GC)”管理。老空间(旧世代)
在新空间存在了两次 GC 周期的对象将被移动到 old space。该空间有 主要 GC 管理
旧指针空间:包含具有指向其他对象的指针的幸存对象。
旧数据空间:包含
仅包含数据
的对象(无指向其他对象的指针)。大对象空间
这里是大于其他空间大小限制的对象所在的地方。每个对象都有自己的内存区域。
代码空间
即时(JIT)编译器在此处存储已编译的代码块。这是唯一具有可执行内存的空间(尽管 Codes 可以在“大对象空间”中分配,并且它们也是可执行的)。
Cell space, property cell space, and map space:
这些空间分别包含了
Cells
,PropertyCells
, 和Maps
,这些空间包含了大小相同的对象,并且对它们指向的对象有一些限制,从而简化了收集。
这些空间中的每一个都由一组页面组成。页面是操作系统通过 mmap 分配的连续的内存块。除较大的对象空间外,每个页面的大小均为
1MB
。Stack
每个 v8 进程都存在一个栈,用来存储静态数据。包含方法或者函数的 frame,原始类型的数据,指向对象的指针。
v8 内存使用(Heap vs Stack)
全局范围
保存在 Stack 的 全局 frame 中孤儿
对象stack 上的内存都是由系统自动管理的,通常情况下我们不需要担心 stack 上的内存管理。
与之相对的,heap 的上内存则不由系统管理,因此垃圾回收是针对 heap 上的内存进行管理。
区分堆上的指针和数据对于垃圾回收很重要,V8 为此使用“标记指针”方法-在这种方法中,它在每个单词的末尾保留一点以指示它是指针还是数据。
v8 垃圾回收机制
当程序尝试申请大于可用空间的内存时将产生 OOM 的错误,错误的内存管理方式则会导致内存泄漏
v8 通过释放那些在 heap 不在被引用的对象的内存来达到内存释放的目的。
v8 的垃圾回收器用来回收并从用未被使用的内存
Minor GC (Scavenger)
将 new space 分为大小相等的两个部分。分别命名为 from-space、to-space。
每次都是从 from-space 中分配内存,如果发现 from-space 中的内存不够,就会进行一次 GC
GC 的过程可以概况如下
Major GC(Mark-Sweep-Compact)
标记-清扫-紧凑算法
标记:这是两种算法共有的第一步,垃圾收集器在其中标识正在使用的对象和未使用的对象。从 GC 根目录(堆栈指针)递归使用或使用的对象被标记为活动对象。从技术上讲,这是对堆的深度优先搜索,可以视为有向图
清除:垃圾收集器遍历堆并记下任何未标记为活动的对象的内存地址。现在,该空间在空闲列表中被标记为空闲,可用于存储其他对象
压缩:清扫后,如果需要,所有使用中的对象将被移动到一起。这将减少碎片并提高为新对象分配内存的性能
延迟页面中垃圾的删除,直到需要内存为止。
其他文章
如何避免内存泄漏
The text was updated successfully, but these errors were encountered: