【问题标题】:how to reduce spring boot memory usage?如何减少spring boot的内存使用?
【发布时间】:2017-11-13 10:43:39
【问题描述】:

我正在使用 Spring Boot 开发客户端应用程序。 在运行spring boot应用程序时(使用完全可执行的jar),x64服务器的内存使用量约为190M,x86服务器为110M。

我的 JVM 选项是 (-Xmx64M -Xms64M -XX:MaxPermSize=64M -server), 为什么在 x64 服务器中,内存使用量如此之大? 150M以下如何减少内存使用?

谢谢。

【问题讨论】:

  • x64(64 位)指针是 x86(32 位)指针的两倍,因此 64 位模式下的内存使用量必然会更大。
  • 是的,但是我不知道除了heap + Perm之外使用什么内存。我设置了max heap size 64M,max perm size 64M,但是为什么使用了60M(190M - 64Mx2)左右,却无法减小。
  • @HailongLi 您提到了导致内存增加的原因。但是如何减少呢?
  • 稍晚一点,但这篇文章可能会有所帮助dzone.com/articles/…

标签: java memory spring-boot


【解决方案1】:

经过搜索,我发现它已经在 stackoveflow 中有答案。 Spring Boot memory consumption increases beyond -Xmx option

1. Number of http threads (Undertow starts around 50 threads per default, but you can increase / decrease via property the amount of threads needed)
2. Access to native routines (.dll, .so) via JNI
3. Static variables
4. Use of cache (memcache, ehcache, etc)
If a VM is 32 bit or 64 bit, 64 bit uses more memory to run the same application, so if you don't need a heap bigger than 1.5GB, so keep your application runnnig over 32 bit to save memory.

因为对于 http 服务(Tomcat 或 Undertow、Jetty),spring boot 每个默认启动大约 50 个线程,并且每个线程使用 1 MB(64 位 jvm 默认设置)。

所以在 64bit jvm 中,内存使用量是 堆(64M)+ Permgen(最大 64M)+ 线程堆栈(1M x 50+)+ 本机句柄。

参考:

【讨论】:

  • 如何减小这个内存大小?是因为jar文件嵌入了tomcat服务器吗?如果我们将它作为war文件运行,内存会减少吗?
  • 这个接受的答案没有回答问题。问题是如何减少内存消耗,而不是解释为什么要使用大量内存。
  • 为什么会有 5 个赞?它只是部分回答了这个问题
  • 了解某事发生的原因有助于解决问题。两个答案都很好,一个是细节,另一个是概述。他们互相恭维。
【解决方案2】:

这里有点晚了,但我在 Docker 上的容器化 Spring Boot 应用程序中遇到了同样的问题。在具有单个控制器和嵌入式 Tomcat 的最简单的 Spring Boot 应用程序上,您将得到的最低限度是大约 72M 总内存。加上 Spring Data REST、Spring Security 和一些 JPA 实体,您将看到至少 200M-300M。通过使用以下 JVM 选项,您可以将一个简单的 Spring Boot 应用程序的总大小减少到大约 72M。

With -XX:+UseSerialGC 这将与分配堆内存的线程内联执行垃圾收集,而不是使用专用的 GC 线程

使用-Xss512k这会将每个线程的堆栈内存限制为512KB,而不是默认的1MB

With -XX:MaxRAM=72m 这将限制 JVM 对堆和非堆托管内存的计算在此值的范围内。

除了上述 JVM 选项之外,您还可以在 application.properties 文件中使用以下属性:

server.tomcat.max-threads = 1这会将HTTP请求处理程序线程的数量限制为1(默认为200)


这是一个 docker stats 运行具有上述限制和 docker -m 72m 参数的简单 Spring Boot 应用程序的示例。如果我将值降低到低于此值,我将无法启动应用程序。

83ccc9b2156d: Mem Usage: 70.36MiB / 72MiB | Mem Percentage: 97.72%

在这里您可以看到退出时所有本机和 Java 堆内存的细分。

Native Memory Tracking:

Total: reserved=1398681KB, committed=112996KB
-                 Java Heap (reserved=36864KB, committed=36260KB)
                            (mmap: reserved=36864KB, committed=36260KB) 

-                     Class (reserved=1086709KB, committed=43381KB)
                            (classes #7548)
                            (  instance classes #7049, array classes #499)
                            (malloc=1269KB #19354) 
                            (mmap: reserved=1085440KB, committed=42112KB) 
                            (  Metadata:   )
                            (    reserved=36864KB, committed=36864KB)
                            (    used=36161KB)
                            (    free=703KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=1048576KB, committed=5248KB)
                            (    used=4801KB)
                            (    free=447KB)
                            (    waste=0KB =0.00%)

-                    Thread (reserved=9319KB, committed=938KB)
                            (thread #14)
                            (stack: reserved=9253KB, committed=872KB)
                            (malloc=50KB #74) 
                            (arena=16KB #26)

-                      Code (reserved=248678KB, committed=15310KB)
                            (malloc=990KB #4592) 
                            (mmap: reserved=247688KB, committed=14320KB) 

-                        GC (reserved=400KB, committed=396KB)
                            (malloc=272KB #874) 
                            (mmap: reserved=128KB, committed=124KB) 

-                  Compiler (reserved=276KB, committed=276KB)
                            (malloc=17KB #409) 
                            (arena=260KB #6)

-                  Internal (reserved=660KB, committed=660KB)
                            (malloc=620KB #1880) 
                            (mmap: reserved=40KB, committed=40KB) 

-                    Symbol (reserved=11174KB, committed=11174KB)
                            (malloc=8417KB #88784) 
                            (arena=2757KB #1)

-    Native Memory Tracking (reserved=1858KB, committed=1858KB)
                            (malloc=6KB #80) 
                            (tracking overhead=1852KB)

-               Arena Chunk (reserved=2583KB, committed=2583KB)
                            (malloc=2583KB) 

-                   Logging (reserved=4KB, committed=4KB)
                            (malloc=4KB #179) 

-                 Arguments (reserved=17KB, committed=17KB)
                            (malloc=17KB #470) 

-                    Module (reserved=137KB, committed=137KB)
                            (malloc=137KB #1616)

也不要期望从中获得任何不错的性能,因为我认为 GC 会在此设置下频繁运行,因为它没有很多空闲内存可供使用

【讨论】:

  • 2020 年的救生员,我的 heroku dyno 的 -XX:MaxRAM 设置不断抛出 R14 故障
  • 72 MB?!哈!!是的,我的应用程序开始为 950 MB。 Spring boot 2.3.0,无非就是几个 REST 控制器。启动时间不到 10 秒,但即使没有收到任何请求,也没有对其施加任何负载,它会飙升至 1GB 并保持在那里。
  • @JeneralJames 这正是在生产中发生在我身上的。我越来越觉得这不是容器化世界的技术。这确实是为单片应用程序服务器和数百个端点(控制器)而设计的。这就是为什么像 quarkus 这样的 Java 领域的新技术正在出现以解决这个问题。更好的平台,如 Node/Go/.net 核心,为云/容器原生架构奠定了基础。
【解决方案3】:

您可以使用 -XX:+UseSerialGC 作为 JVM 参数来指定串行垃圾收集器,这是减少内存堆的最佳选择。

【讨论】:

    猜你喜欢
    • 2019-12-07
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2011-12-02
    • 2010-09-10
    • 1970-01-01
    相关资源
    最近更新 更多