Skip to content

Create an annotation

Jean Bisutti edited this page Nov 20, 2019 · 14 revisions

In this page, you will learn the principles to create a QuickPerf annotation. After reading it, you should be able to create a QuickPerf annotation in the QuickPerf project or in your own project. In addition, you will learn how to create your own Maven module defining your custom QuickPerf annotations.

🚩 Table of contents

Principles to create a QuickPerf annotation

Create a core, a JVM or a SQL annotation

Define custom annotations in a specific Maven module

Test your new annotation

Debug an annotation

Principles to create a QuickPerf annotation

⚠️ You can follow all the instructions below if you create a new annotation type (that is to say not a core, a JVM or a SQL annotation) or if you define annotations in a specific Maven module. Otherwise, you can read this part and follow the instructions given here.

The code examples below come from sql-annotations Maven module.

Declare a SPI implementation

QuickPerf uses the Service Provider Interface (SPI) to dynamically load the configurations of annotations.

A file named org.quickperf.config.library.QuickPerfConfigLoader has to be in src/main/resources/META-INF/services:



The Content of org.quickperf.config.library.QuickPerfConfigLoader file is here: org.quickperf.sql.config.library.SqlConfigLoader

Implement QuickPerfConfigLoader

An implementation of QuickPerfConfigLoader has to define three methods:

  • loadAnnotationConfigs(): returns the configurations of annotations
  • loadRecorderExecutionOrdersBeforeTestMethod(): returns the recorder priorities before the execution of a test method
  • loadRecorderExecutionOrdersAfterTestMethod(): returns the recorder priorities after the execution of a test method
public class SqlConfigLoader implements QuickPerfConfigLoader {

 @Override
    public Collection<AnnotationConfig> loadAnnotationConfigs() {
        return Arrays.asList(
                // ..
                , SqlAnnotationsConfigs.DISABLE_EXACTLY_SAME_SQL_SELECTS
                // ...
        );
    }

    @Override
    public Collection<RecorderExecutionOrder> loadRecorderExecutionOrdersBeforeTestMethod() {
        return Arrays.asList(
                  new RecorderExecutionOrder(PersistenceSqlRecorder.class, 2000)
        );
    }

    @Override
    public Collection<RecorderExecutionOrder> loadRecorderExecutionOrdersAfterTestMethod() {
        return Arrays.asList(
                 new RecorderExecutionOrder(PersistenceSqlRecorder.class, 7000)
        );
    }

}

Define the configuration of a given annotation

The configuration of an annotation is defined with the help of an instance of AnnotationConfig.Builder().

class SqlAnnotationsConfigs {

	static final AnnotationConfig DISABLE_EXACTLY_SAME_SQL_SELECTS = new AnnotationConfig.Builder()
			.perfRecorderClass(PersistenceSqlRecorder.class)
			.perfMeasureExtractor(HasExactlySameSelectExtractor.INSTANCE)
			.perfIssueVerifier(HasExactlySameSelectVerifier.INSTANCE)
			.build(DisableExactlySameSelects.class);
      // ...
}

Let's explain the methods used in the example above:

  • perfRecorderClass: to specify a performance recorder, for example the set of SQL statements sent to database during the execution of the test method body
  • perfMeasureExtractor: to define the way a performance measure is extracted from the recorder, for example if there exists exactly same SELECT statements sent to the database
  • perfIssueVerifier: to evaluate if a performance issue exists
  • build: the annotation for which the annotation configuration is built

You can use testHasToBeLaunchedInASpecificJvm() method to specify that the test method has to be executed in a specific JVM. A testHasToBeLaunchedInASpecificJvm(AnnotationToJvmOptionConverter annotationToJvmOptionConverter) method is also available to add some options to the JVM.

An example for @Xmx:

   static final AnnotationConfig XMX = new AnnotationConfig.Builder()
            .testHasToBeLaunchedInASpecificJvm(XmxAnnotToJvmOptionConverter.INSTANCE)
            .build(Xmx.class);

The code of XmxAnnotToJvmOptionConverter can be found here.

Create a core, a JVM or a SQL annotation

You need to:

  1. Define the configuration of the annotation
  2. Declare a new annotation configuration in loadAnnotationConfigs() method of QuickPerfConfigLoader implementation
  3. If you have defined a new recorder type, you have to complete the loadRecorderExecutionOrdersBeforeTestMethod() loadRecorderExecutionOrdersAfterTestMethod() methods of QuickPerfConfigLoader implementation

Define custom annotations in a specific Maven module

You can develop custom QuickPerf annotations and gather them in a Maven module. To develop the annotations, you can follow the principles described above. To use them, you simply have to use the developed Maven dependency together with one QuickPerf dependency (see here for JUnit4 or here for Spring). Don't hesitate to propose a feature request and a PR to integrate your annotations in the QuickPerf project!

Test your new annotation

Test your new annotation with JUnit 4

Example of JUnit4 test class.

Test your new annotation with JUnit 5

Example of JUnit5 test class

Debug an annotation

You can add @DebugQuickPerf on a test method to get debug data.

Annotations

πŸ‘‰ Β Core

πŸ‘‰ Β JVM

πŸ‘‰ Β SQL

πŸ‘‰ Β Scopes

πŸ‘‰ Β Create an annotation

Supported frameworks

πŸ‘‰ Β JUnit 4

πŸ‘‰ Β JUnit 5

πŸ‘‰ Β TestNG

πŸ‘‰ Β Spring

How to

πŸ‘‰ Β Detect and fix N+1 SELECT

Project examples

πŸ‘‰ Β Maven performance

πŸ‘‰ Β Spring Boot - JUnit 4

πŸ‘‰ Β Spring Boot - JUnit 5

πŸ‘‰ Β Micronaut Data - JUnit 5

πŸ‘‰ Β Micronaut - Spring - JUnit 5

πŸ‘‰ Β Quarkus - JUnit 5

Miscellaneous

πŸ‘‰ Β FAQ

πŸ‘‰ Β QuickPerf code

Clone this wiki locally