winter daily log
Starter code for your blog

JVM启动优化

March 20, 2024

jvm启动优化

背景说明

这个项目启动大概在30分钟,目标是通过调整jdk参数来提高程序的一个启动时间

启动时间缩减到10分钟

@echo off
title [APP_NAME] Server

::Optional values: prod|dev. 
::prod:Production Environment; dev:Development Environment, Remote debugging is enabled. See the SERVER_MODE parameter
set SERVER_MODE=dev
::Optional values: true|false. true:logs are printed on the console; false:Logs are not printed at the console.
if {%SERVER_MODE%}=={prod} (
  set ENABLE_CONSOLE_LOGGING=false
) else (
  set ENABLE_CONSOLE_LOGGING=true
)

::The default value of APP_SERVER_PATH is SERVER. You can change it to another directory name, you should keep the following variable value matching with the actual directory name. Jstack is compatible with the old version, please ignore it.
set APP_SERVER_PATH=server
set APP_SERVER_HOME=%~dp0%APP_SERVER_PATH%
if not exist "%APP_SERVER_HOME%" (
  set APP_SERVER_PATH=jstack
  set APP_SERVER_HOME=%~dp0jstack
)

::The following JAVA_HOME points to the APP JDK by default; If system environment variables are used, comment out the following line; For JDKs in other locations, change the following JAVA_HOME value.
set JAVA_HOME=%APP_SERVER_HOME%\runtime\java\%PROCESSOR_ARCHITECTURE%-win

::JVM_MEMORY_OPTS is used to specify the memory parameters that the Java virtual machine can use. By default, the appropriate memory is automatically calculated based on the physical machine environment. If you need to specify a fixed value, uncomment the downward comment and change the corresponding value
REM set JVM_MEMORY_OPTS=-Xmx3350M

::Change the following line to adjust the JVM debugging parameters
if not defined DEBUG_PORT (
  set DEBUG_PORT=5006
)
set JVM_DEBUG_OPTS=-Dspring.profiles.active=dev,lsvo -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006

if not exist "%JAVA_HOME%" (
    echo Invalid JAVA_HOME Path: "%JAVA_HOME%"
	pause
	exit
)
REM echo JAVA_HOME: %JAVA_HOME%
REM echo APP_SERVER_HOME: %APP_SERVER_HOME%

for /f "delims=" %%a in ('wmic os get TotalVisibleMemorySize /value^|find "="') do set %%a
set  /a MemorySize=%TotalVisibleMemorySize% /1024 
set TotalMemorySize=%MemorySize%M

@setlocal enabledelayedexpansion
for /r "%APP_SERVER_HOME%\runtime\" %%k in (app-bootstrap*.jar) do  (
    @set APP_BOOTSTRAP="%%k"
)

::APP_Runtime
@set APP_MODULE_PATHS="%APP_SERVER_HOME%\runtime\3rd","%APP_SERVER_HOME%\runtime\libs"

:: Total Memory Size
set /a totalMem=16777216+1
for /f "skip=1" %%i in ('wmic os get TotalVisibleMemorySize') do (
    if %%i geq 0 set totalMem=%%i
)

set /a memorySize=%totalMem%/1024

::if total size less than 16G,then XmxSize=totalSize*6/10
set /a totalMem=%memorySize%/10*6
set XmxSize=%totalMem%M
if not defined JVM_MEM_OPTS (
  if %memorySize% leq 16384 set JVM_MEM_OPTS=-Xmx%XmxSize%
)

if {%SERVER_MODE%}=={prod} (
  set JVM_DEBUG_OPTS=-Dspring.profiles.active=prod,lsvo
)

Set REBEL_HOME=[REDACTED_PATH]
for /f "tokens=*" %%a in ('powershell -Command "(Get-CimInstance -ClassName Win32_Processor).NumberOfCores"') do set CPU_CORES=%%a

:: 计算并行线程数(核心数-1)
set /a PARALLEL_THREADS=23

