当前位置: 首页 > 知识库问答 >
问题:

Akka http scala服务中的Zig-zag堆内存模式

殷浩慨
2023-03-14

我有一个基于AKKA-HTTP的服务,它是用Scala编写的。此服务用作API调用的代理。它使用https://doc.akka.io/docs/akka-http/current/client-side/host-level.html创建一个用于调用API的主机连接池

我想了解这种“之”字形模式的原因,即使服务上没有流量,并且主机池中的连接由于空闲超时而终止。

此外,我还想知道,是否只有在达到一个阈值(比如7GB)后才会出现完整的GC?或者它也可以发生在其他一些没有交通的时间?

该服务的XmX为8GB。而且,还有多个执行多个任务的调度器(fork-join-executor)。

共有1个答案

堵睿范
2023-03-14

通常,对于不是引用计数的GC,您会看到这种“之”字形模式,因为只有在GC运行时才会回收内存。

G1通常只收集堆中它希望找到大量相对于活动对象的垃圾的区域(“垃圾收集”有点用词不当:它实际上包括收集活动对象,并(在像G1这样的重新定位垃圾收集器的情况下)将活动对象移动到堆的不同区域,这允许将它收集的区域声明为新分配做好准备;因此它需要处理的活动对象越少,它需要做的相对于释放的内存的工作就越少)。

在高层,G1通过定义一个Eden(年轻一代)来工作,其中新创建的对象分配了新创建的对象,并且它将Eden划分为多个区域,每个线程映射到一个区域。当一个区域被填满时,只有该区域被收集,幸存者被移入老一代(这是简化)。这个过程一直持续到生还者世代满为止,此时生还者世代和伊甸园世代被收集起来,幸存的生还者被提升到老世代,当老世代满时,你就有一个满的GC了。

因此,触发完整GC的阈值不一定是固定的,但一般而言,堆用得越多,运行完整GC的可能性就越大。除此之外,JVM上的垃圾收集器往往或多或少是自治的:大多数垃圾收集器会忽略system.gc和/或其他触发GC的尝试。

在G1中,如果您在启动时分配了一个多GIB数组,丢弃了引用,然后在每次空闲之后重新分配了一个与启动时分配的数组大小相同的数组,然后丢弃了引用,那么您就有很大的机会触发一个完整的GC。这是因为该数组足够大,可以绕过eden直接进入旧代,在旧代中,它将消耗heap直到下一个完整的GC。最终,旧代中将没有足够的连续可用空间来分配这些数组,这将触发一个完整的GC。这种方法的唯一复杂之处是:

>

  • 您最终必须胜过JIT优化器,它将看到您分配了这个数组并丢弃它,并决定它实际上不必分配这个数组

    如果您有足够长的繁忙时间,以至于自上次分配并丢弃之后运行了一个完整的GC,则无法保证在一个完整的GC之后大数组的分配会成功,这将导致OOM。

  •  类似资料:
    • 本文向大家介绍如何使用CSS创建自适应Zig zag(交替)布局?,包括了如何使用CSS创建自适应Zig zag(交替)布局?的使用技巧和注意事项,需要的朋友参考一下 要使用CSS创建响应之字形布局,代码如下- 示例 输出结果 上面的代码将产生以下输出- 在调整屏幕大小时-

    • 本文向大家介绍java 中堆内存和栈内存理解,包括了java 中堆内存和栈内存理解的使用技巧和注意事项,需要的朋友参考一下  Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存

    • 我使用的是ignite 2.9。本机持久性已禁用。 使用在堆缓存上启用 缓存配置。setOnheapCacheEnabled(真) 但我仍然可以在日志中看到堆外指标。 在将on heap设置为true后,它不应该只使用堆内存吗 什么类型的数据存储在堆外 在为堆上的默认数据区域定义的逐出策略为random2Lru和LRU的情况下,逐出如何工作

    • 本文向大家介绍简述JAVA中堆内存与栈内存的区别,包括了简述JAVA中堆内存与栈内存的区别的使用技巧和注意事项,需要的朋友参考一下 Java把内存划分成两种:一种是栈内存,一种是堆内存。 一、栈内存       存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则。       栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都在函数的栈内存中分配。当在一段代码块定义一个变量时,

    • 本文向大家介绍Java中的堆栈和堆内存之间的区别,包括了Java中的堆栈和堆内存之间的区别的使用技巧和注意事项,需要的朋友参考一下 JVM将内存空间分为两部分,一个是堆栈,另一个是堆空间。堆栈空间主要用于存储方法执行的顺序和局部变量。 堆栈始终按照LIFO顺序存储块,而堆内存使用动态分配来分配和取消分配内存块。  分配给堆的内存将一直存在,直到发生以下事件之一: 程序终止  无记忆  相反,分配给

    • 我们Java开发人员有时会使用来确保我们为每个特定于线程的堆栈提供了1MB的空间。现在,我经常感到困惑,JVM从哪里借用了1MB,从堆或系统内存中借用,或者Java为线程分配任何特定的内存。你能帮我理解一下吗? 此外,我们是否有一个可视化(插件)运行时工具,可以以可理解的方式显示堆和堆栈的内容? 提前感谢。