CPU和Memory压测程序
背景:服务暂未上线,但是为了避免缩容,需要有一个程序提高服务器CPU和Memory使用率.
代码实现
创建maven工程,编写主实现类。
App.java
package org.example;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* CPU和内存测试工具
*/
public class App {
private static final int DEFAULT_THREADS = Runtime.getRuntime().availableProcessors();
private static final int DEFAULT_DURATION = -1; // 默认无限运行,直到用户中断
private static final int DEFAULT_MEMORY = 0; // 默认不占用额外内存
public static void main(String[] args) {
int threads = DEFAULT_THREADS;
int duration = DEFAULT_DURATION;
int memoryMB = DEFAULT_MEMORY;
boolean cpuTest = true; // 默认进行CPU测试
boolean memoryTest = false;
// 解析命令行参数
for (int i = 0; i < args.length; i++) {
if ("-t".equals(args[i]) && i + 1 < args.length) {
try {
threads = Integer.parseInt(args[i + 1]);
i++;
} catch (NumberFormatException e) {
System.err.println("线程数必须是整数");
printUsage();
System.exit(1);
}
} else if ("-d".equals(args[i]) && i + 1 < args.length) {
try {
duration = Integer.parseInt(args[i + 1]);
i++;
} catch (NumberFormatException e) {
System.err.println("持续时间必须是整数(秒)");
printUsage();
System.exit(1);
}
} else if ("-m".equals(args[i]) && i + 1 < args.length) {
try {
memoryMB = Integer.parseInt(args[i + 1]);
memoryTest = true;
i++;
} catch (NumberFormatException e) {
System.err.println("内存量必须是整数(MB)");
printUsage();
System.exit(1);
}
} else if ("--no-cpu".equals(args[i])) {
cpuTest = false;
} else if ("-h".equals(args[i]) || "--help".equals(args[i])) {
printUsage();
System.exit(0);
}
}
System.out.println("开始性能压力测试");
// 显示测试配置
if (cpuTest) {
System.out.println("CPU测试线程数: " + threads);
}
if (memoryTest) {
System.out.println("内存占用: " + memoryMB + " MB");
}
if (duration > 0) {
System.out.println("持续时间: " + duration + " 秒");
} else {
System.out.println("持续时间: 无限制(按Ctrl+C终止)");
}
// 启动测试
runStressTest(cpuTest, memoryTest, threads, memoryMB, duration);
}
private static void printUsage() {
System.out.println("用法: java -jar cpu-service.jar [选项]");
System.out.println("选项:");
System.out.println(" -t <数值> 设置线程数 (默认: 可用处理器数量)");
System.out.println(" -d <数值> 设置持续时间,单位秒 (默认: 无限制运行,需手动中断)");
System.out.println(" -m <数值> 设置内存占用量,单位MB (默认: 0, 不进行内存测试)");
System.out.println(" --no-cpu 不执行CPU测试 (默认: 执行CPU测试)");
System.out.println(" -h, --help 显示帮助信息");
System.out.println("\n可同时进行CPU和内存测试,例如:");
System.out.println(" java -jar cpu-service.jar -t 4 -m 1024 -d 60");
}
/**
* 运行压力测试(可同时进行CPU和内存测试)
* @param cpuTest 是否进行CPU测试
* @param memoryTest 是否进行内存测试
* @param threads CPU测试线程数
* @param memoryMB 内存占用量(MB)
* @param durationSeconds 持续时间(秒),-1表示无限运行
*/
private static void runStressTest(boolean cpuTest, boolean memoryTest, int threads, int memoryMB, int durationSeconds) {
ExecutorService executor;
List<CpuLoadTask> cpuTasks = new ArrayList<>();
MemoryLoadTask memoryTask;
Thread memoryThread;
// 启动CPU测试
if (cpuTest) {
System.out.println("启动CPU压力测试...");
executor = Executors.newCachedThreadPool();
// 创建并启动CPU任务
for (int i = 0; i < threads; i++) {
CpuLoadTask task = new CpuLoadTask();
cpuTasks.add(task);
executor.submit(task);
}
} else {
executor = null;
}
// 启动内存测试
if (memoryTest) {
System.out.println("启动内存压力测试...");
memoryTask = new MemoryLoadTask(memoryMB);
memoryThread = new Thread(memoryTask);
memoryThread.start();
} else {
memoryTask = null;
memoryThread = null;
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("\n正在停止压力测试...");
// 停止CPU测试
if (cpuTest) {
for (CpuLoadTask task : cpuTasks) {
task.stop();
}
if (executor != null) {
executor.shutdown();
try {
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
System.out.println("CPU压力测试已停止");
}
// 停止内存测试
if (memoryTest && memoryTask != null) {
memoryTask.stop();
System.out.println("内存压力测试已停止");
}
}));
// 每3秒打印一次系统状态
Thread monitorThread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(3000);
// 打印内存使用情况
if (memoryTest) {
long totalMemory = Runtime.getRuntime().totalMemory() / (1024 * 1024);
long freeMemory = Runtime.getRuntime().freeMemory() / (1024 * 1024);
long usedMemory = totalMemory - freeMemory;
// System.out.println("当前内存使用: " + usedMemory + "MB / " + totalMemory + "MB");
}
// 这里可以添加CPU使用率监控
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
monitorThread.setDaemon(true);
monitorThread.start();
if (durationSeconds > 0) {
// 运行指定的时间
try {
Thread.sleep(durationSeconds * 1000L);
// 停止所有任务
if (cpuTest) {
for (CpuLoadTask task : cpuTasks) {
task.stop();
}
if (executor != null) {
executor.shutdown();
try {
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
if (memoryTest && memoryTask != null) {
memoryTask.stop();
}
monitorThread.interrupt();
System.out.println("压力测试完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
} else {
// 无限运行,等待用户中断
try {
// 等待任意活动线程结束(实际上不会结束,除非用户中断)
if (memoryThread != null) {
memoryThread.join();
} else {
Thread.currentThread().join();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
/**
* 内存负载任务
*/
private static class MemoryLoadTask implements Runnable {
private volatile boolean running = true;
private final int targetMemoryMB;
private static final List<byte[]> memoryBlocks = new ArrayList<>();
public MemoryLoadTask(int memoryMB) {
this.targetMemoryMB = memoryMB;
}
@Override
public void run() {
try {
// 分配指定大小的内存
allocateMemory();
// 保持程序运行并保持内存分配状态
while (running) {
// 每个内存块执行一些操作,确保它们不会被GC回收
touchMemoryBlocks();
Thread.sleep(1000);
}
} catch (OutOfMemoryError e) {
System.err.println("内存分配失败,请尝试较小的内存值: " + e.getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 释放内存
memoryBlocks.clear();
System.gc();
}
}
private void allocateMemory() {
int allocated = 0;
// 每次分配1MB块
final int blockSize = 1024 * 1024; // 1MB
while (allocated < targetMemoryMB && running) {
try {
memoryBlocks.add(new byte[blockSize]);
allocated++;
} catch (OutOfMemoryError e) {
System.err.println("在分配 " + allocated + "MB 后内存不足");
break;
}
}
System.out.println("内存分配完成,共分配 " + allocated + "MB");
}
private void touchMemoryBlocks() {
// 随机访问内存块,确保它们不被GC回收
if (!memoryBlocks.isEmpty()) {
int randomIndex = (int) (Math.random() * memoryBlocks.size());
byte[] block = memoryBlocks.get(randomIndex);
if (block != null && block.length > 0) {
// 写入一些数据
block[0] = 1;
// 读取一些数据
byte temp = block[block.length / 2];
// 确保使用了读取的值
if (temp == Byte.MAX_VALUE) {
block[0] = 0;
}
}
}
}
public void stop() {
running = false;
memoryBlocks.clear();
System.gc();
}
}
/**
* CPU负载任务
*/
private static class CpuLoadTask implements Runnable {
private volatile boolean running = true;
private static final int LOOP_COUNT = 10000;
private static final int INNER_LOOP_COUNT = 1000;
@Override
public void run() {
// 使用原始数组而不是Java集合,以避免GC和优化
double[] results = new double[4096];
long[] primeNumbers = new long[1024];
// 设置线程优先级为最高,确保获得最大CPU时间
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
// 预填充素数数组,避免初始化开销
generatePrimeNumbers(primeNumbers);
while (running) {
try {
// 使用多种不同类型的计算来消耗CPU
for (int i = 0; i < LOOP_COUNT; i++) {
// 1. 浮点数密集型计算
doFloatingPointCalculations(results);
// 2. 整数密集型计算
doIntegerCalculations(primeNumbers);
// 3. 位操作密集型计算
doBitwiseOperations(results);
// 4. 混合计算
doMixedCalculations(results, primeNumbers);
}
// 强制使用计算结果,防止编译器优化掉计算
double sum = 0;
for (double result : results) {
sum += result;
}
// 使用volatile变量存储结果,确保不被优化掉
if (sum == Double.POSITIVE_INFINITY) {
System.out.println(".");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 生成素数填充数组
*/
private void generatePrimeNumbers(long[] primes) {
int count = 0;
long num = 2;
while (count < primes.length) {
if (isPrime(num)) {
primes[count++] = num;
}
num++;
}
}
/**
* 检查一个数是否为素数
*/
private boolean isPrime(long n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (long i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
/**
* 执行浮点数密集型计算
*/
private void doFloatingPointCalculations(double[] results) {
for (int i = 0; i < INNER_LOOP_COUNT; i++) {
int index = i % results.length;
double a = Math.random() * 100;
results[index] = Math.sin(a) * Math.cos(a) / (Math.tan(a) + 0.1);
results[(index + 1) % results.length] = Math.exp(Math.min(a, 3)) * Math.log(a + 1);
results[(index + 2) % results.length] = Math.pow(a, Math.min(a % 5, 3)) * Math.sqrt(a);
}
}
/**
* 执行整数密集型计算
*/
private void doIntegerCalculations(long[] primes) {
long result = 0;
for (int i = 0; i < INNER_LOOP_COUNT; i++) {
int index1 = i % primes.length;
int index2 = (i * 7 + 3) % primes.length;
result += (primes[index1] * primes[index2]) % (primes[(index1 + index2) % primes.length] + 1);
}
// 确保结果被使用
if (result == Long.MAX_VALUE) {
primes[0] = result;
}
}
/**
* 执行位操作密集型计算
*/
private void doBitwiseOperations(double[] results) {
long bits = 0x7FFFFFFFFFFFFFFFL;
for (int i = 0; i < INNER_LOOP_COUNT; i++) {
int index = i % results.length;
bits = (bits << 1) | (bits >>> 63);
bits ^= (long) results[index];
bits = Long.rotateLeft(bits, 5);
bits &= ~(1L << (i % 64));
results[index] = Double.longBitsToDouble(bits & 0x7FFFFFFFFFFFFFFFL);
}
}
/**
* 执行混合计算
*/
private void doMixedCalculations(double[] results, long[] primes) {
for (int i = 0; i < INNER_LOOP_COUNT; i++) {
int index1 = i % results.length;
int index2 = i % primes.length;
// 混合浮点计算和整数计算
double value = Math.sin(results[index1]) + Math.cos(primes[index2]);
results[index1] = value * value;
// 确保每次迭代结果依赖于前一次计算结果
if (i > 0) {
results[index1] += results[(index1 - 1) % results.length] * 0.01;
}
}
}
public void stop() {
running = false;
}
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>cpu-service</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cpu-service</name>
<description>CPU压力测试工具</description>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>cpu-service</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.example.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>