【JVM】性能调优+监控利器

1、JVM监控系统

JMH 测试报告

Benchmark注解:标识在某个具体方法上,表示这个方法将是一个被测试的最小方法,在JMH中成为一个OPS
BenmarkMode:测试类型,JMH提供了几种不同的Mode
Throughput:整体吞吐量
AverageTime:调用的平均时间,每次OPS执行的时间
SampleTime:取样,给出不同比例的ops时间,例如99%的ops时间,99.99%的ops时间
fork:fork的次数,如果设置为2,JMH会fork出两个进程来测试
Threads:很容易理解,这个参数表示这个方法同时被多少个线程执行

BenchMark介绍

BenchMark 又叫做基准测试,主要用来测试一些方法的性能,可以根据不同的参数以不同的单位进行计算(例如可以使用吞吐量为单位,也可以使用平均时间作为单位,在 BenchmarkMode 里面进行调整)。

开始前的步骤

项目使用的是 Maven,因此只要对 pom.xml 添加依赖即可。

<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.19</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.19</version>
    <scope>provided</scope>
</dependency>
代码
package com.psd.benchmark;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Author: Shadowdsp
 * Date: 18/07/22
 */

@BenchmarkMode(Mode.Throughput) // 吞吐量
@OutputTimeUnit(TimeUnit.MILLISECONDS) // 结果所使用的时间单位
@State(Scope.Thread) // 每个测试线程分配一个实例
@Fork(2) // Fork进行的数目
@Warmup(iterations = 4) // 先预热4轮
@Measurement(iterations = 10) // 进行10轮测试
public class BenchMark {

    @Param({"10", "40", "70", "100"}) // 定义四个参数,之后会分别对这四个参数进行测试
    private int n;

    private List<Integer> array;
    private List<Integer> list;

    @Setup(Level.Trial) // 初始化方法,在全部Benchmark运行之前进行
    public void init() {
        array = new ArrayList<>(0);
        list = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            array.add(i);
            list.add(i);
        }
    }

    @Benchmark
    public void arrayTraverse() {
        for (int i = 0; i < n; i++) {
            array.get(i);
        }
    }

    @Benchmark
    public void listTraverse() {
        for (int i = 0; i < n; i++) {
            list.get(i);
        }
    }

    @TearDown(Level.Trial) // 结束方法,在全部Benchmark运行之后进行
    public void arrayRemove() {
        for (int i = 0; i < n; i++) {
            array.remove(0);
            list.remove(0);
        }
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder().include(BenchMark.class.getSimpleName()).build();
        new Runner(options).run();
    }
}

