Skip to content
目录

页面在打开10小时后内存达到高峰,然后下降250MB,随后稳定没有大波动”的现象,可能的原因分析

总量限制

Chrome的V8引擎在64位操作系统上,对单个堆的内存限制通常是约1.5GB到2GB

  • 表层原因是,V8最初为浏览器而设计,不太可能遇到用大量内存的场景
  • 深层原因是,V8的垃圾回收机制的限制(如果清理大量的内存垃圾是很耗时间,这样回引起JavaScript线程暂停执行的时间,那么性能和应用直线下降)
  • 我的电脑console.log(performance.memory.jsHeapSizeLimit); 打印2172649472 字节大约等于 2072 MB 或 2.02 GB

垃圾回收机制分析

  1. 内存高峰的原因
    • 在运行的前几小时,JavaScript 应用可能会产生大量对象,这些对象由于条件或事件的变化而存活在内存中。由于垃圾回收机制的特性,内存使用量可能会逐渐增加,直到达到系统的内存限制或垃圾回收的触发条件(如老年代使用量超过阈值)。
  2. 老年代的使用量阈值
    • 根据 V8 的垃圾回收机制,当老年代的内存使用达到某个阈值(通常是其总量的 75% 或 80%)时,会触发 Mark-Compact 垃圾回收。这意味着一旦内存占用过高,系统需要释放内存并整理内存碎片
  3. 内存下降250MB的原因
    • 经过一次 Mark-Compact 的过程,存活对象被标记并整理后,内存中不再活跃的对象会被清除。这一过程能够有效地释放未被使用的内存,从而导致内存使用量下降250MB。
    • 此时,V8 对老年代的对象进行了清理,并通过整理将存活的对象向内存的一端移动,从而减少了内存碎片
  4. 稳定状态的出现
    • 在内存清理之后,系统进入了比较稳定的状态。由于 JavaScript 运行时环境的特点,假设在此之后没有新的大量对象被创建,或者即使创建对象,由于使用合理的内存管理和正确的对象寿命控制,内存的占用保持在一个相对平稳的水平,因此没有大波动。

垃圾回收过程的细节

分代回收机制

  • V8 将对象分为新生代和老生代:
    • 新生代中的对象大部分是短生命周期的,主要使用 Scavenge 算法进行回收。
    • 老生代中的对象生命周期较长,使用 Mark-Sweep 和 Mark-Compact 算法进行回收。 标记-压缩 (Mark-Compact)
  • 在老生代垃圾回收时:
    • 首先,系统会对内存中的所有活跃对象进行标记,识别出存活对象。
    • 随着标记的完成,清扫过程将非活动(未标记)的对象移除。
    • 此后,活跃的对象将被整理(移动)到内存的一端,清除边界外的空间以消除内存碎片全停顿 (Stop-the-world)
  • 在老生代垃圾回收过程中,可能会发生全停顿,这个过程会影响到正在执行的 JavaScript 应用,导致一些响应的延迟。

结论

通过这一现象的分析,可以得出以下总结:

  • 内存使用量的波动是由对象的创建与销毁、以及垃圾回收的机制直接相关的
  • 当内存使用达到预设的阈值时,V8 垃圾回收器会自动触发 Mark-Compact 垃圾回收,这导致内存迅速释放并整理,最终使得内存使用趋于平稳。 适当的内存管理和减少不必要的对象创建可以帮助降低内存压力,提升应用的性能和用户体验。这也是优化 JavaScript 应用的重要方向。
本站总访问量 次 本站访客数 人次

1111111111111111111