本章概述

应用程序性能分析是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());
        }
    }
}

数据库连接池监控

连接池性能指标

关键指标

  1. 连接池大小

    • 最大连接数
    • 当前活跃连接数
    • 空闲连接数
  2. 连接获取性能

    • 平均获取时间
    • 最大等待时间
    • 获取超时次数
  3. 连接使用情况

    • 连接使用率
    • 连接泄漏检测
    • 长时间占用连接

数据库连接池监控示例

// 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();
        }
    }
}

本章总结

关键要点

  1. 应用程序性能分析基础

    • 性能指标:响应时间、吞吐量、资源利用率
    • 性能监控的重要性和方法
    • 性能分析的系统性方法
  2. 性能瓶颈识别

    • CPU瓶颈:高CPU使用率、热点方法、算法效率
    • 内存瓶颈:内存泄漏、频繁GC、对象创建过多
    • I/O瓶颈:磁盘I/O、网络I/O、数据库连接
    • 数据库连接池监控和优化
  3. 性能优化策略

    • 算法优化:选择合适的数据结构和算法
    • 缓存策略:减少重复计算和数据访问
    • 并发优化:合理使用多线程和并发工具
    • 锁优化:减少锁竞争,使用合适的锁类型
  4. 实践练习

    • 综合性能分析:模拟真实应用场景
    • 性能基准测试:建立性能基线
    • 性能回归测试:确保性能不退化

最佳实践

  1. 监控策略

    • 建立完整的性能监控体系
    • 设置合理的性能阈值和告警
    • 定期进行性能分析和优化
  2. 优化原则

    • 先测量,后优化
    • 关注关键路径和热点代码
    • 平衡性能和代码可维护性
  3. 性能测试

    • 建立性能基线和回归测试
    • 模拟真实的负载场景
    • 持续监控生产环境性能
  4. 故障诊断

    • 使用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));
    }
}