报告
E:\Java\JDK8\bin\java "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin" -Dfile.encoding=UTF-8 -classpath E:\Java\JDK8\jre\lib\charsets.jar;E:\Java\JDK8\jre\lib\deploy.jar;E:\Java\JDK8\jre\lib\ext\access-bridge-64.jar;E:\Java\JDK8\jre\lib\ext\cldrdata.jar;E:\Java\JDK8\jre\lib\ext\dnsns.jar;E:\Java\JDK8\jre\lib\ext\jaccess.jar;E:\Java\JDK8\jre\lib\ext\jfxrt.jar;E:\Java\JDK8\jre\lib\ext\localedata.jar;E:\Java\JDK8\jre\lib\ext\nashorn.jar;E:\Java\JDK8\jre\lib\ext\sunec.jar;E:\Java\JDK8\jre\lib\ext\sunjce_provider.jar;E:\Java\JDK8\jre\lib\ext\sunmscapi.jar;E:\Java\JDK8\jre\lib\ext\sunpkcs11.jar;E:\Java\JDK8\jre\lib\ext\zipfs.jar;E:\Java\JDK8\jre\lib\javaws.jar;E:\Java\JDK8\jre\lib\jce.jar;E:\Java\JDK8\jre\lib\jfr.jar;E:\Java\JDK8\jre\lib\jfxswt.jar;E:\Java\JDK8\jre\lib\jsse.jar;E:\Java\JDK8\jre\lib\management-agent.jar;E:\Java\JDK8\jre\lib\plugin.jar;E:\Java\JDK8\jre\lib\resources.jar;E:\Java\JDK8\jre\lib\rt.jar;E:\Java\IdeaProjects\Warehouse\target\classes;E:\Java\maven\LocalWarehouse\junit\junit\4.11\junit-4.11.jar;E:\Java\maven\LocalWarehouse\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-core\4.0.2.RELEASE\spring-core-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-web\4.0.2.RELEASE\spring-web-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-beans\4.0.2.RELEASE\spring-beans-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-context\4.0.2.RELEASE\spring-context-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-oxm\4.0.2.RELEASE\spring-oxm-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-tx\4.0.2.RELEASE\spring-tx-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-jdbc\4.0.2.RELEASE\spring-jdbc-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-webmvc\4.0.2.RELEASE\spring-webmvc-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-expression\4.0.2.RELEASE\spring-expression-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-aop\4.0.2.RELEASE\spring-aop-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-context-support\4.0.2.RELEASE\spring-context-support-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-test\4.0.2.RELEASE\spring-test-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\mybatis\mybatis\3.2.6\mybatis-3.2.6.jar;E:\Java\maven\LocalWarehouse\org\mybatis\mybatis-spring\1.2.2\mybatis-spring-1.2.2.jar;E:\Java\maven\LocalWarehouse\javax\javaee-api\7.0\javaee-api-7.0.jar;E:\Java\maven\LocalWarehouse\com\sun\mail\javax.mail\1.5.0\javax.mail-1.5.0.jar;E:\Java\maven\LocalWarehouse\javax\activation\activation\1.1\activation-1.1.jar;E:\Java\maven\LocalWarehouse\mysql\mysql-connector-java\5.1.30\mysql-connector-java-5.1.30.jar;E:\Java\maven\LocalWarehouse\commons-dbcp\commons-dbcp\1.2.2\commons-dbcp-1.2.2.jar;E:\Java\maven\LocalWarehouse\commons-pool\commons-pool\1.3\commons-pool-1.3.jar;E:\Java\maven\LocalWarehouse\jstl\jstl\1.2\jstl-1.2.jar;E:\Java\maven\LocalWarehouse\log4j\log4j\1.2.17\log4j-1.2.17.jar;E:\Java\maven\LocalWarehouse\com\alibaba\fastjson\1.1.41\fastjson-1.1.41.jar;E:\Java\maven\LocalWarehouse\org\slf4j\slf4j-api\1.7.7\slf4j-api-1.7.7.jar;E:\Java\maven\LocalWarehouse\org\slf4j\slf4j-log4j12\1.7.7\slf4j-log4j12-1.7.7.jar;E:\Java\maven\LocalWarehouse\org\codehaus\jackson\jackson-mapper-asl\1.9.13\jackson-mapper-asl-1.9.13.jar;E:\Java\maven\LocalWarehouse\org\codehaus\jackson\jackson-core-asl\1.9.13\jackson-core-asl-1.9.13.jar;E:\Java\maven\LocalWarehouse\commons-fileupload\commons-fileupload\1.3.1\commons-fileupload-1.3.1.jar;E:\Java\maven\LocalWarehouse\commons-io\commons-io\2.4\commons-io-2.4.jar;E:\Java\maven\LocalWarehouse\commons-codec\commons-codec\1.9\commons-codec-1.9.jar;E:\Java\maven\LocalWarehouse\org\junit\jupiter\junit-jupiter-api\5.3.0-M1\junit-jupiter-api-5.3.0-M1.jar;E:\Java\maven\LocalWarehouse\org\apiguardian\apiguardian-api\1.0.0\apiguardian-api-1.0.0.jar;E:\Java\maven\LocalWarehouse\org\opentest4j\opentest4j\1.1.0\opentest4j-1.1.0.jar;E:\Java\maven\LocalWarehouse\org\junit\platform\junit-platform-commons\1.3.0-M1\junit-platform-commons-1.3.0-M1.jar;E:\Java\maven\LocalWarehouse\org\openjdk\jmh\jmh-core\1.19\jmh-core-1.19.jar;E:\Java\maven\LocalWarehouse\net\sf\jopt-simple\jopt-simple\4.6\jopt-simple-4.6.jar;E:\Java\maven\LocalWarehouse\org\apache\commons\commons-math3\3.2\commons-math3-3.2.jar com.psd.benchmark.BenchMark
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 10)

# Run progress: 0.00% complete, ETA 00:03:44
# Fork: 1 of 2
# Warmup Iteration   1: 189538.902 ops/ms
# Warmup Iteration   2: 287165.702 ops/ms
# Warmup Iteration   3: 282388.510 ops/ms
# Warmup Iteration   4: 277296.753 ops/ms
Iteration   1: 288687.174 ops/ms
Iteration   2: 277046.541 ops/ms
Iteration   3: 288680.458 ops/ms
Iteration   4: 279775.705 ops/ms
Iteration   5: 289098.257 ops/ms
Iteration   6: 287462.515 ops/ms
Iteration   7: 255330.788 ops/ms
Iteration   8: 282631.894 ops/ms
Iteration   9: 277038.372 ops/ms
Iteration  10: 277690.784 ops/ms

# Run progress: 6.25% complete, ETA 00:03:42
# Fork: 2 of 2
# Warmup Iteration   1: 286568.900 ops/ms
# Warmup Iteration   2: 288014.591 ops/ms
# Warmup Iteration   3: 281790.934 ops/ms
# Warmup Iteration   4: 279647.288 ops/ms
Iteration   1: 280839.175 ops/ms
Iteration   2: 289208.462 ops/ms
Iteration   3: 282724.949 ops/ms
Iteration   4: 289762.265 ops/ms
Iteration   5: 284551.820 ops/ms
Iteration   6: 283700.745 ops/ms
Iteration   7: 261083.800 ops/ms
Iteration   8: 283651.988 ops/ms
Iteration   9: 284418.725 ops/ms
Iteration  10: 282418.733 ops/ms


Result "com.psd.benchmark.BenchMark.arrayTraverse":
  281290.158 ±(99.9%) 7750.303 ops/ms [Average]
  (min, avg, max) = (255330.788, 281290.158, 289762.265), stdev = 8925.261
  CI (99.9%): [273539.854, 289040.461] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 40)

