本章概述
应用程序性能分析是VisualVM最重要的应用场景之一。本章将深入介绍如何使用VisualVM分析实际应用程序的性能问题,包括性能指标监控、瓶颈识别、数据库连接池分析、缓存性能优化等关键技能。
学习目标
- 掌握应用程序性能指标的含义和监控方法
- 学会识别和分析性能瓶颈
- 了解数据库连接池的监控和优化
- 掌握缓存系统的性能分析
- 学习Web应用程序的性能调优
- 掌握微服务架构下的性能分析
应用程序性能指标
关键性能指标(KPI)
1. 响应时间指标
- 平均响应时间:所有请求的平均处理时间
- 95%分位响应时间:95%的请求在此时间内完成
- 99%分位响应时间:99%的请求在此时间内完成
- 最大响应时间:最慢请求的处理时间
2. 吞吐量指标
- QPS(Queries Per Second):每秒查询数
- TPS(Transactions Per Second):每秒事务数
- 并发用户数:同时处理的用户请求数
3. 资源利用率指标
- CPU利用率:处理器使用百分比
- 内存利用率:内存使用百分比
- 磁盘I/O:磁盘读写速率
- 网络I/O:网络传输速率
性能监控示例程序
// PerformanceMonitor.java
import java.lang.management.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class PerformanceMonitor {
private static final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(2);
// 性能计数器
private static final AtomicLong requestCount = new AtomicLong(0);
private static final AtomicLong totalResponseTime = new AtomicLong(0);
private static final AtomicLong errorCount = new AtomicLong(0);
// 响应时间分布
private static final ConcurrentHashMap<String, AtomicLong> responseTimeDistribution =
new ConcurrentHashMap<>();
static {
responseTimeDistribution.put("<100ms", new AtomicLong(0));
responseTimeDistribution.put("100-500ms", new AtomicLong(0));
responseTimeDistribution.put("500ms-1s", new AtomicLong(0));
responseTimeDistribution.put(">1s", new AtomicLong(0));
}
public static void main(String[] args) {
System.out.println("=== 应用程序性能监控 ===");
// 启动性能监控
startPerformanceMonitoring();
// 模拟应用程序负载
simulateApplicationLoad();
// 运行5分钟
try {
Thread.sleep(300000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
scheduler.shutdown();
System.out.println("\n=== 监控结束 ===");
}
private static void startPerformanceMonitoring() {
// 每10秒打印一次性能报告
scheduler.scheduleAtFixedRate(() -> {
printPerformanceReport();
}, 10, 10, TimeUnit.SECONDS);
// 每秒打印系统资源使用情况
scheduler.scheduleAtFixedRate(() -> {
printSystemMetrics();
}, 1, 1, TimeUnit.SECONDS);
}
private static void simulateApplicationLoad() {
// 创建多个工作线程模拟不同类型的请求
for (int i = 0; i < 10; i++) {
Thread worker = new Thread(() -> {
Random random = new Random();
while (!Thread.currentThread().isInterrupted()) {
try {
// 模拟不同类型的请求
RequestType requestType = RequestType.values()[random.nextInt(RequestType.values().length)];
processRequest(requestType);
// 随机间隔
Thread.sleep(random.nextInt(100) + 50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
worker.setDaemon(true);
worker.start();
}
}
private static void processRequest(RequestType requestType) {
long startTime = System.currentTimeMillis();
try {
// 模拟请求处理
switch (requestType) {
case FAST_QUERY:
simulateFastQuery();
break;
case SLOW_QUERY:
simulateSlowQuery();
break;
case DATABASE_OPERATION:
simulateDatabaseOperation();
break;
case CACHE_OPERATION:
simulateCacheOperation();
break;
case FILE_OPERATION:
simulateFileOperation();
break;
}
// 记录成功请求
long responseTime = System.currentTimeMillis() - startTime;
recordRequest(responseTime, false);
} catch (Exception e) {
// 记录错误请求
long responseTime = System.currentTimeMillis() - startTime;
recordRequest(responseTime, true);
}
}
private static void simulateFastQuery() throws InterruptedException {
Thread.sleep(10 + new Random().nextInt(50)); // 10-60ms
}
private static void simulateSlowQuery() throws InterruptedException {
Thread.sleep(200 + new Random().nextInt(800)); // 200-1000ms
}
private static void simulateDatabaseOperation() throws InterruptedException {
Thread.sleep(50 + new Random().nextInt(200)); // 50-250ms
// 5%概率出现数据库超时
if (new Random().nextInt(100) < 5) {
throw new RuntimeException("Database timeout");
}
}
private static void simulateCacheOperation() throws InterruptedException {
Thread.sleep(1 + new Random().nextInt(10)); // 1-11ms
}
private static void simulateFileOperation() throws InterruptedException {
Thread.sleep(20 + new Random().nextInt(100)); // 20-120ms
}
private static void recordRequest(long responseTime, boolean isError) {
requestCount.incrementAndGet();
totalResponseTime.addAndGet(responseTime);
if (isError) {
errorCount.incrementAndGet();
}
// 记录响应时间分布
if (responseTime < 100) {
responseTimeDistribution.get("<100ms").incrementAndGet();
} else if (responseTime < 500) {
responseTimeDistribution.get("100-500ms").incrementAndGet();
} else if (responseTime < 1000) {
responseTimeDistribution.get("500ms-1s").incrementAndGet();
} else {
responseTimeDistribution.get(">1s").incrementAndGet();
}
}
private static void printPerformanceReport() {
long requests = requestCount.get();
long errors = errorCount.get();
long totalTime = totalResponseTime.get();
if (requests == 0) return;
double avgResponseTime = (double) totalTime / requests;
double errorRate = (double) errors / requests * 100;
System.out.println("\n=== 性能报告 ===");
System.out.printf("总请求数: %d\n", requests);
System.out.printf("错误数: %d (%.2f%%)\n", errors, errorRate);
System.out.printf("平均响应时间: %.2fms\n", avgResponseTime);
System.out.println("\n响应时间分布:");
responseTimeDistribution.forEach((range, count) -> {
double percentage = (double) count.get() / requests * 100;
System.out.printf(" %s: %d (%.2f%%)\n", range, count.get(), percentage);
});
}
private static void printSystemMetrics() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
// 内存使用情况
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
double heapUtilization = (double) heapUsage.getUsed() / heapUsage.getMax() * 100;
// CPU使用情况(如果支持)
double cpuUsage = -1;
if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
cpuUsage = ((com.sun.management.OperatingSystemMXBean) osBean).getProcessCpuLoad() * 100;
}
System.out.printf("[%s] 堆内存: %.2f%%, CPU: %.2f%%\n",
new Date(), heapUtilization, cpuUsage);
}
enum RequestType {
FAST_QUERY,
SLOW_QUERY,
DATABASE_OPERATION,
CACHE_OPERATION,
FILE_OPERATION
}
}
3. I/O瓶颈
特征: - 大量线程处于BLOCKED或WAITING状态 - 磁盘或网络I/O使用率高 - 响应时间不稳定
识别方法:
// IOBottleneckDetector.java
import java.io.*;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.*;
public class IOBottleneckDetector {
private static final int THREAD_COUNT = 20;
private static final String TEST_DIR = "io_test";
public static void main(String[] args) {
System.out.println("=== I/O瓶颈检测 ===");
// 创建测试目录
createTestDirectory();
// 启动I/O监控
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
analyzeIOPerformance();
}, 0, 5, TimeUnit.SECONDS);
// 创建I/O密集型任务
ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
final int threadId = i;
executor.submit(() -> {
performIOIntensiveTask(threadId);
});
}
// 运行3分钟
try {
Thread.sleep(180000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
executor.shutdown();
monitor.shutdown();
// 清理测试文件
cleanupTestDirectory();
}
private static void createTestDirectory() {
try {
Files.createDirectories(Paths.get(TEST_DIR));
} catch (IOException e) {
System.err.println("创建测试目录失败: " + e.getMessage());
}
}
private static void performIOIntensiveTask(int threadId) {
Random random = new Random();
int fileCount = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
String fileName = String.format("%s/thread_%d_file_%d.txt", TEST_DIR, threadId, fileCount++);
// 写文件
long writeStart = System.currentTimeMillis();
writeTestFile(fileName, random);
long writeTime = System.currentTimeMillis() - writeStart;
// 读文件
long readStart = System.currentTimeMillis();
readTestFile(fileName);
long readTime = System.currentTimeMillis() - readStart;
// 删除文件
Files.deleteIfExists(Paths.get(fileName));
if (writeTime > 100 || readTime > 100) {
System.out.printf("线程%d: 慢I/O检测 - 写入:%dms, 读取:%dms\n",
threadId, writeTime, readTime);
}
Thread.sleep(random.nextInt(100) + 50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (IOException e) {
System.err.printf("线程%d I/O错误: %s\n", threadId, e.getMessage());
}
}
}
private static void writeTestFile(String fileName, Random random) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(fileName))) {
// 写入随机数据
int lines = random.nextInt(100) + 50;
for (int i = 0; i < lines; i++) {
writer.write("Line " + i + ": " + UUID.randomUUID().toString());
writer.newLine();
}
}
}
private static void readTestFile(String fileName) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(fileName))) {
String line;
int lineCount = 0;
while ((line = reader.readLine()) != null) {
lineCount++;
// 模拟处理
if (line.length() > 100) {
// 处理长行
}
}
}
}
private static void analyzeIOPerformance() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds);
Map<Thread.State, Integer> stateCount = new HashMap<>();
int blockedThreads = 0;
for (ThreadInfo info : threadInfos) {
if (info != null) {
Thread.State state = info.getThreadState();
stateCount.put(state, stateCount.getOrDefault(state, 0) + 1);
if (state == Thread.State.BLOCKED || state == Thread.State.WAITING) {
blockedThreads++;
}
}
}
System.out.println("\n=== I/O性能分析 ===");
System.out.printf("阻塞/等待线程数: %d\n", blockedThreads);
stateCount.forEach((state, count) -> {
System.out.printf("%s: %d\n", state, count);
});
if (blockedThreads > THREAD_COUNT * 0.7) {
System.out.println("警告:检测到I/O瓶颈!大量线程处于阻塞状态");
}
}
private static void cleanupTestDirectory() {
try {
Files.walk(Paths.get(TEST_DIR))
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
} catch (IOException e) {
System.err.println("清理测试目录失败: " + e.getMessage());
}
}
}
数据库连接池监控
连接池性能指标
关键指标
连接池大小
- 最大连接数
- 当前活跃连接数
- 空闲连接数
连接获取性能
- 平均获取时间
- 最大等待时间
- 获取超时次数
连接使用情况
- 连接使用率
- 连接泄漏检测
- 长时间占用连接
数据库连接池监控示例
// DatabaseConnectionPoolMonitor.java
import java.sql.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import javax.sql.DataSource;
import java.util.*;
public class DatabaseConnectionPoolMonitor {
// 模拟连接池
private static final BlockingQueue<Connection> connectionPool = new LinkedBlockingQueue<>();
private static final int MAX_CONNECTIONS = 10;
private static final int MIN_CONNECTIONS = 2;
// 监控指标
private static final AtomicInteger activeConnections = new AtomicInteger(0);
private static final AtomicInteger totalConnectionsCreated = new AtomicInteger(0);
private static final AtomicLong totalWaitTime = new AtomicLong(0);
private static final AtomicInteger connectionTimeouts = new AtomicInteger(0);
private static final AtomicInteger connectionLeaks = new AtomicInteger(0);
// 连接使用跟踪
private static final ConcurrentHashMap<Connection, Long> connectionUsageTime = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Connection, String> connectionOwner = new ConcurrentHashMap<>();
public static void main(String[] args) {
System.out.println("=== 数据库连接池监控 ===");
// 初始化连接池
initializeConnectionPool();
// 启动监控
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
printConnectionPoolStatus();
detectConnectionLeaks();
}, 0, 10, TimeUnit.SECONDS);
// 模拟数据库操作
ExecutorService executor = Executors.newFixedThreadPool(20);
for (int i = 0; i < 50; i++) {
final int taskId = i;
executor.submit(() -> {
simulateDatabaseOperation(taskId);
});
}
// 运行5分钟
try {
Thread.sleep(300000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
executor.shutdown();
monitor.shutdown();
// 打印最终统计
printFinalStatistics();
}
private static void initializeConnectionPool() {
for (int i = 0; i < MIN_CONNECTIONS; i++) {
Connection conn = createConnection();
connectionPool.offer(conn);
}
System.out.println("连接池初始化完成,初始连接数: " + MIN_CONNECTIONS);
}
private static Connection createConnection() {
// 模拟创建数据库连接
MockConnection conn = new MockConnection();
totalConnectionsCreated.incrementAndGet();
return conn;
}
private static Connection getConnection(int timeoutMs) throws SQLException {
long startTime = System.currentTimeMillis();
try {
Connection conn = connectionPool.poll(timeoutMs, TimeUnit.MILLISECONDS);
if (conn == null) {
// 尝试创建新连接
if (activeConnections.get() < MAX_CONNECTIONS) {
conn = createConnection();
} else {
connectionTimeouts.incrementAndGet();
throw new SQLException("连接池获取超时");
}
}
long waitTime = System.currentTimeMillis() - startTime;
totalWaitTime.addAndGet(waitTime);
activeConnections.incrementAndGet();
connectionUsageTime.put(conn, System.currentTimeMillis());
connectionOwner.put(conn, Thread.currentThread().getName());
return conn;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new SQLException("获取连接被中断");
}
}
private static void releaseConnection(Connection conn) {
if (conn != null) {
activeConnections.decrementAndGet();
connectionUsageTime.remove(conn);
connectionOwner.remove(conn);
connectionPool.offer(conn);
}
}
private static void simulateDatabaseOperation(int taskId) {
Connection conn = null;
try {
// 获取连接
conn = getConnection(5000); // 5秒超时
// 模拟数据库操作
Random random = new Random();
int operationType = random.nextInt(4);
switch (operationType) {
case 0:
simulateQuickQuery(conn);
break;
case 1:
simulateSlowQuery(conn);
break;
case 2:
simulateTransaction(conn);
break;
case 3:
simulateBatchOperation(conn);
break;
}
// 5%概率模拟连接泄漏(忘记释放连接)
if (random.nextInt(100) < 5) {
System.out.println("任务 " + taskId + " 模拟连接泄漏");
connectionLeaks.incrementAndGet();
return; // 不释放连接
}
} catch (SQLException e) {
System.err.println("任务 " + taskId + " 数据库操作失败: " + e.getMessage());
} finally {
// 正常情况下释放连接
if (conn != null) {
releaseConnection(conn);
}
}
}
private static void simulateQuickQuery(Connection conn) throws SQLException {
try {
Thread.sleep(50 + new Random().nextInt(100)); // 50-150ms
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private static void simulateSlowQuery(Connection conn) throws SQLException {
try {
Thread.sleep(500 + new Random().nextInt(2000)); // 0.5-2.5s
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private static void simulateTransaction(Connection conn) throws SQLException {
try {
// 模拟事务操作
Thread.sleep(200 + new Random().nextInt(500)); // 200-700ms
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private static void simulateBatchOperation(Connection conn) throws SQLException {
try {
// 模拟批量操作
Thread.sleep(1000 + new Random().nextInt(3000)); // 1-4s
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private static void printConnectionPoolStatus() {
int poolSize = connectionPool.size();
int active = activeConnections.get();
int total = totalConnectionsCreated.get();
long avgWaitTime = total > 0 ? totalWaitTime.get() / total : 0;
System.out.println("\n=== 连接池状态 ===");
System.out.printf("池中连接数: %d\n", poolSize);
System.out.printf("活跃连接数: %d\n", active);
System.out.printf("总创建连接数: %d\n", total);
System.out.printf("平均等待时间: %dms\n", avgWaitTime);
System.out.printf("连接超时次数: %d\n", connectionTimeouts.get());
System.out.printf("连接泄漏次数: %d\n", connectionLeaks.get());
double utilizationRate = (double) active / MAX_CONNECTIONS * 100;
System.out.printf("连接池使用率: %.2f%%\n", utilizationRate);
if (utilizationRate > 80) {
System.out.println("警告:连接池使用率过高!");
}
}
private static void detectConnectionLeaks() {
long currentTime = System.currentTimeMillis();
long leakThreshold = 30000; // 30秒
connectionUsageTime.forEach((conn, startTime) -> {
long usageTime = currentTime - startTime;
if (usageTime > leakThreshold) {
String owner = connectionOwner.get(conn);
System.out.printf("警告:检测到可能的连接泄漏 - 连接被线程 %s 占用 %dms\n",
owner, usageTime);
}
});
}
private static void printFinalStatistics() {
System.out.println("\n=== 最终统计 ===");
System.out.printf("总连接创建数: %d\n", totalConnectionsCreated.get());
System.out.printf("连接超时总次数: %d\n", connectionTimeouts.get());
System.out.printf("连接泄漏总次数: %d\n", connectionLeaks.get());
System.out.printf("总等待时间: %dms\n", totalWaitTime.get());
if (connectionLeaks.get() > 0) {
System.out.println("建议:检查应用代码,确保所有数据库连接都被正确释放");
}
if (connectionTimeouts.get() > 0) {
System.out.println("建议:考虑增加连接池大小或优化数据库查询性能");
}
}
// 模拟数据库连接类
static class MockConnection implements Connection {
private final String id = UUID.randomUUID().toString().substring(0, 8);
@Override
public String toString() {
return "MockConnection[" + id + "]";
}
// 实现Connection接口的其他方法(省略具体实现)
@Override public Statement createStatement() throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql) throws SQLException { return null; }
@Override public CallableStatement prepareCall(String sql) throws SQLException { return null; }
@Override public String nativeSQL(String sql) throws SQLException { return null; }
@Override public void setAutoCommit(boolean autoCommit) throws SQLException {}
@Override public boolean getAutoCommit() throws SQLException { return false; }
@Override public void commit() throws SQLException {}
@Override public void rollback() throws SQLException {}
@Override public void close() throws SQLException {}
@Override public boolean isClosed() throws SQLException { return false; }
@Override public DatabaseMetaData getMetaData() throws SQLException { return null; }
@Override public void setReadOnly(boolean readOnly) throws SQLException {}
@Override public boolean isReadOnly() throws SQLException { return false; }
@Override public void setCatalog(String catalog) throws SQLException {}
@Override public String getCatalog() throws SQLException { return null; }
@Override public void setTransactionIsolation(int level) throws SQLException {}
@Override public int getTransactionIsolation() throws SQLException { return 0; }
@Override public SQLWarning getWarnings() throws SQLException { return null; }
@Override public void clearWarnings() throws SQLException {}
@Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
@Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return null; }
@Override public Map<String, Class<?>> getTypeMap() throws SQLException { return null; }
@Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException {}
@Override public void setHoldability(int holdability) throws SQLException {}
@Override public int getHoldability() throws SQLException { return 0; }
@Override public Savepoint setSavepoint() throws SQLException { return null; }
@Override public Savepoint setSavepoint(String name) throws SQLException { return null; }
@Override public void rollback(Savepoint savepoint) throws SQLException {}
@Override public void releaseSavepoint(Savepoint savepoint) throws SQLException {}
@Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
@Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return null; }
@Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return null; }
@Override public Clob createClob() throws SQLException { return null; }
@Override public Blob createBlob() throws SQLException { return null; }
@Override public NClob createNClob() throws SQLException { return null; }
@Override public SQLXML createSQLXML() throws SQLException { return null; }
@Override public boolean isValid(int timeout) throws SQLException { return true; }
@Override public void setClientInfo(String name, String value) throws SQLClientInfoException {}
@Override public void setClientInfo(Properties properties) throws SQLClientInfoException {}
@Override public String getClientInfo(String name) throws SQLException { return null; }
@Override public Properties getClientInfo() throws SQLException { return null; }
@Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return null; }
@Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return null; }
@Override public void setSchema(String schema) throws SQLException {}
@Override public String getSchema() throws SQLException { return null; }
@Override public void abort(Executor executor) throws SQLException {}
@Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {}
@Override public int getNetworkTimeout() throws SQLException { return 0; }
@Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
@Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
}
}
应用程序性能优化策略
代码层面优化
1. 算法优化
// AlgorithmOptimization.java
import java.util.*;
import java.util.concurrent.*;
public class AlgorithmOptimization {
public static void main(String[] args) {
System.out.println("=== 算法优化示例 ===");
// 测试数据
List<Integer> data = generateTestData(100000);
// 低效算法 vs 高效算法
compareSearchAlgorithms(data);
compareSortingAlgorithms(data);
compareCollectionOperations();
}
private static List<Integer> generateTestData(int size) {
List<Integer> data = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < size; i++) {
data.add(random.nextInt(size));
}
return data;
}
private static void compareSearchAlgorithms(List<Integer> data) {
System.out.println("\n--- 搜索算法对比 ---");
int target = data.get(data.size() / 2);
// 线性搜索(低效)
long start = System.nanoTime();
boolean found1 = linearSearch(data, target);
long time1 = System.nanoTime() - start;
// 使用HashSet(高效)
Set<Integer> dataSet = new HashSet<>(data);
start = System.nanoTime();
boolean found2 = dataSet.contains(target);
long time2 = System.nanoTime() - start;
System.out.printf("线性搜索: %s, 耗时: %d ns\n", found1, time1);
System.out.printf("HashSet搜索: %s, 耗时: %d ns\n", found2, time2);
System.out.printf("性能提升: %.2fx\n", (double) time1 / time2);
}
private static boolean linearSearch(List<Integer> data, int target) {
for (int value : data) {
if (value == target) {
return true;
}
}
return false;
}
private static void compareSortingAlgorithms(List<Integer> data) {
System.out.println("\n--- 排序算法对比 ---");
// 冒泡排序(低效)
List<Integer> data1 = new ArrayList<>(data.subList(0, 1000)); // 小数据集
long start = System.nanoTime();
bubbleSort(data1);
long time1 = System.nanoTime() - start;
// Collections.sort(高效)
List<Integer> data2 = new ArrayList<>(data.subList(0, 1000));
start = System.nanoTime();
Collections.sort(data2);
long time2 = System.nanoTime() - start;
System.out.printf("冒泡排序: 耗时 %d ns\n", time1);
System.out.printf("Collections.sort: 耗时 %d ns\n", time2);
System.out.printf("性能提升: %.2fx\n", (double) time1 / time2);
}
private static void bubbleSort(List<Integer> data) {
int n = data.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (data.get(j) > data.get(j + 1)) {
Collections.swap(data, j, j + 1);
}
}
}
}
private static void compareCollectionOperations() {
System.out.println("\n--- 集合操作对比 ---");
int size = 100000;
// ArrayList vs LinkedList 随机访问
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
// 填充数据
for (int i = 0; i < size; i++) {
arrayList.add(i);
linkedList.add(i);
}
// 随机访问测试
Random random = new Random();
long start = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int index = random.nextInt(size);
arrayList.get(index);
}
long arrayListTime = System.nanoTime() - start;
start = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int index = random.nextInt(size);
linkedList.get(index);
}
long linkedListTime = System.nanoTime() - start;
System.out.printf("ArrayList随机访问: %d ns\n", arrayListTime);
System.out.printf("LinkedList随机访问: %d ns\n", linkedListTime);
System.out.printf("ArrayList性能优势: %.2fx\n", (double) linkedListTime / arrayListTime);
}
}
2. 缓存策略
// CacheOptimization.java
import java.util.concurrent.*;
import java.util.*;
public class CacheOptimization {
// 简单缓存实现
private static final Map<String, Object> simpleCache = new ConcurrentHashMap<>();
// LRU缓存实现
private static final int CACHE_SIZE = 1000;
private static final Map<String, Object> lruCache = new LinkedHashMap<String, Object>(CACHE_SIZE, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
return size() > CACHE_SIZE;
}
};
public static void main(String[] args) {
System.out.println("=== 缓存优化示例 ===");
// 测试缓存效果
testCachePerformance();
// 测试缓存策略
testCacheStrategies();
}
private static void testCachePerformance() {
System.out.println("\n--- 缓存性能测试 ---");
int iterations = 10000;
// 无缓存
long start = System.nanoTime();
for (int i = 0; i < iterations; i++) {
String key = "key" + (i % 100); // 重复访问相同的key
expensiveOperation(key);
}
long noCacheTime = System.nanoTime() - start;
// 有缓存
start = System.nanoTime();
for (int i = 0; i < iterations; i++) {
String key = "key" + (i % 100);
getCachedResult(key);
}
long cacheTime = System.nanoTime() - start;
System.out.printf("无缓存耗时: %d ns\n", noCacheTime);
System.out.printf("有缓存耗时: %d ns\n", cacheTime);
System.out.printf("性能提升: %.2fx\n", (double) noCacheTime / cacheTime);
}
private static Object expensiveOperation(String key) {
// 模拟耗时操作
try {
Thread.sleep(1); // 1ms
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "result_" + key;
}
private static Object getCachedResult(String key) {
return simpleCache.computeIfAbsent(key, k -> expensiveOperation(k));
}
private static void testCacheStrategies() {
System.out.println("\n--- 缓存策略测试 ---");
// 测试不同缓存策略的命中率
testCacheHitRate("简单缓存", simpleCache);
testCacheHitRate("LRU缓存", lruCache);
}
private static void testCacheHitRate(String cacheName, Map<String, Object> cache) {
cache.clear();
int totalRequests = 10000;
int hitCount = 0;
Random random = new Random();
for (int i = 0; i < totalRequests; i++) {
// 80%概率访问热点数据,20%概率访问随机数据
String key;
if (random.nextDouble() < 0.8) {
key = "hot_key_" + random.nextInt(50); // 热点数据
} else {
key = "cold_key_" + random.nextInt(1000); // 冷数据
}
if (cache.containsKey(key)) {
hitCount++;
} else {
cache.put(key, "value_" + key);
}
}
double hitRate = (double) hitCount / totalRequests * 100;
System.out.printf("%s命中率: %.2f%% (%d/%d)\n", cacheName, hitRate, hitCount, totalRequests);
}
}
3. 并发优化
// ConcurrencyOptimization.java
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.*;
public class ConcurrencyOptimization {
private static final int THREAD_COUNT = Runtime.getRuntime().availableProcessors();
private static final int TASK_COUNT = 100000;
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 并发优化示例 ===");
// 比较串行 vs 并行处理
compareSerialVsParallel();
// 比较不同并发工具
compareConcurrencyTools();
// 测试锁优化
testLockOptimization();
}
private static void compareSerialVsParallel() throws InterruptedException {
System.out.println("\n--- 串行 vs 并行处理 ---");
List<Integer> data = new ArrayList<>();
for (int i = 0; i < TASK_COUNT; i++) {
data.add(i);
}
// 串行处理
long start = System.nanoTime();
long serialSum = data.stream()
.mapToLong(ConcurrencyOptimization::expensiveComputation)
.sum();
long serialTime = System.nanoTime() - start;
// 并行处理
start = System.nanoTime();
long parallelSum = data.parallelStream()
.mapToLong(ConcurrencyOptimization::expensiveComputation)
.sum();
long parallelTime = System.nanoTime() - start;
System.out.printf("串行处理: 结果=%d, 耗时=%d ms\n", serialSum, serialTime / 1_000_000);
System.out.printf("并行处理: 结果=%d, 耗时=%d ms\n", parallelSum, parallelTime / 1_000_000);
System.out.printf("性能提升: %.2fx\n", (double) serialTime / parallelTime);
}
private static long expensiveComputation(int value) {
// 模拟CPU密集型计算
long result = 0;
for (int i = 0; i < 1000; i++) {
result += Math.sqrt(value * i);
}
return result;
}
private static void compareConcurrencyTools() throws InterruptedException {
System.out.println("\n--- 并发工具对比 ---");
// 测试AtomicInteger vs synchronized
testAtomicVsSynchronized();
// 测试ConcurrentHashMap vs synchronized HashMap
testConcurrentCollections();
}
private static void testAtomicVsSynchronized() throws InterruptedException {
System.out.println("\n--- AtomicInteger vs Synchronized ---");
// AtomicInteger测试
AtomicInteger atomicCounter = new AtomicInteger(0);
long start = System.nanoTime();
CountDownLatch latch1 = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
new Thread(() -> {
for (int j = 0; j < TASK_COUNT / THREAD_COUNT; j++) {
atomicCounter.incrementAndGet();
}
latch1.countDown();
}).start();
}
latch1.await();
long atomicTime = System.nanoTime() - start;
// Synchronized测试
SynchronizedCounter syncCounter = new SynchronizedCounter();
start = System.nanoTime();
CountDownLatch latch2 = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
new Thread(() -> {
for (int j = 0; j < TASK_COUNT / THREAD_COUNT; j++) {
syncCounter.increment();
}
latch2.countDown();
}).start();
}
latch2.await();
long syncTime = System.nanoTime() - start;
System.out.printf("AtomicInteger: 结果=%d, 耗时=%d ms\n",
atomicCounter.get(), atomicTime / 1_000_000);
System.out.printf("Synchronized: 结果=%d, 耗时=%d ms\n",
syncCounter.getValue(), syncTime / 1_000_000);
System.out.printf("AtomicInteger性能优势: %.2fx\n", (double) syncTime / atomicTime);
}
private static void testConcurrentCollections() throws InterruptedException {
System.out.println("\n--- ConcurrentHashMap vs Synchronized HashMap ---");
// ConcurrentHashMap测试
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
long start = System.nanoTime();
CountDownLatch latch1 = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < TASK_COUNT / THREAD_COUNT; j++) {
String key = "key_" + (threadId * 1000 + j);
concurrentMap.put(key, j);
}
latch1.countDown();
}).start();
}
latch1.await();
long concurrentTime = System.nanoTime() - start;
// Synchronized HashMap测试
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
start = System.nanoTime();
CountDownLatch latch2 = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++) {
final int threadId = i;
new Thread(() -> {
for (int j = 0; j < TASK_COUNT / THREAD_COUNT; j++) {
String key = "key_" + (threadId * 1000 + j);
syncMap.put(key, j);
}
latch2.countDown();
}).start();
}
latch2.await();
long syncTime = System.nanoTime() - start;
System.out.printf("ConcurrentHashMap: 大小=%d, 耗时=%d ms\n",
concurrentMap.size(), concurrentTime / 1_000_000);
System.out.printf("Synchronized HashMap: 大小=%d, 耗时=%d ms\n",
syncMap.size(), syncTime / 1_000_000);
System.out.printf("ConcurrentHashMap性能优势: %.2fx\n", (double) syncTime / concurrentTime);
}
private static void testLockOptimization() throws InterruptedException {
System.out.println("\n--- 锁优化测试 ---");
// 测试读写锁 vs 普通锁
testReadWriteLock();
}
private static void testReadWriteLock() throws InterruptedException {
System.out.println("\n--- ReadWriteLock vs ReentrantLock ---");
SharedResource resource1 = new SharedResource();
SharedResourceWithReadWriteLock resource2 = new SharedResourceWithReadWriteLock();
int readerCount = 8;
int writerCount = 2;
int operationsPerThread = 1000;
// 测试ReentrantLock
long start = System.nanoTime();
CountDownLatch latch1 = new CountDownLatch(readerCount + writerCount);
for (int i = 0; i < readerCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
resource1.read();
}
latch1.countDown();
}).start();
}
for (int i = 0; i < writerCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
resource1.write(j);
}
latch1.countDown();
}).start();
}
latch1.await();
long reentrantTime = System.nanoTime() - start;
// 测试ReadWriteLock
start = System.nanoTime();
CountDownLatch latch2 = new CountDownLatch(readerCount + writerCount);
for (int i = 0; i < readerCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
resource2.read();
}
latch2.countDown();
}).start();
}
for (int i = 0; i < writerCount; i++) {
new Thread(() -> {
for (int j = 0; j < operationsPerThread; j++) {
resource2.write(j);
}
latch2.countDown();
}).start();
}
latch2.await();
long readWriteTime = System.nanoTime() - start;
System.out.printf("ReentrantLock: 耗时=%d ms\n", reentrantTime / 1_000_000);
System.out.printf("ReadWriteLock: 耗时=%d ms\n", readWriteTime / 1_000_000);
System.out.printf("ReadWriteLock性能优势: %.2fx\n", (double) reentrantTime / readWriteTime);
}
// 辅助类
static class SynchronizedCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getValue() {
return count;
}
}
static class SharedResource {
private final ReentrantLock lock = new ReentrantLock();
private int value = 0;
public int read() {
lock.lock();
try {
// 模拟读操作
Thread.sleep(1);
return value;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return 0;
} finally {
lock.unlock();
}
}
public void write(int newValue) {
lock.lock();
try {
// 模拟写操作
Thread.sleep(1);
value = newValue;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
}
static class SharedResourceWithReadWriteLock {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
private int value = 0;
public int read() {
readLock.lock();
try {
// 模拟读操作
Thread.sleep(1);
return value;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return 0;
} finally {
readLock.unlock();
}
}
public void write(int newValue) {
writeLock.lock();
try {
// 模拟写操作
Thread.sleep(1);
value = newValue;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
writeLock.unlock();
}
}
}
}
实践练习
练习1:综合性能分析
创建一个综合性能分析练习,模拟真实应用场景:
// PerformanceAnalysisExercise.java
import java.util.concurrent.*;
import java.util.*;
import java.lang.management.*;
public class PerformanceAnalysisExercise {
private static final int USER_COUNT = 100;
private static final int OPERATIONS_PER_USER = 1000;
// 模拟服务组件
private static final UserService userService = new UserService();
private static final OrderService orderService = new OrderService();
private static final PaymentService paymentService = new PaymentService();
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 综合性能分析练习 ===");
// 启动性能监控
PerformanceMonitor monitor = new PerformanceMonitor();
monitor.startMonitoring();
// 模拟用户负载
simulateUserLoad();
// 停止监控并生成报告
monitor.stopMonitoring();
monitor.generateReport();
}
private static void simulateUserLoad() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(USER_COUNT);
CountDownLatch latch = new CountDownLatch(USER_COUNT);
for (int i = 0; i < USER_COUNT; i++) {
final int userId = i;
executor.submit(() -> {
try {
simulateUserSession(userId);
} finally {
latch.countDown();
}
});
}
latch.await();
executor.shutdown();
}
private static void simulateUserSession(int userId) {
Random random = new Random();
for (int i = 0; i < OPERATIONS_PER_USER; i++) {
try {
// 随机选择操作类型
int operationType = random.nextInt(4);
switch (operationType) {
case 0:
userService.getUserInfo(userId);
break;
case 1:
userService.updateUserProfile(userId, "profile_" + i);
break;
case 2:
orderService.createOrder(userId, "product_" + random.nextInt(100));
break;
case 3:
paymentService.processPayment(userId, random.nextDouble() * 1000);
break;
}
// 模拟用户思考时间
Thread.sleep(random.nextInt(10) + 1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
// 用户服务
static class UserService {
private final Map<Integer, String> userCache = new ConcurrentHashMap<>();
private final Random random = new Random();
public String getUserInfo(int userId) {
// 模拟缓存查找
String userInfo = userCache.get(userId);
if (userInfo == null) {
// 模拟数据库查询
simulateDBQuery(50 + random.nextInt(100));
userInfo = "User_" + userId;
userCache.put(userId, userInfo);
}
return userInfo;
}
public void updateUserProfile(int userId, String profile) {
// 模拟数据库更新
simulateDBQuery(100 + random.nextInt(200));
userCache.put(userId, profile);
}
private void simulateDBQuery(int delayMs) {
try {
Thread.sleep(delayMs);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
// 订单服务
static class OrderService {
private final AtomicLong orderIdGenerator = new AtomicLong(1);
private final Random random = new Random();
public long createOrder(int userId, String product) {
long orderId = orderIdGenerator.getAndIncrement();
// 模拟订单处理
simulateOrderProcessing();
// 模拟库存检查
simulateInventoryCheck();
return orderId;
}
private void simulateOrderProcessing() {
try {
Thread.sleep(20 + random.nextInt(50));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void simulateInventoryCheck() {
try {
Thread.sleep(30 + random.nextInt(70));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
// 支付服务
static class PaymentService {
private final Random random = new Random();
public boolean processPayment(int userId, double amount) {
// 模拟支付处理
simulatePaymentProcessing();
// 模拟第三方支付API调用
simulateThirdPartyAPI();
// 90%成功率
return random.nextDouble() < 0.9;
}
private void simulatePaymentProcessing() {
try {
Thread.sleep(100 + random.nextInt(200));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void simulateThirdPartyAPI() {
try {
// 模拟网络延迟
Thread.sleep(200 + random.nextInt(500));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
// 性能监控器
static class PerformanceMonitor {
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private final List<PerformanceSnapshot> snapshots = new ArrayList<>();
private volatile boolean monitoring = false;
public void startMonitoring() {
monitoring = true;
scheduler.scheduleAtFixedRate(this::takeSnapshot, 0, 5, TimeUnit.SECONDS);
System.out.println("性能监控已启动");
}
public void stopMonitoring() {
monitoring = false;
scheduler.shutdown();
System.out.println("性能监控已停止");
}
private void takeSnapshot() {
if (!monitoring) return;
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
long threadCount = threadBean.getThreadCount();
PerformanceSnapshot snapshot = new PerformanceSnapshot(
System.currentTimeMillis(),
heapUsage.getUsed(),
heapUsage.getMax(),
threadCount
);
snapshots.add(snapshot);
System.out.printf("[%s] 内存使用: %d MB / %d MB (%.2f%%), 线程数: %d\n",
new Date(snapshot.timestamp),
snapshot.usedMemory / 1024 / 1024,
snapshot.maxMemory / 1024 / 1024,
(double) snapshot.usedMemory / snapshot.maxMemory * 100,
snapshot.threadCount
);
}
public void generateReport() {
if (snapshots.isEmpty()) {
System.out.println("没有性能数据");
return;
}
System.out.println("\n=== 性能分析报告 ===");
// 内存使用统计
long maxMemoryUsed = snapshots.stream()
.mapToLong(s -> s.usedMemory)
.max().orElse(0);
long avgMemoryUsed = (long) snapshots.stream()
.mapToLong(s -> s.usedMemory)
.average().orElse(0);
// 线程数统计
long maxThreadCount = snapshots.stream()
.mapToLong(s -> s.threadCount)
.max().orElse(0);
long avgThreadCount = (long) snapshots.stream()
.mapToLong(s -> s.threadCount)
.average().orElse(0);
System.out.printf("内存使用 - 最大: %d MB, 平均: %d MB\n",
maxMemoryUsed / 1024 / 1024, avgMemoryUsed / 1024 / 1024);
System.out.printf("线程数 - 最大: %d, 平均: %d\n", maxThreadCount, avgThreadCount);
// 性能建议
generateRecommendations(maxMemoryUsed, avgMemoryUsed, maxThreadCount);
}
private void generateRecommendations(long maxMemory, long avgMemory, long maxThreads) {
System.out.println("\n=== 性能优化建议 ===");
if (maxMemory > 500 * 1024 * 1024) { // 500MB
System.out.println("- 内存使用较高,建议检查内存泄漏和优化对象创建");
}
if (maxThreads > 200) {
System.out.println("- 线程数过多,建议优化线程池配置");
}
double memoryVariation = (double) (maxMemory - avgMemory) / avgMemory;
if (memoryVariation > 0.5) {
System.out.println("- 内存使用波动较大,建议检查GC配置");
}
}
}
// 性能快照
static class PerformanceSnapshot {
final long timestamp;
final long usedMemory;
final long maxMemory;
final long threadCount;
PerformanceSnapshot(long timestamp, long usedMemory, long maxMemory, long threadCount) {
this.timestamp = timestamp;
this.usedMemory = usedMemory;
this.maxMemory = maxMemory;
this.threadCount = threadCount;
}
}
}
练习2:性能基准测试
// PerformanceBenchmark.java
import java.util.concurrent.*;
import java.util.*;
public class PerformanceBenchmark {
public static void main(String[] args) {
System.out.println("=== 性能基准测试 ===");
// 运行各种基准测试
runStringBenchmark();
runCollectionBenchmark();
runConcurrencyBenchmark();
runIOBenchmark();
}
private static void runStringBenchmark() {
System.out.println("\n--- 字符串操作基准测试 ---");
int iterations = 10000;
// String concatenation
long start = System.nanoTime();
String result1 = "";
for (int i = 0; i < iterations; i++) {
result1 += "test" + i;
}
long stringTime = System.nanoTime() - start;
// StringBuilder
start = System.nanoTime();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append("test").append(i);
}
String result2 = sb.toString();
long sbTime = System.nanoTime() - start;
System.out.printf("String拼接: %d ms\n", stringTime / 1_000_000);
System.out.printf("StringBuilder: %d ms\n", sbTime / 1_000_000);
System.out.printf("StringBuilder性能优势: %.2fx\n", (double) stringTime / sbTime);
}
private static void runCollectionBenchmark() {
System.out.println("\n--- 集合操作基准测试 ---");
int size = 100000;
// ArrayList vs LinkedList 插入性能
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
// ArrayList插入
long start = System.nanoTime();
for (int i = 0; i < size; i++) {
arrayList.add(i);
}
long arrayListTime = System.nanoTime() - start;
// LinkedList插入
start = System.nanoTime();
for (int i = 0; i < size; i++) {
linkedList.add(i);
}
long linkedListTime = System.nanoTime() - start;
System.out.printf("ArrayList插入: %d ms\n", arrayListTime / 1_000_000);
System.out.printf("LinkedList插入: %d ms\n", linkedListTime / 1_000_000);
// HashMap vs TreeMap 查找性能
Map<Integer, String> hashMap = new HashMap<>();
Map<Integer, String> treeMap = new TreeMap<>();
// 填充数据
for (int i = 0; i < size; i++) {
hashMap.put(i, "value" + i);
treeMap.put(i, "value" + i);
}
Random random = new Random();
// HashMap查找
start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
hashMap.get(random.nextInt(size));
}
long hashMapTime = System.nanoTime() - start;
// TreeMap查找
start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
treeMap.get(random.nextInt(size));
}
long treeMapTime = System.nanoTime() - start;
System.out.printf("HashMap查找: %d ms\n", hashMapTime / 1_000_000);
System.out.printf("TreeMap查找: %d ms\n", treeMapTime / 1_000_000);
}
private static void runConcurrencyBenchmark() {
System.out.println("\n--- 并发基准测试 ---");
int threadCount = Runtime.getRuntime().availableProcessors();
int tasksPerThread = 10000;
// 测试不同的ExecutorService实现
testExecutorService("FixedThreadPool",
Executors.newFixedThreadPool(threadCount), threadCount, tasksPerThread);
testExecutorService("CachedThreadPool",
Executors.newCachedThreadPool(), threadCount, tasksPerThread);
testExecutorService("WorkStealingPool",
Executors.newWorkStealingPool(), threadCount, tasksPerThread);
}
private static void testExecutorService(String name, ExecutorService executor,
int threadCount, int tasksPerThread) {
long start = System.nanoTime();
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
executor.submit(() -> {
for (int j = 0; j < tasksPerThread; j++) {
// 模拟CPU密集型任务
Math.sqrt(j * 1000);
}
latch.countDown();
});
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long time = System.nanoTime() - start;
System.out.printf("%s: %d ms\n", name, time / 1_000_000);
executor.shutdown();
}
private static void runIOBenchmark() {
System.out.println("\n--- I/O基准测试 ---");
// 这里可以添加文件I/O、网络I/O等基准测试
// 由于篇幅限制,这里只是示例框架
System.out.println("I/O基准测试需要根据具体环境配置");
}
}
练习3:性能回归测试
// PerformanceRegressionTest.java
import java.util.concurrent.*;
import java.util.*;
import java.lang.management.*;
public class PerformanceRegressionTest {
private static final int WARMUP_ITERATIONS = 1000;
private static final int TEST_ITERATIONS = 10000;
public static void main(String[] args) {
System.out.println("=== 性能回归测试 ===");
// 运行性能回归测试
runPerformanceTests();
}
private static void runPerformanceTests() {
System.out.println("\n--- 性能基线测试 ---");
// 测试各种操作的性能基线
testStringOperations();
testCollectionOperations();
testMemoryOperations();
testConcurrentOperations();
}
private static void testStringOperations() {
System.out.println("\n字符串操作性能测试:");
// 预热
for (int i = 0; i < WARMUP_ITERATIONS; i++) {
performStringOperation();
}
// 测试
long start = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
performStringOperation();
}
long duration = System.nanoTime() - start;
double avgTime = (double) duration / TEST_ITERATIONS / 1_000_000; // ms
System.out.printf("平均执行时间: %.3f ms\n", avgTime);
// 性能阈值检查
double threshold = 0.1; // 0.1ms
if (avgTime > threshold) {
System.out.printf("⚠️ 性能警告: 超过阈值 %.3f ms\n", threshold);
} else {
System.out.println("✅ 性能正常");
}
}
private static String performStringOperation() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append("test").append(i);
}
return sb.toString();
}
private static void testCollectionOperations() {
System.out.println("\n集合操作性能测试:");
List<Integer> list = new ArrayList<>();
// 预热
for (int i = 0; i < WARMUP_ITERATIONS; i++) {
performCollectionOperation(list);
}
// 测试
long start = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
performCollectionOperation(list);
}
long duration = System.nanoTime() - start;
double avgTime = (double) duration / TEST_ITERATIONS / 1_000; // μs
System.out.printf("平均执行时间: %.3f μs\n", avgTime);
// 性能阈值检查
double threshold = 10; // 10μs
if (avgTime > threshold) {
System.out.printf("⚠️ 性能警告: 超过阈值 %.3f μs\n", threshold);
} else {
System.out.println("✅ 性能正常");
}
}
private static void performCollectionOperation(List<Integer> list) {
list.add(1);
if (list.size() > 1000) {
list.clear();
}
}
private static void testMemoryOperations() {
System.out.println("\n内存操作性能测试:");
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
long initialMemory = memoryBean.getHeapMemoryUsage().getUsed();
// 预热
for (int i = 0; i < WARMUP_ITERATIONS; i++) {
performMemoryOperation();
}
// 强制GC
System.gc();
Thread.yield();
long beforeMemory = memoryBean.getHeapMemoryUsage().getUsed();
// 测试
long start = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
performMemoryOperation();
}
long duration = System.nanoTime() - start;
long afterMemory = memoryBean.getHeapMemoryUsage().getUsed();
long memoryUsed = afterMemory - beforeMemory;
double avgTime = (double) duration / TEST_ITERATIONS / 1_000; // μs
double avgMemory = (double) memoryUsed / TEST_ITERATIONS; // bytes
System.out.printf("平均执行时间: %.3f μs\n", avgTime);
System.out.printf("平均内存使用: %.0f bytes\n", avgMemory);
// 性能阈值检查
if (avgMemory > 1000) { // 1KB
System.out.printf("⚠️ 内存使用警告: 超过阈值 1000 bytes\n");
} else {
System.out.println("✅ 内存使用正常");
}
}
private static Object performMemoryOperation() {
return new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
}
private static void testConcurrentOperations() {
System.out.println("\n并发操作性能测试:");
int threadCount = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
// 预热
performConcurrentTest(executor, WARMUP_ITERATIONS / threadCount);
// 测试
long start = System.nanoTime();
performConcurrentTest(executor, TEST_ITERATIONS / threadCount);
long duration = System.nanoTime() - start;
double avgTime = (double) duration / TEST_ITERATIONS / 1_000; // μs
System.out.printf("平均执行时间: %.3f μs\n", avgTime);
// 性能阈值检查
double threshold = 50; // 50μs
if (avgTime > threshold) {
System.out.printf("⚠️ 性能警告: 超过阈值 %.3f μs\n", threshold);
} else {
System.out.println("✅ 性能正常");
}
executor.shutdown();
}
private static void performConcurrentTest(ExecutorService executor, int tasksPerThread) {
int threadCount = Runtime.getRuntime().availableProcessors();
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
executor.submit(() -> {
for (int j = 0; j < tasksPerThread; j++) {
Math.sqrt(j);
}
latch.countDown();
});
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
本章总结
关键要点
应用程序性能分析基础
- 性能指标:响应时间、吞吐量、资源利用率
- 性能监控的重要性和方法
- 性能分析的系统性方法
性能瓶颈识别
- CPU瓶颈:高CPU使用率、热点方法、算法效率
- 内存瓶颈:内存泄漏、频繁GC、对象创建过多
- I/O瓶颈:磁盘I/O、网络I/O、数据库连接
- 数据库连接池监控和优化
性能优化策略
- 算法优化:选择合适的数据结构和算法
- 缓存策略:减少重复计算和数据访问
- 并发优化:合理使用多线程和并发工具
- 锁优化:减少锁竞争,使用合适的锁类型
实践练习
- 综合性能分析:模拟真实应用场景
- 性能基准测试:建立性能基线
- 性能回归测试:确保性能不退化
最佳实践
监控策略
- 建立完整的性能监控体系
- 设置合理的性能阈值和告警
- 定期进行性能分析和优化
优化原则
- 先测量,后优化
- 关注关键路径和热点代码
- 平衡性能和代码可维护性
性能测试
- 建立性能基线和回归测试
- 模拟真实的负载场景
- 持续监控生产环境性能
故障诊断
- 使用VisualVM进行实时性能分析
- 结合日志和监控数据定位问题
- 建立性能问题的快速响应机制
下一章预告
下一章我们将学习VisualVM插件开发与扩展,包括: - VisualVM插件架构 - 自定义插件开发 - 插件部署和分发 - 高级扩展功能
通过插件开发,您可以扩展VisualVM的功能,满足特定的监控和分析需求。
性能瓶颈识别
常见性能瓶颈类型
1. CPU瓶颈
特征: - CPU使用率持续高于80% - 线程大量处于RUNNABLE状态 - 响应时间随并发数线性增长
识别方法:
// CPUBottleneckDetector.java
import java.lang.management.*;
import java.util.concurrent.*;
public class CPUBottleneckDetector {
private static final double CPU_THRESHOLD = 80.0;
private static final int SAMPLE_INTERVAL = 1000; // 1秒
public static void main(String[] args) {
System.out.println("=== CPU瓶颈检测 ===");
// 创建CPU密集型任务
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
// 启动监控
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
checkCPUUsage();
}, 0, SAMPLE_INTERVAL, TimeUnit.MILLISECONDS);
// 提交CPU密集型任务
for (int i = 0; i < 20; i++) {
executor.submit(() -> {
performCPUIntensiveTask();
});
}
// 运行2分钟
try {
Thread.sleep(120000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
executor.shutdown();
monitor.shutdown();
}
private static void checkCPUUsage() {
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
com.sun.management.OperatingSystemMXBean sunOsBean =
(com.sun.management.OperatingSystemMXBean) osBean;
double processCpuLoad = sunOsBean.getProcessCpuLoad() * 100;
double systemCpuLoad = sunOsBean.getSystemCpuLoad() * 100;
System.out.printf("[%s] 进程CPU: %.2f%%, 系统CPU: %.2f%%\n",
new java.util.Date(), processCpuLoad, systemCpuLoad);
if (processCpuLoad > CPU_THRESHOLD) {
System.out.println("警告:检测到CPU瓶颈!");
analyzeThreads();
}
}
}
private static void analyzeThreads() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
// 获取所有线程信息
long[] threadIds = threadBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds);
System.out.println("\n=== 线程状态分析 ===");
Map<Thread.State, Integer> stateCount = new HashMap<>();
for (ThreadInfo info : threadInfos) {
if (info != null) {
Thread.State state = info.getThreadState();
stateCount.put(state, stateCount.getOrDefault(state, 0) + 1);
}
}
stateCount.forEach((state, count) -> {
System.out.printf("%s: %d\n", state, count);
});
}
private static void performCPUIntensiveTask() {
// 模拟CPU密集型计算
long result = 0;
for (int i = 0; i < 10000000; i++) {
result += Math.sqrt(i) * Math.sin(i);
}
// 防止编译器优化
if (result == Long.MAX_VALUE) {
System.out.println("Unlikely result");
}
}
}
2. 内存瓶颈
特征: - 频繁的GC活动 - 内存使用率持续高于85% - OutOfMemoryError异常
识别方法:
// MemoryBottleneckDetector.java
import java.lang.management.*;
import java.util.*;
import java.util.concurrent.*;
public class MemoryBottleneckDetector {
private static final double MEMORY_THRESHOLD = 85.0;
private static final List<Object> memoryConsumer = Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) {
System.out.println("=== 内存瓶颈检测 ===");
// 启动内存监控
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
checkMemoryUsage();
}, 0, 2, TimeUnit.SECONDS);
// 逐渐增加内存使用
Thread memoryConsumerThread = new Thread(() -> {
try {
consumeMemoryGradually();
} catch (OutOfMemoryError e) {
System.out.println("内存耗尽:" + e.getMessage());
}
});
memoryConsumerThread.start();
// 运行直到内存耗尽或5分钟
try {
memoryConsumerThread.join(300000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
monitor.shutdown();
}
private static void checkMemoryUsage() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
double memoryUtilization = (double) heapUsage.getUsed() / heapUsage.getMax() * 100;
System.out.printf("[%s] 内存使用: %.2f%% (%s / %s)\n",
new Date(),
memoryUtilization,
formatBytes(heapUsage.getUsed()),
formatBytes(heapUsage.getMax()));
if (memoryUtilization > MEMORY_THRESHOLD) {
System.out.println("警告:检测到内存瓶颈!");
analyzeGC();
}
}
private static void analyzeGC() {
List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
System.out.println("\n=== GC分析 ===");
for (GarbageCollectorMXBean gcBean : gcBeans) {
System.out.printf("%s: 收集次数=%d, 总时间=%dms\n",
gcBean.getName(),
gcBean.getCollectionCount(),
gcBean.getCollectionTime());
}
}
private static void consumeMemoryGradually() {
Random random = new Random();
int iteration = 0;
while (true) {
try {
// 创建不同大小的对象
int size = random.nextInt(10000) + 1000;
byte[] data = new byte[size];
// 填充随机数据
random.nextBytes(data);
memoryConsumer.add(data);
iteration++;
if (iteration % 1000 == 0) {
System.out.println("已创建 " + iteration + " 个对象");
// 偶尔释放一些内存
if (iteration % 5000 == 0 && memoryConsumer.size() > 1000) {
for (int i = 0; i < 500; i++) {
memoryConsumer.remove(0);
}
System.out.println("释放了500个对象");
}
}
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
private static String formatBytes(long bytes) {
if (bytes < 1024) return bytes + " B";
if (bytes < 1024 * 1024) return String.format("%.2f KB", bytes / 1024.0);
if (bytes < 1024 * 1024 * 1024) return String.format("%.2f MB", bytes / (1024.0 * 1024));
return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
}
}