如何通过PBS脚本在集群上持续监测Java模型的内存与时间消耗
按模拟年份记录Java模型的内存与时间消耗方案
完全可行,以下是几种实用方案,可根据是否愿意修改代码来选择:
一、Java代码内部埋点(最精准匹配模拟年份)
直接在模型代码中针对每个模拟年份的开始/结束节点埋点,能完美对齐模拟进度:
- 时间消耗记录:在每个模拟年份启动时调用
System.currentTimeMillis()记录起始时间戳,年份计算完成后再次获取时间戳,差值即为该年份耗时,将年份、耗时写入独立日志(如yearly_timing.log)。 - 内存占用记录:通过
Runtime类实时获取JVM内存数据:
将年份、已用内存、最大内存按结构化格式(如// 获取已使用内存(字节) long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); // 转换为MB long usedMemoryMB = usedMemory / (1024 * 1024); // 获取最大可用内存(MB) long maxMemoryMB = Runtime.getRuntime().maxMemory() / (1024 * 1024);年份,耗时(ms),已用内存(MB),最大内存(MB))写入日志,方便后续分析。
二、外部工具定时采样(无需修改代码)
如果不想改动Java程序,可通过系统工具定时采集进程数据,再结合模型输出的年份时间点关联数据:
1. 用jstat监控JVM内存(推荐)
jstat是JDK自带工具,可输出JVM内存、GC等详细指标。修改你的PBS脚本,在启动Java程序后后台运行采样任务:
#!/bin/bash #PBS -l ncpus=1 #PBS -l mem=10 #PBS -l walltime=10:00:00 . /appli/anaconda/latest/etc/profile.d/conda.sh conda activate MODEL rm -rfv $SCRATCH/0D/* cp -r $HOME/MODELDIRECTORY/0D $SCRATCH cp $HOME/MODELDIRECTORY/inst/java/MODEL.jar $SCRATCH/0D cd $SCRATCH/0D # 启动Java程序并记录进程PID java -Xmx6g -jar MODEL.jar CONFIG.csv >& output.log & JAVA_PID=$! # 后台每30秒采样一次JVM内存数据(可根据模拟年份时长调整间隔) # 输出包含时间戳、各内存区域使用率等信息 jstat -gcutil $JAVA_PID 30000 > jstat_memory.log & # 等待Java程序结束后终止采样进程 wait $JAVA_PID pkill -P $$ jstat
之后可通过output.log中模拟年份的输出时间,对应jstat_memory.log的采样时间戳,匹配每个年份的内存变化。
2. 用ps+date记录进程物理内存
如果集群没有jstat,可通过ps获取进程物理内存占用:
# 启动Java程序后 java -Xmx6g -jar MODEL.jar CONFIG.csv >& output.log & JAVA_PID=$! # 每30秒采样一次,记录时间、PID、物理内存(RSS) while kill -0 $JAVA_PID 2>/dev/null; do echo "$(date +%Y-%m-%d_%H:%M:%S),$(ps -o rss= -p $JAVA_PID)" >> process_memory.log sleep 30 done & wait $JAVA_PID
三、增强time命令的输出
默认time信息有限,可使用系统自带的/usr/bin/time(避免shell内置的time)获取更详细的汇总资源数据:
/usr/bin/time -v java -Xmx6g -jar MODEL.jar CONFIG.csv >& output.log
该命令会在stderr输出内存峰值、CPU使用率、上下文切换次数等汇总数据,适合和前两种方案配合,作为整体性能参考。
注意事项
- 外部采样的间隔需匹配模拟年份的时长,比如每个模拟年运行10分钟,可设置1分钟采样一次,避免数据冗余或缺失。
- 确保集群节点安装了JDK(含
jstat),若未安装可通过conda安装openjdk包。
内容的提问来源于stack exchange,提问作者moody_modeller
相关产品推荐
相关产品推荐