# Run progress: 12.50% complete, ETA 00:03:27
# Fork: 1 of 2
# Warmup Iteration   1: 277185.994 ops/ms
# Warmup Iteration   2: 277343.966 ops/ms
# Warmup Iteration   3: 289105.366 ops/ms
# Warmup Iteration   4: 281931.930 ops/ms
Iteration   1: 279532.380 ops/ms
Iteration   2: 278419.091 ops/ms
Iteration   3: 281165.591 ops/ms
Iteration   4: 288999.045 ops/ms
Iteration   5: 277378.462 ops/ms
Iteration   6: 275360.726 ops/ms
Iteration   7: 282858.013 ops/ms
Iteration   8: 283601.524 ops/ms
Iteration   9: 279043.295 ops/ms
Iteration  10: 279976.466 ops/ms

# Run progress: 18.75% complete, ETA 00:03:12
# Fork: 2 of 2
# Warmup Iteration   1: 284211.718 ops/ms
# Warmup Iteration   2: 287327.346 ops/ms
# Warmup Iteration   3: 268548.012 ops/ms
# Warmup Iteration   4: 289429.098 ops/ms
Iteration   1: 283348.446 ops/ms
Iteration   2: 262579.782 ops/ms
Iteration   3: 283534.897 ops/ms
Iteration   4: 266160.111 ops/ms
Iteration   5: 289614.776 ops/ms
Iteration   6: 274270.699 ops/ms
Iteration   7: 267829.186 ops/ms
Iteration   8: 279612.742 ops/ms
Iteration   9: 283569.117 ops/ms
Iteration  10: 288172.441 ops/ms


Result "com.psd.benchmark.BenchMark.arrayTraverse":
  279251.339 ±(99.9%) 6287.385 ops/ms [Average]
  (min, avg, max) = (262579.782, 279251.339, 289614.776), stdev = 7240.561
  CI (99.9%): [272963.955, 285538.724] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 70)

# Run progress: 25.00% complete, ETA 00:02:57
# Fork: 1 of 2
# Warmup Iteration   1: 276172.253 ops/ms
# Warmup Iteration   2: 284624.007 ops/ms
# Warmup Iteration   3: 288356.101 ops/ms
# Warmup Iteration   4: 284278.064 ops/ms
Iteration   1: 287831.035 ops/ms
Iteration   2: 286518.388 ops/ms
Iteration   3: 287016.992 ops/ms
Iteration   4: 282654.336 ops/ms
Iteration   5: 287899.254 ops/ms
Iteration   6: 287299.594 ops/ms
Iteration   7: 284624.713 ops/ms
Iteration   8: 287280.777 ops/ms
Iteration   9: 268079.560 ops/ms
Iteration  10: 266327.469 ops/ms

# Run progress: 31.25% complete, ETA 00:02:42
# Fork: 2 of 2
# Warmup Iteration   1: 282831.765 ops/ms
# Warmup Iteration   2: 271396.073 ops/ms
# Warmup Iteration   3: 280114.449 ops/ms
# Warmup Iteration   4: 272365.705 ops/ms
Iteration   1: 287276.286 ops/ms
Iteration   2: 258473.510 ops/ms
Iteration   3: 287822.759 ops/ms
Iteration   4: 281849.137 ops/ms
Iteration   5: 281739.415 ops/ms
Iteration   6: 271390.808 ops/ms
Iteration   7: 279252.964 ops/ms
Iteration   8: 280445.016 ops/ms
Iteration   9: 287019.516 ops/ms
Iteration  10: 283679.804 ops/ms


Result "com.psd.benchmark.BenchMark.arrayTraverse":
  281224.067 ±(99.9%) 7376.077 ops/ms [Average]
  (min, avg, max) = (258473.510, 281224.067, 287899.254), stdev = 8494.301
  CI (99.9%): [273847.990, 288600.143] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 100)

# Run progress: 37.50% complete, ETA 00:02:27
# Fork: 1 of 2
# Warmup Iteration   1: 277758.992 ops/ms
# Warmup Iteration   2: 283193.840 ops/ms
# Warmup Iteration   3: 280441.005 ops/ms
# Warmup Iteration   4: 284059.500 ops/ms
Iteration   1: 288156.207 ops/ms
Iteration   2: 277402.478 ops/ms
Iteration   3: 274760.100 ops/ms
Iteration   4: 280052.747 ops/ms
Iteration   5: 261148.816 ops/ms
Iteration   6: 281093.340 ops/ms
Iteration   7: 278472.671 ops/ms
Iteration   8: 257387.342 ops/ms
Iteration   9: 258938.869 ops/ms
Iteration  10: 281241.529 ops/ms

# Run progress: 43.75% complete, ETA 00:02:12
# Fork: 2 of 2
# Warmup Iteration   1: 261991.159 ops/ms
# Warmup Iteration   2: 272490.286 ops/ms
# Warmup Iteration   3: 283308.053 ops/ms
# Warmup Iteration   4: 262856.702 ops/ms
Iteration   1: 283588.427 ops/ms
Iteration   2: 289665.875 ops/ms
Iteration   3: 242227.467 ops/ms
Iteration   4: 235915.418 ops/ms
Iteration   5: 282235.546 ops/ms
Iteration   6: 262060.151 ops/ms
Iteration   7: 249476.606 ops/ms
Iteration   8: 289452.132 ops/ms
Iteration   9: 249939.347 ops/ms
Iteration  10: 268307.387 ops/ms