:: 设置JVM参数
set JVM_GC_OPTS=-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:MaxGCPauseMillis=3000 -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=60 -XX:+DisableExplicitGC -XX:ParallelGCThreads=%PARALLEL_THREADS% -XX:ConcGCThreads=%PARALLEL_THREADS% 


::Dparallel.startup=true 并行启动部署信息:
"%JAVA_HOME%\bin\java" %APP_OPS% %JVM_GC_OPTS% -server  -Ddebug=true -Dloader.path=%APP_MODULE_PATHS% -Dparallel.startup=true  -Dserver.runtime.path.name=%APP_SERVER_PATH% %JVM_MEM_OPTS% %JVM_DEBUG_OPTS% -jar %APP_BOOTSTRAP% --spring.config.location="%APP_SERVER_HOME%/runtime/"

pause
::-Dparallel.startup=true

优化说明

1. 内存管理优化

  • 动态内存分配:根据系统总内存自动计算JVM堆内存大小
    • 当系统内存小于16GB时,设置最大堆内存为系统内存的60%(XmxSize=totalSize*6/10)
    • 通过wmic os get TotalVisibleMemorySize获取系统实际可用内存
    • 避免固定内存设置可能带来的资源浪费或不足问题

2. 垃圾收集器优化

  • 使用G1垃圾收集器(-XX:+UseG1GC)
    • 适合大内存应用,可预测的停顿时间
    • 设置最大GC暂停时间为3000ms(-XX:MaxGCPauseMillis=3000)
    • 优化新生代比例:
      • 初始新生代占比40%(-XX:G1NewSizePercent=40)
      • 最大新生代占比60%(-XX:G1MaxNewSizePercent=60)

3. 并行处理优化

  • 基于CPU核心数优化GC线程数
    • 设置并行GC线程数(-XX:ParallelGCThreads=23)
    • 设置并发GC线程数(-XX:ConcGCThreads=23)
    • 充分利用多核CPU资源,提高GC效率

4. 启动性能优化

  • 启用并行启动(-Dparallel.startup=true)
    • 允许应用组件并行初始化
    • 减少启动时的串行等待时间
  • 使用服务器模式(-server)
    • 启用JIT编译器优化
    • 适合长期运行的应用

5. 其他优化

  • 禁用显式GC调用(-XX:+DisableExplicitGC)
    • 防止手动调用System.gc()影响性能
  • 启用实验性JVM选项(-XX:+UnlockExperimentalVMOptions)
    • 允许使用一些实验性的JVM优化选项

这些优化措施共同作用,显著提升了应用的启动速度和运行性能。通过动态内存管理、优化的垃圾收集策略和并行处理,使应用能够更高效地利用系统资源。

6. Windows进程优先级优化

在Windows环境下,可以通过设置进程优先级来优化应用性能:

高优先级(High Priority)
  • 优点:
    • 获得更多的CPU时间片
    • 提高应用响应速度
    • 减少其他后台进程的干扰
  • 缺点:
    • 可能影响其他重要系统进程
    • 在系统负载高时可能导致其他应用响应变慢
    • 不适合长期运行的生产环境
实时优先级(Realtime Priority)
  • 优点:
    • 获得最高的CPU优先级
    • 几乎不会被其他进程抢占
    • 适合对实时性要求极高的场景
  • 缺点:
    • 可能导致系统不稳定
    • 影响系统关键进程(如系统服务)
    • 可能造成系统响应迟缓
    • 不建议在生产环境使用
建议
  1. 开发/测试环境:

    • 可以临时使用高优先级进行性能测试
    • 使用start /HIGH命令启动应用
    • 或通过任务管理器手动设置优先级
  2. 生产环境:

    • 建议保持默认优先级(Normal)
    • 避免影响系统稳定性
    • 通过其他JVM参数优化性能
  3. 特殊情况:

    • 如果确实需要提高优先级,建议使用"高于标准"(Above Normal)
    • 在系统资源充足的情况下使用
    • 需要持续监控系统性能
© Copyright 2025 winter daily log. Powered with by CreativeDesignsGuru