#!/usr/bin/env julia

# This script generates the table published at https://julialang.org/benchmarks/
# (file _includes/benchmarks.html in the JuliaLang/julialang.github.com repository)

using Compat
import Compat.Statistics
import Compat.Printf

const benchmark_order = [
    "iteration_pi_sum",
    "recursion_fibonacci",
    "recursion_quicksort",
    "parse_integers",
    "print_to_file",
    "matrix_statistics",
    "matrix_multiply",
    "userfunc_mandelbrot",
]

const versions = Dict{String, String}()
const benchmarks = Dict{String, Dict{String, Float64}}()

# Read versions.csv
for line in eachline(ARGS[1])
    lang, version = split(line, ',')
    versions[lang] = version
end

# Read benchmarks.csv
for line in eachline(ARGS[2])
    lang, bench, time_str = split(line, ',')
    times = get!(benchmarks, lang, Dict{String, Float64}())
    times[bench] = parse(Float64, time_str)
end

const labels = Dict{String, String}(
    "c"           => "C"                ,
    "julia"       => "Julia"            ,
    "lua"         => "LuaJIT"           ,
    "fortran"     => "Fortran"          ,
    "java"        => "Java"             ,
    "javascript"  => "JavaScript"       ,
    "matlab"      => "Matlab"           ,
    "python"      => "Python"           ,
    "mathematica" => "Mathe&shy;matica" ,
    "r"           => "R"                ,
    "octave"      => "Octave"           ,
    "go"          => "Go"               ,
    "rust"        => "Rust"             ,
)

# Produce the sorting order for the list of languages
function lang_by(lang::String)
    # C is placed at the start of the list
    lang == "c" ? -Inf :
    # Julia is sorted immediately after C
    @compat lang == "julia" ? -floatmax() :
    # The rest of the languages are sorted by the geometric mean of their benchmark values
    # See https://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_logarithms for details
    @compat exp(Statistics.mean(log.(collect(values(benchmarks[lang])))))
end

const language_order = sort!(collect(keys(benchmarks)), by=lang_by)

print("""
<!-- generated by JuliaLang/Microbenchmarks/bin/table.jl -->

<table class="benchmarks">
    <colgroup>
        <col class="name">
        <col class="relative" span="$(length(language_order))">
    </colgroup>
    <thead>
        <tr><th></th>
""")

for lang in language_order
    label = get(labels, lang, lang)
    println("            <th class=\"system\">$label</th>")
end

print("""
        </tr>
        <tr><td></td>
""")

for lang in language_order
    version = get(versions, lang, "???")
    println("            <th class=\"version\">$version</th>")
end

print("""
        </tr>
    </thead>
    <tbody>
""")

for benchmark in benchmark_order
    println("        <tr><th>$benchmark</th>")
    c_time = benchmarks["c"][benchmark]
    for lang in language_order
        rel_time = "n/a"
        if haskey(benchmarks[lang], benchmark)
            @compat rel_time = Printf.@sprintf "%.2f" benchmarks[lang][benchmark]/c_time
        end
        println("            <td class=\"data\">$rel_time</td>")
    end
    println("        </tr>")
end

print("""
    </tbody>
</table>

<!-- end of generated table -->
""")