Result "com.psd.benchmark.BenchMark.arrayTraverse":
  269576.123 ±(99.9%) 14237.446 ops/ms [Average]
  (min, avg, max) = (235915.418, 269576.123, 289665.875), stdev = 16395.864
  CI (99.9%): [255338.677, 283813.569] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 10)

# Run progress: 50.00% complete, ETA 00:01:58
# Fork: 1 of 2
# Warmup Iteration   1: 44140.774 ops/ms
# Warmup Iteration   2: 32207.674 ops/ms
# Warmup Iteration   3: 36260.862 ops/ms
# Warmup Iteration   4: 32678.534 ops/ms
Iteration   1: 35846.579 ops/ms
Iteration   2: 34837.967 ops/ms
Iteration   3: 36439.906 ops/ms
Iteration   4: 36522.320 ops/ms
Iteration   5: 35112.493 ops/ms
Iteration   6: 35687.937 ops/ms
Iteration   7: 35727.530 ops/ms
Iteration   8: 31676.889 ops/ms
Iteration   9: 36219.853 ops/ms
Iteration  10: 35857.764 ops/ms

# Run progress: 56.25% complete, ETA 00:01:43
# Fork: 2 of 2
# Warmup Iteration   1: 34479.354 ops/ms
# Warmup Iteration   2: 34805.614 ops/ms
# Warmup Iteration   3: 37839.045 ops/ms
# Warmup Iteration   4: 38778.482 ops/ms
Iteration   1: 37184.558 ops/ms
Iteration   2: 35340.593 ops/ms
Iteration   3: 37976.310 ops/ms
Iteration   4: 39359.895 ops/ms
Iteration   5: 37142.984 ops/ms
Iteration   6: 38973.376 ops/ms
Iteration   7: 38609.058 ops/ms
Iteration   8: 39516.419 ops/ms
Iteration   9: 33589.403 ops/ms
Iteration  10: 37153.584 ops/ms


Result "com.psd.benchmark.BenchMark.listTraverse":
  36438.771 ±(99.9%) 1680.987 ops/ms [Average]
  (min, avg, max) = (31676.889, 36438.771, 39516.419), stdev = 1935.828
  CI (99.9%): [34757.784, 38119.758] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 40)

# Run progress: 62.50% complete, ETA 00:01:28
# Fork: 1 of 2
# Warmup Iteration   1: 6381.367 ops/ms
# Warmup Iteration   2: 6267.589 ops/ms
# Warmup Iteration   3: 6070.546 ops/ms
# Warmup Iteration   4: 6311.543 ops/ms
Iteration   1: 6294.215 ops/ms
Iteration   2: 6221.013 ops/ms
Iteration   3: 6196.371 ops/ms
Iteration   4: 5960.573 ops/ms
Iteration   5: 5748.201 ops/ms
Iteration   6: 5494.775 ops/ms
Iteration   7: 5594.778 ops/ms
Iteration   8: 6345.496 ops/ms
Iteration   9: 6141.148 ops/ms
Iteration  10: 6017.750 ops/ms

# Run progress: 68.75% complete, ETA 00:01:13
# Fork: 2 of 2
# Warmup Iteration   1: 6369.814 ops/ms
# Warmup Iteration   2: 6258.675 ops/ms
# Warmup Iteration   3: 5802.971 ops/ms
# Warmup Iteration   4: 6028.703 ops/ms
Iteration   1: 6192.258 ops/ms
Iteration   2: 5966.093 ops/ms
Iteration   3: 5958.597 ops/ms
Iteration   4: 6171.185 ops/ms
Iteration   5: 5617.002 ops/ms
Iteration   6: 5387.913 ops/ms
Iteration   7: 5299.407 ops/ms
Iteration   8: 5939.628 ops/ms
Iteration   9: 5640.087 ops/ms
Iteration  10: 6057.939 ops/ms


Result "com.psd.benchmark.BenchMark.listTraverse":
  5912.221 ±(99.9%) 271.819 ops/ms [Average]
  (min, avg, max) = (5299.407, 5912.221, 6345.496), stdev = 313.027
  CI (99.9%): [5640.403, 6184.040] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 70)

# Run progress: 75.00% complete, ETA 00:00:59
# Fork: 1 of 2
# Warmup Iteration   1: 1904.675 ops/ms
# Warmup Iteration   2: 1829.190 ops/ms
# Warmup Iteration   3: 1799.166 ops/ms
# Warmup Iteration   4: 1823.508 ops/ms
Iteration   1: 1483.423 ops/ms
Iteration   2: 1733.061 ops/ms
Iteration   3: 1752.878 ops/ms
Iteration   4: 1877.448 ops/ms
Iteration   5: 1748.907 ops/ms
Iteration   6: 1836.011 ops/ms
Iteration   7: 1830.008 ops/ms
Iteration   8: 1733.991 ops/ms
Iteration   9: 1821.246 ops/ms
Iteration  10: 1827.086 ops/ms

