/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */

import java.text.DecimalFormat

plugins {
    id "me.champeau.gradle.jmh" version "0.5.0"
}

configurations {
    stats
    testImplementation.extendsFrom(stats)
}

dependencies {
    jmh rootProject
    testImplementation rootProject
    stats 'org.apache.commons:commons-math3:3.6.1'
}

jmh {
    jmhVersion = '1.21'
    if (project.hasProperty('benchInclude')) {
        include = ['.*' + project.benchInclude + '.*']
    }
    includeTests = true
    duplicateClassesStrategy = 'WARN'
}
jmhClasses.dependsOn clean

sourceCompatibility = 1.8
targetCompatibility = 1.8

task performanceTests {
    ext.outputDir = file("$buildDir/compilation")
    ext.dataFile = file("$buildDir/compilation-stats.csv")

    dependsOn rootProject.jar
    doLast {
        ext.outputDir.deleteDir()
        def versions = []
        dataFile.eachLine {
            def (version, mean, stdDev) = it.split(';')
            mean = Double.valueOf(mean)
            stdDev = Double.valueOf(stdDev)
            versions << [version == project.version ? 'current' : version, mean, stdDev]
        }
        versions = versions.sort { it[1] }
        def fastest = versions[0][1]
        versions.each { version, mean, stdDev ->
            print "Groovy $version Average ${mean}ms ± ${new DecimalFormat("#.##").format(stdDev)}ms "
            if (mean > fastest) {
                def diff = 100 * (mean - fastest) / fastest
                print "(${new DecimalFormat("#.##").format(diff)}% slower)"
            }
            println()
        }
        dataFile.delete()
    }
}

['1.8.9', '2.0.8', '2.1.9', '2.2.2', '2.3.10', '2.3.11', '2.4.7', 'current'].each { version ->
    def t = task "performanceTestGroovy${version.replace('.', '_')}"(type: JavaExec, dependsOn: compileTestGroovy) {
        def groovyConf = configurations.detachedConfiguration(
                dependencies.create(
                        'current' == version ? files(rootProject.jar.archivePath) : "org.codehaus.groovy:groovy:$version")
        )
        groovyConf.transitive = false
        main = 'org.apache.groovy.perf.CompilerPerformanceTest'
        classpath = groovyConf + sourceSets.test.output + configurations.stats
        jvmArgs = ['-Xms512m', '-Xmx512m', '-XX:MaxPermSize=512m']

        // configure some files to compile. This is an arbitrary set of files which can be compiled
        // independently of the version of Groovy being tested
        def testFiles = ['gls/CompilableTestSupport.groovy',
                         'groovy/beans',
                         'groovy/benchmarks',
                         'groovy/execute',
                         'groovy/gpath',
                         'groovy/io',
                         'groovy/script',
                         'groovy/time',
                         'groovy/tree',
                         'gls/syntax'].collect { "../../src/test/$it" }
        ['groovy-ant', 'groovy-test', 'groovy-jsr223'].collect(testFiles) { "../../subprojects/$it/src/test/groovy" }

        ['ackermann', 'fibo', 'random', 'spectralnorm', 'ary', 'hello', 'recursive', 'threadring',
         'binarytrees', 'mandelbrot', 'regexdna', 'wordfreq',
         'fannkuch', 'nsieve', 'revcomp'].collect(testFiles) {
            "../../benchmark/bench/${it}.groovy"
        }

        doFirst {
            def compileClassPath = [
                    '-cp',
                    groovyConf.files[0]
            ]
            rootProject.sourceSets.test.compileClasspath.files
                    .findAll { it.name.endsWith('jar') && !it.name.contains('groovy') && !it.name.contains('antlr') && !it.name.contains('asm') }
                    .collect(compileClassPath) { it.absolutePath }

            args = [
                    *testFiles,
                    *compileClassPath
            ]
        }

    }
    performanceTests.dependsOn(t)
}

compileJmhGroovy {
    classpath += compileJmhJava.classpath
}
