橘子学JDK之JMH-02(BenchmarkModes)

一、案例二代码

这次我们来搞一下官网文档的第二个案例,我删除了一些没用的注释,然后对代码做了一下注释的翻译,可以看一下意思。

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {

    /*
     * Mode.Throughput, as stated in its Javadoc, measures the raw throughput by
     * continuously calling the benchmark method in a time-bound iteration, and
     * counting how many times we executed the method.
     *
     * We are using the special annotation to select the units to measure in,
     * although you can use the default.
     *
     * AI直译:Mode.Throughput,如其Javadoc所述,通过在时间限制的迭代中连续调用基准方法,
     * 并计算我们执行该方法的次数来衡量原始吞吐量。我们正在使用特殊注解来选择要测量的单位,尽管你可以使用默认值。
     *
     * 我根据我的理解还是说几句人话吧,他的意思是我们之前不是在案例1中输出的是吞吐量的测试指标吗,这里的意思是你可以
     * 使用@BenchmarkMode这个注解,里面设置参数Mode.Throughput一样可以是通过吞吐量的指标的,或者说你不设置,默认
     * 本身就是吞吐量,我们第一个案例就是默认的。
     * 所以我们在第一个方法上看到新出现的两个注解
     * @BenchmarkMode:设置计算指标
     * @OutputTimeUnit:计算模式对应的单位
     */

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.SECONDS)
    public void measureThroughput() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    /*
     * Mode.AverageTime measures the average execution time, and it does it
     * in the way similar to Mode.Throughput.
     * 在性能测试或基准测试的背景下,Mode.AverageTime(平均时间模式)测量了给定操作或代码片段的平均执行时间。
     * 该模式计算了每次调用被测试代码所花费的平均时间。它与Mode.Throughput(吞吐量模式)相似,两种模式都专注于性能测量,
     * 但它们在优先考虑的性能方面存在差异。以下是Mode.AverageTime和Mode.Throughput之间的简要比较:
     * 平均时间:该模式计算每个操作或调用的平均执行时间。它提供了关于单个操作平均执行时间的信息。
     * 吞吐量:另一方面,Mode.Throughput关注的是在给定时间内完成的操作速率。它衡量每单位时间内可以执行多少操作,通常是每秒。
     * 它提供了系统在高负载下处理大量操作的效率信息。
     * 虽然两种模式都提供了有关性能的有价值的信息,但它们服务于不同的目的,可能适用于不同类型的性能分析。
     * Mode.AverageTime适用于了解单个操作的平均延迟或执行时间,而Mode.Throughput更适用于在指定时间范围内最大化完成的操作数量。
     *
     *
     * Some might say it is the reciprocal throughput, and it really is.
     * There are workloads where measuring times is more convenient though.
     * 有人说,这个指标是吞吐量的倒数,你也可以这么理解,不过有时候你测试的时候,统计时间维度是更加直观的。
     *
     * 换言之,这个是统计你方法的执行平均时间的,所以看起来比吞吐量更加直观,毕竟耗时是我们普遍关心的第一指标
     */
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureAvgTime() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    /*
     * Mode.SampleTime samples the execution time. With this mode, we are
     * still running the method in a time-bound iteration, but instead of
     * measuring the total time, we measure the time spent in *some* of
     * the benchmark method calls.
     *
     * Mode.SampleTime是用于对方法执行时间进行采样的一种模式。在这种模式下,我们仍然在一个有时间限制的迭代中运行方法,
     * 但不再测量总时间,而是测量一部分基准方法调用所花费的时间。使用Mode.SampleTime模式时,
     * 基准测试框架会定期中断方法的执行并记录经过的时间。通过只对部分调用进行采样,可以减少与连续时间测量相关的开销,
     * 同时仍能提供有关方法执行时间分布的有意义数据,而不仅仅关注整体持续时间。这种模式对于识别执行时间的变化非常有用,
     * 特别是如果方法的某些部分可能具有不同的性能特点或表现出间歇性行为。它使开发人员能够了解方法在不同条件下的性能表现,
     * 并帮助优化其性能。
     *
     * This allows us to infer the distributions, percentiles, etc.
     * JMH also tries to auto-adjust sampling frequency: if the method
     * is long enough, you will end up capturing all the samples.
     * 这样可以让我们推断出分布情况、百分位数等。JMH 还会尝试自动调整采样频率:如果方法足够长,你最终会捕获到所有的样本
     *
     * 这个解释的不明确,我们待会通过现象来看一下具体啥意思。
     */
    @Benchmark
    @BenchmarkMode(Mode.SampleTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureSamples() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    /*
     * Mode.SingleShotTime measures the single method invocation time. As the Javadoc
     * suggests, we do only the single benchmark method invocation. The iteration
     * time is meaningless in this mode: as soon as benchmark method stops, the
     * iteration is over.
     *
     * Mode.SingleShotTime测量的是单个方法调用的时间。正如Javadoc所建议的,我们只进行一次基准方法的调用。
     * 在这种模式下,迭代时间是没有意义的:一旦基准方法停止,迭代就结束了。
     *
     * This mode is useful to do cold startup tests, when you specifically
     * do not want to call the benchmark method continuously.
     * 这种模式在进行冷启动测试时非常有用,当你不想连续调用基准方法时。
     *
     * 说白了就是只测试一次,就跟你跑main函数一样的,没有预热,就是冷启动的测试。
     */
    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureSingleShot() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    /*
     * We can also ask for multiple benchmark modes at once. All the tests
     * above can be replaced with just a single test like this:
     *
     * 这个注解还能写数组,指定多种测试指标,一起生效
     */
    @Benchmark
    @BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureMultiple() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    /*
     * Or even...
     * 如果你懒得写很多模式,你还能直接用Mode.All来表示全部的模式
     */
    @Benchmark
    @BenchmarkMode(Mode.All)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureAll() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

二、@BenchmarkMode

我们先不急着运行程序,我们在看完上面的例子之后可以看到这次出现了一个新的注解,就是
@BenchmarkMode

@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface BenchmarkMode {
    Mode[] value();
}

这个注解我们看到,作用的位置就是方法和类上面,你要是标注在类上,那就这个类所有的方法都按照这个配置生效了。
而且我们注意到他有一个变量,是Mode类型的数组,注意是数组,也就是可以传入多个。我们看一下这个Mode类型是啥。

public enum Mode {
    Throughput("thrpt", "Throughput, ops/time"),
    AverageTime("avgt", "Average time, time/op"),
    SampleTime("sample", "Sampling time"),
    SingleShotTime("ss", "Single shot invocation time"),
    All("all", "All benchmark modes");
}

就是个枚举类型,总共五个类型,我们上面的注释其实也标注了这五个类型的各自的作用。

三、 @OutputTimeUnit

与@BenchmarkMode 配套的还有一个注解就是@OutputTimeUnit。

@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OutputTimeUnit {
    TimeUnit value();
}

他的作用就是你输出指标的时间单位,没别的了。OK,我们在大致有个了解之后,我们开始通过执行程序来看一下结果,加深我们对于注解的理解。

四、执行程序

鉴于我们这里这次一次写了N个方法测试,输出的报告巨长,我们这里就一个一个的测试,这样方便观察。

1、测试吞吐模式:measureThroughput

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {

    /*
     * Mode.Throughput, as stated in its Javadoc, measures the raw throughput by
     * continuously calling the benchmark method in a time-bound iteration, and
     * counting how many times we executed the method.
     *
     * We are using the special annotation to select the units to measure in,
     * although you can use the default.
     *
     * AI直译:Mode.Throughput,如其Javadoc所述,通过在时间限制的迭代中连续调用基准方法,
     * 并计算我们执行该方法的次数来衡量原始吞吐量。我们正在使用特殊注解来选择要测量的单位,尽管你可以使用默认值。
     *
     * 我根据我的理解还是说几句人话吧,他的意思是我们之前不是在案例1中输出的是吞吐量的测试指标吗,这里的意思是你可以
     * 使用@BenchmarkMode这个注解,里面设置参数Mode.Throughput一样可以是通过吞吐量的指标的,或者说你不设置,默认
     * 本身就是吞吐量,我们第一个案例就是默认的。
     * 所以我们在第一个方法上看到新出现的两个注解
     * @BenchmarkMode:设置计算指标
     * @OutputTimeUnit:计算模式对应的单位
     */

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.SECONDS)
    public void measureThroughput() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

运行结果为:
Benchmark :JMHSample_02_01_BenchmarkModes.measureThroughput
Mode :thrpt
Cnt : 因为我控制了1次,所以这里没东西
Score :9.160 这个分数在吞吐这里其实就是你执行的吞吐量,因为我写的@OutputTimeUnit(TimeUnit.SECONDS)单位是秒,所以意思就是一秒能执行9.16次。
Error :没输出
Units:ops/s
我们看到这个吞吐量其实和我们在第一个案例测试的差不多,其实他就是默认的。你不写就是他。

2、测试平均时间模式:measureAvgTime

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {

   
    /*
     * Mode.AverageTime measures the average execution time, and it does it
     * in the way similar to Mode.Throughput.
     * 在性能测试或基准测试的背景下,Mode.AverageTime(平均时间模式)测量了给定操作或代码片段的平均执行时间。
     * 该模式计算了每次调用被测试代码所花费的平均时间。它与Mode.Throughput(吞吐量模式)相似,两种模式都专注于性能测量,
     * 但它们在优先考虑的性能方面存在差异。以下是Mode.AverageTime和Mode.Throughput之间的简要比较:
     * 平均时间:该模式计算每个操作或调用的平均执行时间。它提供了关于单个操作平均执行时间的信息。
     * 吞吐量:另一方面,Mode.Throughput关注的是在给定时间内完成的操作速率。它衡量每单位时间内可以执行多少操作,通常是每秒。
     * 它提供了系统在高负载下处理大量操作的效率信息。
     * 虽然两种模式都提供了有关性能的有价值的信息,但它们服务于不同的目的,可能适用于不同类型的性能分析。
     * Mode.AverageTime适用于了解单个操作的平均延迟或执行时间,而Mode.Throughput更适用于在指定时间范围内最大化完成的操作数量。
     *
     *
     * Some might say it is the reciprocal throughput, and it really is.
     * There are workloads where measuring times is more convenient though.
     * 有人说,这个指标是吞吐量的倒数,你也可以这么理解,不过有时候你测试的时候,统计时间维度是更加直观的。
     *
     * 换言之,这个是统计你方法的执行平均时间的,所以看起来比吞吐量更加直观,毕竟耗时是我们普遍关心的第一指标
     */
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureAvgTime() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

运行结果如下:
Benchmark :JMHSample_02_01_BenchmarkModes.measureAvgTime
Mode:avgt 平均统计模式
Cnt :同上
Score:108407.350
Error :没错误,不输出
Units:us/op 其实你能看出来,他是时间除以执行次数,所以就是吞吐量的倒数,吞吐量的意思是每秒能执行几次,这里就是执行一次需要几秒,不就是平均时间吗。只是我指定的时间单位是@OutputTimeUnit(TimeUnit.MICROSECONDS)微秒,所以这里自然也就是这个单位。
他主打的是一个平均耗时。

3、测试统计时间:measureSamples

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
    /*
     * Mode.SampleTime samples the execution time. With this mode, we are
     * still running the method in a time-bound iteration, but instead of
     * measuring the total time, we measure the time spent in *some* of
     * the benchmark method calls.
     *
     * Mode.SampleTime是用于对方法执行时间进行采样的一种模式。在这种模式下,我们仍然在一个有时间限制的迭代中运行方法,
     * 但不再测量总时间,而是测量一部分基准方法调用所花费的时间。使用Mode.SampleTime模式时,
     * 基准测试框架会定期中断方法的执行并记录经过的时间。通过只对部分调用进行采样,可以减少与连续时间测量相关的开销,
     * 同时仍能提供有关方法执行时间分布的有意义数据,而不仅仅关注整体持续时间。这种模式对于识别执行时间的变化非常有用,
     * 特别是如果方法的某些部分可能具有不同的性能特点或表现出间歇性行为。它使开发人员能够了解方法在不同条件下的性能表现,
     * 并帮助优化其性能。
     *
     * This allows us to infer the distributions, percentiles, etc.
     * JMH also tries to auto-adjust sampling frequency: if the method
     * is long enough, you will end up capturing all the samples.
     * 这样可以让我们推断出分布情况、百分位数等。JMH 还会尝试自动调整采样频率:如果方法足够长,你最终会捕获到所有的样本
     *
     * 这个解释的不明确,我们待会通过现象来看一下具体啥意思。
     */
    @Benchmark
    @BenchmarkMode(Mode.SampleTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureSamples() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

在这里插入图片描述
他是以一种分布统计的方式输出的测试指标,单位还是平均时间耗时,等于说百分之99的测试跑一次是109707.264us的耗时,他内部给你做了一个测试,拆分出来测的,测出这么个结果来。
能看出来一个波动,和你实现的代码稳定性,而且他是抽样测试,不会都给你统计,比如我们设置的跑1轮,每轮一秒。可能这一秒跑了一万次,他不会像吞吐和平均那个样都算进去,他是一个抽样,可能抽了前面后面,没取中间。可能压根就是抽了前面。是一个分布统计。

4、测试只跑一次:measureSingleShot

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
    /*
     * Mode.SingleShotTime measures the single method invocation time. As the Javadoc
     * suggests, we do only the single benchmark method invocation. The iteration
     * time is meaningless in this mode: as soon as benchmark method stops, the
     * iteration is over.
     *
     * Mode.SingleShotTime测量的是单个方法调用的时间。正如Javadoc所建议的,我们只进行一次基准方法的调用。
     * 在这种模式下,迭代时间是没有意义的:一旦基准方法停止,迭代就结束了。
     *
     * This mode is useful to do cold startup tests, when you specifically
     * do not want to call the benchmark method continuously.
     * 这种模式在进行冷启动测试时非常有用,当你不想连续调用基准方法时。
     *
     * 说白了就是只测试一次,就跟你跑main函数一样的,没有预热,就是冷启动的测试。
     */
    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureSingleShot() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

执行结果如下:
在这里插入图片描述
这就是测试冷启动的,没预热,就是直接跑,你也能看到单位是us/op。还是执行一次要多久。还是个平均值,只不过就是没预热直接开跑的。就跑一次。

5、测试多种模式组合:measureMultiple

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {

    /*
     * We can also ask for multiple benchmark modes at once. All the tests
     * above can be replaced with just a single test like this:
     *
     * 这个注解还能写数组,指定多种测试指标,一起生效
     */
    @Benchmark
    @BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureMultiple() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

因为我们前面看了Mode是一个数组,所以可以传入多个模式。结果就是一起统计输出了。
在这里插入图片描述

6、测试全量模式:measureAll

package com.levi;

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.concurrent.TimeUnit;

// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
    /*
     * Or even...
     * 如果你懒得写很多模式,你还能直接用Mode.All来表示全部的模式
     */
    @Benchmark
    @BenchmarkMode(Mode.All)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void measureAll() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

自然就是全部的统计都输出了:和上面一样。
在这里插入图片描述
你也可以看他的单位就知道他输出的计算方式了,次数除以时间,那就是平均时间的执行次数,就是吞吐。
时间除以次数,就是统计的某种模式下的平均时间。

五、总结

没啥总结的就是那两个注解,很详细了。

六、参考链接

1、JMH官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/537130.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RocketMQ之Topic和Tag最佳实践

一、Topic是什么?它的作用? Topic即主题,是消息队列中用于对消息进行分类和组织的一种机制,它有以下三种作用: 标识消息分类:RocketMQ的主题用于对消息进行分类和组织。通过为不同类型的消息分配不同的主题…

LeetCode-Java:6.Z字形变换

文章目录 题目解① 找规律 题目 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下: P A H N A P L S I I G Y I R之后&a…

2024Mathorcup(妈妈杯)数学建模C题python代码+数据教学

2024Mathorcup数学建模挑战赛(妈妈杯)C题保姆级分析完整思路代码数据教学 C题题目:物流网络分拣中心货量预测及人员排班 因为一些不可抗力,下面仅展示部分代码(很少部分部分)和部分分析过程,其…

[python] Numpy库用法(持续更新)

先导入一下 import numpy as np 一、np.random用法 生成随机整数:np.random.randint(low, high, size) low: 最小值high: 最大值size: 生成的数组大小(可以是多维,下面同理) 生成随机浮点数:np.random.uniform(low, …

下线圈和包扎

电机槽内放好 所有槽纸 槽内再放入引槽纸 作用是放线圈的时候避免划伤线 开始放线圈 绑了白色扎带的朝外面 线圈的一边放进去后,另一边还悬在外面 ,这里俗称 吊边。 为了保护吊边 ,在吊边处放一张大的绝缘纸 (如下图&#xff0…

32.WEB渗透测试-数据传输与加解密(6)

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:31.WEB渗透测试-数据传输与加解密(5) 关于discuz3.5的源码内容和…

C++STL--谓词

谓词 ① 可调用的表达式称为谓词,包括仿函数,自定义函数,lambda表达式。 ② 接受一个参数的谓词,称为一元谓词。 ③ 接受两个参数的谓词,称为二元谓词。 可调用的表达式:对于一个对象或者表达式,如果可以使用调用运算符(),就称它为可以调用的。 一元谓…

java混淆的重要性分析

Java代码混淆是一种常用的安全技术,它通过对Java代码进行变换和重命名,使得源代码变得难以理解和逆向工程,从而增强代码的安全性。以下是对Java混淆重要性的分析: 保护知识产权:Java混淆可以防止恶意用户或竞争对手轻易…

macos 查看 远程服务器是否开放某个端口

想要使用mac查看远程服务器某个端口是否开发&#xff0c;可通过 nc 命令&#xff0c;如下&#xff1a; nc -zv <服务器IP> <端口号>如果该端口开发&#xff0c;结果为&#xff1a;succeeded! Connection to <服务器IP> port <端口号> [类型] succeed…

密码学 | 椭圆曲线 ECC 密码学入门(二)

目录 4 椭圆曲线&#xff1a;更好的陷门函数 5 奇异的对称性 6 让我们变得奇特 ⚠️ 原文地址&#xff1a;A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography ⚠️ 写在前面&#xff1a;本文属搬运博客&#xff0c;自己留着学习。如果你和我一样…

leetcode 1702

leetcode 1702 题目 例子 代码思路 class Solution { public:string maximumBinaryString(string binary) {int n binary.size();int i binary.find(0);if(i string::npos){return binary;}int zeros count(binary.begin(), binary.end(), 0);string s(n, 1);s[izeros-1]…

Python爬虫怎么挣钱?6个Python爬虫赚钱方式,搞搞副业不是问题

1.最典型的就是找爬虫外包活儿 网络爬虫最通常的的挣钱方式通过外包网站&#xff0c;做中小规模的爬虫项目&#xff0c;向甲方提供数据抓取&#xff0c;数据结构化&#xff0c;数据清洗等服务。新入行的程序员大多都会先尝试这个方向&#xff0c;直接靠技术手段挣钱&#xff0…

数据结构复习指导之绪论(算法的概念以及效率的度量)

文章目录 绪论&#xff1a; 2.算法和算法评价 知识总览 2.1算法的基本概念 知识点回顾与重要考点 2.2算法效率的度量 知识总览 1.时间复杂度 2.空间复杂度 知识点回顾与重要考点 归纳总结 绪论&#xff1a; 2.算法和算法评价 知识总览 2.1算法的基本概念 算法( Al…

一辆汽车的节拍时间是怎样的?

节拍时间&#xff0c;又称 takt time&#xff0c;是德语中“节奏”的意思。在汽车制造业中&#xff0c;它指的是按照客户需求和生产计划&#xff0c;生产一辆汽车所需的时间。这个时间是固定的&#xff0c;它决定了生产线上每个工序的操作速度和节奏&#xff0c;是生产线上所有…

一题多解之数塔问题

递归实现:记忆化深度遍历 #include <iostream> #include <algorithm> #include <string> using namespace std; int num[1000][1000],n;//递归实现:记忆化深度遍历 int dfs(int x,int y){int sum0;//记录最大情况if(x>n||y>x) return sum;//实现每次都…

功能测试_验证标题长度合法性_边界值法

验证标题长度合法性&#xff08;标题长度大于0&#xff0c;小于等于30个字符&#xff09; 开内闭外&#xff0c;保留1和31

水电智能远程抄表系统

水电智能远程抄表系统是一种应用先进技术实现水电抄表的智能化管理系统&#xff0c;通过远程抄表、数据传输和智能分析&#xff0c;实现了对水电使用情况的实时监测和管理。本文将从系统特点、构成以及带来的效益三个方面展开介绍。 系统特点 1.远程抄表&#xff1a;系统能够…

cas学习4:自定义登出页面

接上一章学习 cas学习3&#xff1a;自定义登录页面_cas 个性化页面-CSDN博客 后我们要自定义登出页面&#xff0c;因为在配置完cas后各个子系统退出后的都是cas登出页面。不符合实际需要&#xff0c;所以我们要配置自己的登出页面 1.修改application.properties 增加&#…

有效确认手机号机主姓名,避免信息错误

在如今信息爆炸的时代&#xff0c;手机已经成为我们生活中必不可少的一部分。手机号码的重要性已经不仅仅是联系工具&#xff0c;更是诸多场景下的实名认证必备条件&#xff0c;如电商、游戏、直播、金融等。为了保证用户信息的准确性和安全性&#xff0c;挖数据平台上的手机号…

软件测试学习之MySQL学习笔记(完结)

目录 1. 数据库**** 1.1. 概念**** 1.2. 分类**** 1.2.1. 关系型数据库**** 1.2.1.1. SQL**** 1.2.2. 安装**** 1.2.2.1. Navicat**** 2. SQL语句**** 2.1. 常用数据类型**** 2.2. 数据库**** 2.3. 表**** 2.3.1. 字段约束**** 2.4. 数据**** 2.4.1. 增 insert**…