# Run progress: 81.25% complete, ETA 00:00:44
# Fork: 2 of 2
# Warmup Iteration   1: 1858.409 ops/ms
# Warmup Iteration   2: 1816.699 ops/ms
# Warmup Iteration   3: 1810.298 ops/ms
# Warmup Iteration   4: 1704.668 ops/ms
Iteration   1: 1772.384 ops/ms
Iteration   2: 1619.981 ops/ms
Iteration   3: 1754.014 ops/ms
Iteration   4: 1767.706 ops/ms
Iteration   5: 1706.000 ops/ms
Iteration   6: 1646.038 ops/ms
Iteration   7: 1789.584 ops/ms
Iteration   8: 1746.964 ops/ms
Iteration   9: 1785.779 ops/ms
Iteration  10: 1813.610 ops/ms


Result "com.psd.benchmark.BenchMark.listTraverse":
  1752.306 ±(99.9%) 77.143 ops/ms [Average]
  (min, avg, max) = (1483.423, 1752.306, 1877.448), stdev = 88.838
  CI (99.9%): [1675.163, 1829.449] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 100)

# Run progress: 87.50% complete, ETA 00:00:29
# Fork: 1 of 2
# Warmup Iteration   1: 784.637 ops/ms
# Warmup Iteration   2: 803.586 ops/ms
# Warmup Iteration   3: 780.992 ops/ms
# Warmup Iteration   4: 812.284 ops/ms
Iteration   1: 771.280 ops/ms
Iteration   2: 725.038 ops/ms
Iteration   3: 781.465 ops/ms
Iteration   4: 753.939 ops/ms
Iteration   5: 753.920 ops/ms
Iteration   6: 813.238 ops/ms
Iteration   7: 778.423 ops/ms
Iteration   8: 809.902 ops/ms
Iteration   9: 769.837 ops/ms
Iteration  10: 767.709 ops/ms

# Run progress: 93.75% complete, ETA 00:00:14
# Fork: 2 of 2
# Warmup Iteration   1: 703.812 ops/ms
# Warmup Iteration   2: 752.538 ops/ms
# Warmup Iteration   3: 774.776 ops/ms
# Warmup Iteration   4: 813.269 ops/ms
Iteration   1: 796.985 ops/ms
Iteration   2: 687.697 ops/ms
Iteration   3: 808.395 ops/ms
Iteration   4: 736.341 ops/ms
Iteration   5: 761.328 ops/ms
Iteration   6: 746.422 ops/ms
Iteration   7: 767.855 ops/ms
Iteration   8: 814.670 ops/ms
Iteration   9: 772.441 ops/ms
Iteration  10: 731.986 ops/ms


Result "com.psd.benchmark.BenchMark.listTraverse":
  767.444 ±(99.9%) 28.363 ops/ms [Average]
  (min, avg, max) = (687.697, 767.444, 814.670), stdev = 32.662
  CI (99.9%): [739.081, 795.806] (assumes normal distribution)


# Run complete. Total time: 00:03:56
(一般只需要关注这下面的东西)

Benchmark                (n)   Mode  Cnt       Score       Error   Units
BenchMark.arrayTraverse   10  thrpt   20  281290.158 ±  7750.303  ops/ms
BenchMark.arrayTraverse   40  thrpt   20  279251.339 ±  6287.385  ops/ms
BenchMark.arrayTraverse   70  thrpt   20  281224.067 ±  7376.077  ops/ms
BenchMark.arrayTraverse  100  thrpt   20  269576.123 ± 14237.446  ops/ms
BenchMark.listTraverse    10  thrpt   20   36438.771 ±  1680.987  ops/ms
BenchMark.listTraverse    40  thrpt   20    5912.221 ±   271.819  ops/ms
BenchMark.listTraverse    70  thrpt   20    1752.306 ±    77.143  ops/ms
BenchMark.listTraverse   100  thrpt   20     767.444 ±    28.363  ops/ms

Process finished with exit code 0

报告很长,因为这里的n有四种情况,然后有两个 @Benchmark 方法,因此会进行8次测试。

大多数情况只需要关注最下面的结果。

可以结合 Score 和 Unit 这两列,看到方法的效率。这里显然 arrayTraverse 的效率比 listTraverse 的高很多,因为 Unit 单位是 ops/ms,即单位时间内执行的操作数。所以显然在遍历的时候,ArrayList的效率是比LinkedList高的。

注解介绍

注解名

解释

@BenchmarkMode

Mode 表示 JMH 进行 Benchmark 时所使用的模式。通常是测量的维度不同,或是测量的方式不同。目前 JMH 共有四种模式:

  1. Throughput: 整体吞吐量,例如“1秒内可以执行多少次调用”,单位是操作数/时间。
  2. AverageTime: 调用的平均时间,例如“每次调用平均耗时xxx毫秒”,单位是时间/操作数。
  3. SampleTime: 随机取样,最后输出取样结果的分布,例如“99%的调用在xxx毫秒以内,99.99%的调用在xxx毫秒以内”
  4. SingleShotTime: 以上模式都是默认一次 iteration 是 1s,唯有 SingleShotTime 是只运行一次。往往同时把 warmup 次数设为0,用于测试冷启动时的性能。
@OutputTimeUnit

输出的时间单位。

@Iteration

Iteration 是 JMH 进行测试的最小单位。在大部分模式下,一次 iteration 代表的是一秒,JMH 会在这一秒内不断调用需要 Benchmark 的方法,然后根据模式对其采样,计算吞吐量,计算平均执行时间等。

@WarmUp

Warmup 是指在实际进行 Benchmark 前先进行预热的行为。

