package org.beetl.sql.jmh;

import org.beetl.sql.jmh.beetl.BeetlSQLService;
import org.beetl.sql.jmh.jdbc.JdbcService;
import org.beetl.sql.jmh.jpa.SpringBoot;
import org.beetl.sql.jmh.jpa.SpringService;
import org.beetl.sql.jmh.mybatis.MyBatisSpringBoot;
import org.beetl.sql.jmh.mybatis.MyBatisSpringService;
import org.beetl.sql.jmh.weed.WeedService;
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.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 性能测试入口,数据是Throughput，越大越好
 */
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Threads(1)
@Fork(1)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
public class JMHMain {
    JdbcService jdbcService = null;
    BeetlSQLService beetlSQLService = null;
    SpringService springService = null;
    MyBatisSpringService myBatisSpringService = null;
    WeedService weedService = null;

    @Setup
    public void init() {

        jdbcService = new JdbcService();
        jdbcService.init();

        beetlSQLService = new BeetlSQLService();
        beetlSQLService.init();

        SpringBoot springBoot = new SpringBoot();
        springBoot.init();
        springService = springBoot.getService();


        MyBatisSpringBoot myBatisSpringBoot = new MyBatisSpringBoot();
        myBatisSpringBoot.init();
        myBatisSpringService = myBatisSpringBoot.getService();

        weedService = new WeedService();
        weedService.init();

    }


    /*   JDBC,基准，有些方法性能飞快    */
    @Benchmark
    public void jdbcInsert() {
        jdbcService.addEntity();
    }

    @Benchmark
    public void jdbcSelectById() {
        jdbcService.getEntity();
    }

    @Benchmark
    public void jdbcExecuteJdbc() {
        jdbcService.executeJdbcSql();
    }


    /* mybatis */
    @Benchmark
    public void mybatisInsert() {
        myBatisSpringService.addEntity();
    }

    @Benchmark
    public void mybatisSelectById() {
        myBatisSpringService.getEntity();
    }

    @Benchmark
    public void mybatisLambdaQuery() {
        myBatisSpringService.lambdaQuery();
    }

    @Benchmark
    public void mybatisExecuteTemplate() {
        myBatisSpringService.executeTemplateSql();
    }

    @Benchmark
    public void mybatisFile() {
        myBatisSpringService.sqlFile();
    }

    @Benchmark
    public void mybatisPageQuery() {
        myBatisSpringService.pageQuery();
    }

    @Benchmark
    public void mybatisComplexMapping() {
        myBatisSpringService.complexMapping();
    }


    /*   BeetlSQL    */
    @Benchmark
    public void beetlsqlInsert() {
        beetlSQLService.addEntity();
    }

    @Benchmark
    public void beetlsqlSelectById() {
        beetlSQLService.getEntity();
    }

    @Benchmark
    public void beetlsqlLambdaQuery() {
        beetlSQLService.lambdaQuery();
    }

    @Benchmark
    public void beetlsqlExecuteJdbc() {
        beetlSQLService.executeJdbcSql();
    }

    @Benchmark
    public void beetlsqlExecuteTemplate() {
        beetlSQLService.executeTemplateSql();
    }

    @Benchmark
    public void beetlsqlFile() {
        beetlSQLService.sqlFile();
    }

    @Benchmark
    public void beetlsqlPageQuery() {
        beetlSQLService.pageQuery();
    }


    @Benchmark
    public void beetlsqlOne2Many() {
        beetlSQLService.one2Many();
    }

    @Benchmark
    public void beetlsqlComplexMapping() {
        beetlSQLService.complexMapping();
    }


    /*   Spring Data JPA    */
    @Benchmark
    public void jpaInsert() {
        springService.addEntity();
    }

    @Benchmark
    public void jpaSelectById() {
        springService.getEntity();
    }

    @Benchmark
    public void jpaExecuteJdbc() {
        springService.executeJdbcSql();
    }

    /*实际上JPA并不支持template，但勉强用HQl来测试*/
    @Benchmark
    public void jpaExecuteTemplate() {
        springService.executeTemplateSql();
    }

    @Benchmark
    public void jpaOne2Many() {
        springService.one2Many();
    }

    @Benchmark
    public void jpaPageQuery() {
        springService.pageQuery();
    }

    /*   Weed3    */
    @Benchmark
    public void weedInsert() {
        weedService.addEntity();
    }

    @Benchmark
    public void weedSelectById() {
        weedService.getEntity();
    }

    @Benchmark
    public void weedLambdaQuery() {
        weedService.lambdaQuery();
    }

    @Benchmark
    public void weedExecuteJdbc() {
        weedService.executeJdbcSql();
    }

    @Benchmark
    public void weedExecuteTemplate() {
        weedService.executeTemplateSql();
    }

    @Benchmark
    public void weedFile() {
        weedService.sqlFile();
    }

    @Benchmark
    public void weedPageQuery() {
        weedService.pageQuery();
    }


    public static void main(String[] args) throws RunnerException {

//          test();
        Options opt = new
                OptionsBuilder()
                .include(JMHMain.class.getSimpleName())
                .build();
        new Runner(opt).run();
    }

    /**
     * 先单独运行一下保证每个测试都没有错误
     */
    public static void test() {
        JMHMain jmhMain = new JMHMain();
        jmhMain.init();
        for (int i = 0; i < 3; i++) {
            Method[] methods = jmhMain.getClass().getMethods();
            for (Method method : methods) {
                if (method.getAnnotation(Benchmark.class) == null) {
                    continue;
                }
                try {

                    method.invoke(jmhMain, new Object[0]);

                } catch (Exception ex) {
                    throw new IllegalStateException(" method " + method.getName(), ex);
                }

            }
        }

    }


}
