/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/JMH benchmark sample: Java
 */
package net.ranides.benchmark.app;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import net.ranides.assira.reflection.IClass;
import net.ranides.assira.text.Charsets;
import net.ranides.assira.text.IOStrings;
import org.openjdk.jmh.annotations.Mode;
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;
/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class BenchmarkRunner {
    
    public static void run(Class<?> benchmark) throws RunnerException, IOException {
        run(benchmark,3);
    }
    
    public static void run(Class<?> benchmark, int iterations) throws RunnerException, IOException {
        Map<String, String> names = IClass.typeinfo(benchmark)
            .methods()
            .require(BenchmarkName.class)
            .collect(Collectors.toMap(m -> m.name(), m -> m.annotation(BenchmarkName.class).get().value()));
        
        File file = new File("../doc/"+benchmark.getSimpleName()+".csv");
        Iterator<String> re = new Runner(options(benchmark,iterations))
            .run()
            .stream()
            .map(r -> r.getAggregatedResult().getPrimaryResult())
            .map(r -> String.format("%s,%.0f,%.0f,%s", 
                names.getOrDefault(r.getLabel(), r.getLabel()),
                r.getScore(), 
                r.getScoreError(), 
                r.getScoreUnit()
            ))
            .iterator();
        
        IOStrings.writeLines(file, Charsets.UTF8, re);
    }
    
    public static Options options(Class<?> benchmark, int iterations) {
        String name = benchmark.getSimpleName();
        return new OptionsBuilder()
            .include(".*" + name + ".*")
            .timeUnit(TimeUnit.NANOSECONDS)
            .mode(Mode.AverageTime)
            .forks(3)
            .measurementIterations(iterations)
            .warmupIterations(3)
            .build();
    }
    
    public static void main(String[] args) {
        
    }
    
}