为什么需要预热?因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译成为机器码从而提高执行速度。为了让 Benchmark 的结果更加接近真实情况就需要进行预热。

@State

类注解,JMH测试类必须使用 @State 注解,它定义了一个类实例的生命周期,可以类比 Spring Bean 的 Scope。由于 JMH 允许多线程同时执行测试,不同的选项含义如下:

  1. Scope.Thread:默认的 State,每个测试线程分配一个实例;
  2. Scope.Benchmark:所有测试线程共享一个实例,用于测试有状态实例在多线程共享下的性能;
  3. Scope.Group:每个线程组共享一个实例;
@Fork

进行 fork 的次数。如果 fork 数是2的话,则 JMH 会 fork 出两个进程来进行测试。

@Meansurement

提供真正的测试阶段参数。指定迭代的次数,每次迭代的运行时间和每次迭代测试调用的数量(通常使用 @BenchmarkMode(Mode.SingleShotTime) 测试一组操作的开销——而不使用循环)

@Setup

方法注解,会在执行 benchmark 之前被执行,正如其名,主要用于初始化。

@TearDown

方法注解,与@Setup 相对的,会在所有 benchmark 执行结束以后执行,主要用于资源的回收等。

@Setup/@TearDown注解使用Level参数来指定何时调用fixture:

| 名称 | 描述 |
| - | :-: | -: |
| Level.Trial | 默认level。全部benchmark运行(一组迭代)之前/之后 |
| Level.Iteration | 一次迭代之前/之后(一组调用) |
| Level.Invocation | 每个方法调用之前/之后(不推荐使用,除非你清楚这样做的目的) |

@Benchmark

方法注解,表示该方法是需要进行 benchmark 的对象。

@Param

成员注解,可以用来指定某项参数的多种情况。特别适合用来测试一个函数在不同的参数输入的情况下的性能。@Param 注解接收一个String数组,在 @Setup 方法执行前转化为为对应的数据类型。多个 @Param 注解的成员之间是乘积关系,譬如有两个用 @Param 注解的字段,第一个有5个值,第二个字段有2个值,那么每个测试方法会跑5*2=10次。

Arthas 性能监控

官网地址:Arthas

我们首先通过jps找到程序的进程号,然后直接通过arthas给到的as.sh对我们运行的程序进行字节码增强,然后启动arthas,命令如下

方法1:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
快速入门——常用命令
1、dashboard

dashboard 展示当前进程信息

$ dashboard
ID   NAME                           GROUP           PRIORITY   STATE     %CPU      DELTA_TIME TIME      INTERRUPTE DAEMON
-1   C2 CompilerThread0             -               -1         -         1.55      0.077      0:8.684   false      true
53   Timer-for-arthas-dashboard-07b system          5          RUNNABLE  0.08      0.004      0:0.004   false      true
22   scheduling-1                   main            5          TIMED_WAI 0.06      0.003      0:0.287   false      false
-1   C1 CompilerThread0             -               -1         -         0.06      0.003      0:2.171   false      true
-1   VM Periodic Task Thread        -               -1         -         0.03      0.001      0:0.092   false      true
49   arthas-NettyHttpTelnetBootstra system          5          RUNNABLE  0.02      0.001      0:0.156   false      true
16   Catalina-utility-1             main            1          TIMED_WAI 0.0       0.000      0:0.029   false      false
-1   G1 Young RemSet Sampling       -               -1         -         0.0       0.000      0:0.019   false      true
17   Catalina-utility-2             main            1          WAITING   0.0       0.000      0:0.025   false      false
34   http-nio-8080-ClientPoller     main            5          RUNNABLE  0.0       0.000      0:0.016   false      true
23   http-nio-8080-BlockPoller      main            5          RUNNABLE  0.0       0.000      0:0.011   false      true
-1   VM Thread                      -               -1         -         0.0       0.000      0:0.032   false      true
-1   Service Thread                 -               -1         -         0.0       0.000      0:0.006   false      true
-1   GC Thread#5                    -               -1         -         0.0       0.000      0:0.043   false      true
Memory                     used     total    max      usage    GC
heap                       36M      70M      4096M    0.90%    gc.g1_young_generation.count   12
g1_eden_space              6M       18M      -1       33.33%                                  86
g1_old_gen                 30M      50M      4096M    0.74%    gc.g1_old_generation.count     0
g1_survivor_space          491K     2048K    -1       24.01%   gc.g1_old_generation.time(ms)  0
nonheap                    66M      69M      -1       96.56%
codeheap_'non-nmethods'    1M       2M       5M       22.39%
metaspace                  46M      47M      -1       98.01%
Runtime
os.name                                                        Mac OS X
os.version                                                     10.15.4
java.version                                                   15
java.home                                                      /Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home
systemload.average                                             10.68
processors                                                     8
uptime                                                         272s

数据说明

  • ID: Java 级别的线程 ID,注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。
  • NAME: 线程名
  • GROUP: 线程组名
  • PRIORITY: 线程优先级, 1~10 之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程的 cpu 使用率。比如采样间隔 1000ms,某个线程的增量 cpu 时间为 100ms,则 cpu 使用率=100/1000=10%
  • DELTA_TIME: 上次采样之后线程运行增量 CPU 时间,数据格式为秒
  • TIME: 线程运行总 CPU 时间,数据格式为分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是 daemon 线程

JVM 内部线程

Java 8 之后支持获取 JVM 内部线程 CPU 时间,这些线程只有名称和 CPU 时间,没有 ID 及状态等信息(显示 ID 为-1)。 通过内部线程可以观测到 JVM 活动,如 GC、JIT 编译等占用 CPU 情况,方便了解 JVM 整体运行状况。

  • 当 JVM 堆(heap)/元数据(metaspace)空间不足或 OOM 时,可以看到 GC 线程的 CPU 占用率明显高于其他的线程。
  • 当执行trace/watch/tt/redefine等命令后,可以看到 JIT 线程活动变得更频繁。因为 JVM 热更新 class 字节码时清除了此 class 相关的 JIT 编译结果,需要重新编译。

JVM 内部线程包括下面几种:

  • JIT 编译线程: 如 C1 CompilerThread0, C2 CompilerThread0
  • GC 线程: 如GC Thread0, G1 Young RemSet Sampling
  • 其它内部线程: 如VM Periodic Task Thread, VM Thread, Service Thread

截图展示

2、jad 来反编译 Main Class
通过 jad 来反编译 Main Class
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@3d4eac69
  +-sun.misc.Launcher$ExtClassLoader@66350f69

Location:
/tmp/math-game.jar

/*
 * Decompiled with CFR 0_132.
 */
package demo;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class MathGame {
    private static Random random = new Random();
    private int illegalArgumentCount = 0;

    public static void main(String[] args) throws InterruptedException {
        MathGame game = new MathGame();
        do {
            game.run();
            TimeUnit.SECONDS.sleep(1L);
        } while (true);
    }

    public void run() throws InterruptedException {
        try {
            int number = random.nextInt();
            List<Integer> primeFactors = this.primeFactors(number);
            MathGame.print(number, primeFactors);
        }
        catch (Exception e) {
            System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
        }
    }

    public static void print(int number, List<Integer> primeFactors) {
        StringBuffer sb = new StringBuffer("" + number + "=");
        Iterator<Integer> iterator = primeFactors.iterator();
        while (iterator.hasNext()) {
            int factor = iterator.next();
            sb.append(factor).append('*');
        }
        if (sb.charAt(sb.length() - 1) == '*') {
            sb.deleteCharAt(sb.length() - 1);
        }
        System.out.println(sb);
    }

    public List<Integer> primeFactors(int number) {
        if (number < 2) {
            ++this.illegalArgumentCount;
            throw new IllegalArgumentException("number is: " + number + ", need >= 2");
        }
        ArrayList<Integer> result = new ArrayList<Integer>();
        int i = 2;
        while (i <= number) {
            if (number % i == 0) {
                result.add(i);
                number /= i;
                i = 2;
                continue;
            }
            ++i;
        }
        return result;
    }
}

Affect(row-cnt:1) cost in 970 ms.
3、watch命令来查看函数返回值

通过watch命令来查看demo.MathGame#primeFactors函数的返回值

让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。

参数名称

参数说明

class-pattern

类名表达式匹配

method-pattern

函数名表达式匹配

express

观察表达式,默认值:{params, target, returnObj}

condition-express

条件表达式

[b]

函数调用之前观察

[e]

函数异常之后观察

[s]

函数返回之后观察

[f]

函数结束之后(正常返回和异常返回)观察

[E]

开启正则表达式匹配,默认为通配符匹配

[x:]

指定输出结果的属性遍历深度,默认为 1,最大值是 4

提示

观察表达式,默认值是{params, target, returnObj}

$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 32 ms, listenerId: 5
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2021-08-31 15:22:57; [cost=0.220625ms] result=@ArrayList[
    @Object[][
        @Integer[-179173],
    ],
    @MathGame[
        random=@Random[java.util.Random@31cefde0],
        illegalArgumentCount=@Integer[44],
    ],
    null,
]
method=demo.MathGame.primeFactors location=AtExit
ts=2021-08-31 15:22:58; [cost=1.020982ms] result=@ArrayList[
    @Object[][
        @Integer[1],
    ],
    @MathGame[
        random=@Random[java.util.Random@31cefde0],
        illegalArgumentCount=@Integer[44],
    ],
    @ArrayList[
        @Integer[2],
        @Integer[2],
        @Integer[26947],
    ],
]
  • 上面的结果里,说明函数被执行了两次,第一次结果是location=AtExceptionExit,说明函数抛出异常了,因此returnObj是 null
  • 在第二次结果里是location=AtExit,说明函数正常返回,因此可以看到returnObj结果是一个 ArrayList

4、快速生成火焰图

#启动 profiler

$ profiler start
Started [cpu] profiling 

提示

默认情况下,生成的是 cpu 的火焰图,即 event 为cpu。可以用--event参数来指定。

#获取已采集的 sample 的数量

$ profiler getSamples 
23 

#查看 profiler 状态

$ profiler status 
[cpu] profiling is running for 4 seconds 

可以查看当前 profiler 在采样哪种event和采样时间。

停止 profiler

生成 html 格式结果

默认情况下,结果文件是html格式,也可以用--format参数指定:

$ profiler stop --format html 
profiler output file: /tmp/test/arthas-output/20211207-111550.html OK 

或者在--file参数里用文件名指名格式。比如--file /tmp/result.html 。

通过浏览器查看 arthas-output 下面的 profiler 结果

默认情况下,arthas 使用 3658 端口,则可以打开: http://localhost:3658/arthas-output/在新窗口打开 查看到arthas-output目录下面的 profiler 结果:

点击可以查看具体的结果:

提示

如果是 chrome 浏览器,可能需要多次刷新。

命令手册大全
jvm 相关
  • dashboard - 当前系统的实时数据面板
  • getstatic - 查看类的静态属性
  • heapdump - dump java heap, 类似 jmap 命令的 heap dump 功能
  • jvm - 查看当前 JVM 的信息
  • logger - 查看和修改 logger
  • mbean - 查看 Mbean 的信息
  • memory - 查看 JVM 的内存信息
  • ognl - 执行 ognl 表达式
  • perfcounter - 查看当前 JVM 的 Perf Counter 信息
  • sysenv - 查看 JVM 的环境变量
  • sysprop - 查看和修改 JVM 的系统属性
  • thread - 查看当前 JVM 的线程堆栈信息
  • vmoption - 查看和修改 JVM 里诊断相关的 option
  • vmtool - 从 jvm 里查询对象,执行 forceGc
class/classloader 相关
  • classloader - 查看 classloader 的继承树,urls,类加载信息,使用 classloader 去 getResource
  • dump - dump 已加载类的 byte code 到特定目录
  • jad - 反编译指定已加载类的源码
  • mc - 内存编译器,内存编译.java文件为.class文件
  • redefine - 加载外部的.class文件,redefine 到 JVM 里
  • retransform - 加载外部的.class文件,retransform 到 JVM 里
  • sc - 查看 JVM 已加载的类信息
  • sm - 查看已加载类的方法信息
monitor/watch/trace 相关

注意

请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 stop 或将增强过的类执行 reset 命令。

  • monitor - 方法执行监控
  • stack - 输出当前方法被调用的调用路径
  • trace - 方法内部调用路径,并输出方法路径上的每个节点上耗时
  • tt - 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
  • watch - 方法执行数据观测
profiler/火焰图
鉴权
options
  • options - 查看或设置 Arthas 全局开关
管道

Arthas 支持使用管道对上述命令的结果进行进一步的处理,如sm java.lang.String * | grep 'index'

  • grep - 搜索满足条件的结果
  • plaintext - 将命令的结果去除 ANSI 颜色
  • wc - 按行统计输出结果
后台异步任务

当线上出现偶发的问题,比如需要 watch 某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考这里

  • 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session 断开不影响任务执行(生命周期默认为 1 天)
  • jobs - 列出所有 job
  • kill - 强制终止任务
  • fg - 将暂停的任务拉到前台执行
  • bg - 将暂停的任务放到后台执行
基础命令
  • base64 - base64 编码转换,和 linux 里的 base64 命令类似
  • cat - 打印文件内容,和 linux 里的 cat 命令类似
  • cls - 清空当前屏幕区域
  • echo - 打印参数,和 linux 里的 echo 命令类似
  • grep - 匹配查找,和 linux 里的 grep 命令类似
  • help - 查看命令帮助信息
  • history - 打印命令历史
  • keymap - Arthas 快捷键列表及自定义快捷键
  • pwd - 返回当前的工作目录,和 linux 命令类似
  • quit - 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
  • reset - 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
  • session - 查看当前会话的信息
  • stop - 关闭 Arthas 服务端,所有 Arthas 客户端全部退出
  • tee - 复制标准输入到标准输出和指定的文件,和 linux 里的 tee 命令类似
  • version - 输出当前目标 Java 进程所加载的 Arthas 版本号

2、性能优化

1、经典MVC模型优化

SpringBoot默认使用内嵌的tomcat作为Web容器,使用典型的MVC模式,最终访问到我们的数据

1.使用CDN加速文件获取

比较大的文件,尽量使用CDN(Content Delivery Network)分发。甚至是一些常用的前端脚本、样式、图片等,都可以放到CDN上。CDN通常能够加快这些文件的获取,网页加载也更加迅速。

2.合理设置Cache-Control值

浏览器会判断HTTP头Cache-Control的内容,用来决定是否使用浏览器缓存,这在管理一些静态文件的时候,非常有用。相同作用的头信息还有Expires。Cache-Control表示多久之后过期,Expires则表示什么时候过期。

这个参数可以在Nginx的配置文件中进行设置。

location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ { 
            # 缓存1年
            add_header Cache-Control: no-cache, max-age=31536000;
}

3、开启gzip

开启gzip,可以先把内容压缩后,浏览器再进行解压。由于减少了传输的大小,会减少带宽的使用,提高传输效率。在nginx中可以很容易的开启。配置如下:

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_types text/plain application/javascript text/css;

4.使用keepalive

由于连接的创建和关闭,都需要耗费资源。用户访问我们的服务后,后续也会有更多的互动,所以保持长连接可以显著减少网络交互,提高性能。

nginx默认开启了对客户端的keep avlide支持。你可以通过下面两个参数来调整它的行为。

http {
    keepalive_timeout  120s 120s;
    keepalive_requests 10000;
}
location ~ /{ 
       proxy_pass http://backend;
       proxy_http_version 1.1;
       proxy_set_header Connection "";
}
  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值