Skip to content

Commit

Permalink
Update Nanosoldier to Julia 0.6 and JSON benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
ararslan committed Nov 1, 2017
1 parent 2748fc8 commit 6f8e875
Show file tree
Hide file tree
Showing 12 changed files with 52 additions and 64 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ language: julia
os:
- linux
julia:
- release
- 0.6
- nightly
notifications:
email: false
script:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Once a `BenchmarkJob` is complete, the results are uploaded to the
has its own directory for results. This directory contains the following items:

- `report.md` is a markdown report that summarizes the job results
- `data.tar.gz` contains raw timing data in JLD format. To untar this file, run
- `data.tar.gz` contains raw timing data in JSON format. To untar this file, run
`tar -xzvf data.tar.gz`. You can analyze this data using the
[BenchmarkTools](https://github.com/JuliaCI/BaseBenchmarkReports) package.
- `logs` is a directory containing the build logs and benchmark execution logs for the job.
Expand Down
5 changes: 2 additions & 3 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
julia 0.4
BenchmarkTools 0.0.7
julia 0.6
BenchmarkTools 0.2.0
GitHub
JSON
JLD
HttpCommon
Compat 0.8.6
12 changes: 5 additions & 7 deletions src/Nanosoldier.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
module Nanosoldier

import GitHub, BenchmarkTools, JLD, JSON, HttpCommon
import GitHub, BenchmarkTools, JSON, HttpCommon

using Compat

import Compat.UTF8String

const TRIGGER = r"\@nanosoldier\s*`.*?`"
const SHA_SEPARATOR = '@'
const BRANCH_SEPARATOR = ':'
Expand All @@ -26,13 +24,13 @@ gitreset!(path) = cd(gitreset!, path)
# error handling #
##################

type NanosoldierError{E<:Exception} <: Exception
url::UTF8String
msg::UTF8String
struct NanosoldierError{E<:Exception} <: Exception
url::String
msg::String
err::E
end

NanosoldierError{E<:Exception}(msg, err::E) = NanosoldierError{E}("", msg, err)
NanosoldierError(msg, err::E) where {E<:Exception} = NanosoldierError{E}("", msg, err)

function Base.show(io::IO, err::NanosoldierError)
print(io, "NanosoldierError: ", err.msg, ": ")
Expand Down
10 changes: 5 additions & 5 deletions src/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# BuildRef #
############

type BuildRef
repo::UTF8String # the build repo
sha::UTF8String # the build + status SHA
vinfo::UTF8String # versioninfo() taken during the build
mutable struct BuildRef
repo::String # the build repo
sha::String # the build + status SHA
vinfo::String # versioninfo() taken during the build
end

BuildRef(repo, sha) = BuildRef(repo, sha, "retrieving versioninfo() failed")

function @compat(Base.:(==))(a::BuildRef, b::BuildRef)
function Base.:(==)(a::BuildRef, b::BuildRef)
return (a.repo == b.repo &&
a.sha == b.sha &&
a.vinfo == b.vinfo)
Expand Down
13 changes: 6 additions & 7 deletions src/config.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@

immutable Config
user::UTF8String # the OS username of the user running the server
struct Config
user::String # the OS username of the user running the server
nodes::Vector{Int} # the pids for the nodes on the cluster
cpus::Vector{Int} # the indices of the cpus per node
auth::GitHub.Authorization # the GitHub authorization used to post statuses/reports
secret::UTF8String # the GitHub secret used to validate webhooks
trackrepo::UTF8String # the main Julia repo tracked by the server
reportrepo::UTF8String # the repo to which result reports are posted
workdir::UTF8String # the server's work directory
secret::String # the GitHub secret used to validate webhooks
trackrepo::String # the main Julia repo tracked by the server
reportrepo::String # the repo to which result reports are posted
workdir::String # the server's work directory
testmode::Bool # if true, jobs will run as test jobs
function Config(user, nodes, cpus, auth, secret;
workdir = pwd(),
Expand Down
24 changes: 12 additions & 12 deletions src/jobs/BenchmarkJob.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ end
# BenchmarkJob #
################

type BenchmarkJob <: AbstractJob
mutable struct BenchmarkJob <: AbstractJob
submission::JobSubmission # the original submission
tagpred::UTF8String # predicate string to be fed to @tagged
tagpred::String # predicate string to be fed to @tagged
against::Nullable{BuildRef} # the comparison build (if available)
date::Dates.Date # the date of the submitted job
isdaily::Bool # is the job a daily job?
Expand Down Expand Up @@ -144,10 +144,10 @@ function retrieve_daily_data!(results, key, cfg, date)
try
run(`tar -xvzf data.tar.gz`)
datafiles = readdir(datapath)
primary_index = findfirst(fname -> endswith(fname, "_primary.jld"), datafiles)
primary_index = findfirst(fname -> endswith(fname, "_primary.json"), datafiles)
if primary_index > 0
primary_file = datafiles[primary_index]
results[key] = BenchmarkTools.load(joinpath(datapath, primary_file), "results")
results[key] = BenchmarkTools.load(joinpath(datapath, primary_file))[1]
found_previous_date = true
end
catch err
Expand Down Expand Up @@ -268,14 +268,14 @@ function execute_benchmarks!(job::BenchmarkJob, whichbuild::Symbol)
branchname = cfg.testmode ? "test" : "nanosoldier"
oldpwd = pwd()
try run(`$juliapath -e 'Pkg.clone("https://github.com/JuliaCI/BaseBenchmarks.jl")'`) end
cd(readstring(`$juliapath -e 'print(Pkg.dir("BaseBenchmarks"))'`))
cd(read(`$juliapath -e 'print(Pkg.dir("BaseBenchmarks"))'`, String))
run(`git fetch --all --quiet`)
run(`git reset --hard --quiet origin/$(branchname)`)
cd(oldpwd)

# The following code sets up a CPU shield, then spins up a new julia process on the
# shielded CPU that runs the benchmarks. The results from this new process are
# then serialized to a JLD file so that we can retrieve them.
# then serialized to a JSON file so that we can retrieve them.
#
# CPU shielding requires passwordless sudo access to `cset`. To enable this for the
# server user, run `sudo visudo` and add the following line:
Expand Down Expand Up @@ -305,7 +305,7 @@ function execute_benchmarks!(job::BenchmarkJob, whichbuild::Symbol)
benchname = string(build.sha, "_", whichbuild)
benchout = joinpath(tmplogdir(job), string(benchname, ".out"))
bencherr = joinpath(tmplogdir(job), string(benchname, ".err"))
benchresults = joinpath(tmpdatadir(job), string(benchname, ".jld"))
benchresults = joinpath(tmpdatadir(job), string(benchname, ".json"))

open(jlscriptpath, "w") do file
println(file, """
Expand All @@ -316,12 +316,12 @@ function execute_benchmarks!(job::BenchmarkJob, whichbuild::Symbol)
# move ourselves onto the first CPU in the shielded set
run(`sudo cset proc -m -p \$(getpid()) -t /user/child`)
VERSION < v"0.5.0-dev+4338" ? blas_set_num_threads(1) : BLAS.set_num_threads(1) # ensure BLAS threads do not trample each other
BLAS.set_num_threads(1) # ensure BLAS threads do not trample each other
addprocs(1) # add worker that can be used by parallel benchmarks
using BaseBenchmarks
using BenchmarkTools
using JLD
using JSON
println("LOADING SUITE...")
BaseBenchmarks.loadall!()
Expand All @@ -336,7 +336,7 @@ function execute_benchmarks!(job::BenchmarkJob, whichbuild::Symbol)
results = run(benchmarks; verbose = true)
println("SAVING RESULT...")
BenchmarkTools.save(\"$(benchresults)\", "results", results)
BenchmarkTools.save(\"$(benchresults)\", results)
println("DONE!")
Expand Down Expand Up @@ -365,12 +365,12 @@ function execute_benchmarks!(job::BenchmarkJob, whichbuild::Symbol)
run(`sudo cset set -d /user/child`)
run(`sudo cset shield --reset`)

results = BenchmarkTools.load(benchresults, "results")
results = BenchmarkTools.load(benchresults)[1]

# Get the verbose output of versioninfo for the build, throwing away
# environment information that is useless/potentially risky to expose.
try
build.vinfo = first(split(readstring(`$(juliapath) -e 'versioninfo(true)'`), "Environment"))
build.vinfo = first(split(read(`$(juliapath) -e 'versioninfo(true)'`, String), "Environment"))
catch err
build.vinfo = string("retrieving versioninfo() failed: ", sprint(showerror, err))
end
Expand Down
2 changes: 1 addition & 1 deletion src/jobs/jobs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# - `Base.run(job::J)`: execute `job`
# - `Base.summary(job::J)`: a short string identifying/describing `job`

abstract AbstractJob
abstract type AbstractJob end

reply_status(job::AbstractJob, args...; kwargs...) = reply_status(submission(job), args...; kwargs...)
reply_comment(job::AbstractJob, args...; kwargs...) = reply_comment(submission(job), args...; kwargs...)
Expand Down
3 changes: 1 addition & 2 deletions src/server.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

immutable Server
struct Server
config::Config
jobs::Vector{AbstractJob}
listener::git.luolix.topmentListener
Expand Down
30 changes: 11 additions & 19 deletions src/submission.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@

type JobSubmission
mutable struct JobSubmission
config::Config
build::BuildRef
statussha::UTF8String # the SHA to send statuses to (since `build` can mutate)
url::UTF8String # the URL linking to the triggering comment
statussha::String # the SHA to send statuses to (since `build` can mutate)
url::String # the URL linking to the triggering comment
fromkind::Symbol # `:pr`, `:review`, or `:commit`?
prnumber::Nullable{Int} # the job's PR number, if `fromkind` is `:pr` or `:review`
func::UTF8String
args::Vector{UTF8String}
kwargs::Dict{Symbol,UTF8String}
func::String
args::Vector{String}
kwargs::Dict{Symbol,String}
end

function JobSubmission(config::Config, event::GitHub.WebhookEvent, submission_string)
Expand All @@ -21,7 +20,7 @@ function JobSubmission(config::Config, event::GitHub.WebhookEvent, submission_st
end
end

function @compat(Base.:(==))(a::JobSubmission, b::JobSubmission)
function Base.:(==)(a::JobSubmission, b::JobSubmission)
if isnull(a.prnumber) == isnull(b.prnumber)
same_prnumber = isnull(a.prnumber) ? true : (get(a.prnumber) == get(b.prnumber))
return (same_prnumber && a.config == b.config && a.build == b.build &&
Expand Down Expand Up @@ -77,22 +76,15 @@ function parse_event(config::Config, event::GitHub.WebhookEvent)
end

# `x` can only be Expr, Symbol, QuoteNode, T<:Number, or T<:AbstractString
function phrase_argument{T}(x::T)
if T <: Expr || T <: Symbol || T <: QuoteNode
return UTF8String(string(x))
elseif T <: AbstractString || T <: Number
return UTF8String(repr(x))
else
error("invalid argument type $(typeof(x))")
end
end
phrase_argument(x::Union{Expr, Symbol, QuoteNode}) = string(x)
phrase_argument(x::Union{AbstractString, Number}) = repr(x)

function parse_submission_string(submission_string)
fncall = match(r"`.*?`", submission_string).match[2:end-1]
argind = searchindex(fncall, "(")
name = fncall[1:(argind - 1)]
parsed_args = parse(replace(fncall[argind:end], ";", ","))
args, kwargs = Vector{UTF8String}(), Dict{Symbol,UTF8String}()
args, kwargs = Vector{String}(), Dict{Symbol,String}()
if isa(parsed_args, Expr) && parsed_args.head == :tuple
started_kwargs = false
for x in parsed_args.args
Expand Down Expand Up @@ -132,7 +124,7 @@ function upload_report_repo!(sub::JobSubmission, markdownpath, message)
sha = cd(reportdir(cfg)) do
run(`git add -A`)
run(`git commit -m $message`)
headsha = chomp(readstring(`git rev-parse HEAD`))
headsha = readchomp(`git rev-parse HEAD`)
run(`git pull -X ours`)
run(`git push`)
return headsha
Expand Down
8 changes: 4 additions & 4 deletions test/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ benchmark results remained invariant between builds).

| ID | time ratio | memory ratio |
|----|------------|--------------|
| `["g","h","z"]` | 1.00 (60%) | 5.00 (27%) :x: |
| `["g","h",("y",1)]` | 2.00 (5%) :x: | 0.00 (3%) :white_check_mark: |
| `["g","h",("y",2)]` | 0.50 (5%) :white_check_mark: | 1.00 (1%) |
| `["g", "h", "z"]` | 1.00 (60%) | 5.00 (27%) :x: |
| `["g", "h", ("y", 1)]` | 2.00 (5%) :x: | 0.00 (3%) :white_check_mark: |
| `["g", "h", ("y", 2)]` | 0.50 (5%) :white_check_mark: | 1.00 (1%) |

## Benchmark Group List

Here's a list of all the benchmark groups executed by this job:

- `["g","h"]`
- `["g", "h"]`

## Version Info

Expand Down
4 changes: 2 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import GitHub
using Nanosoldier, Base.Test, Compat, BenchmarkTools
using Nanosoldier, Compat, Compat.Test, BenchmarkTools
using Nanosoldier: BuildRef, JobSubmission, Config, BenchmarkJob, AbstractJob
using BenchmarkTools: TrialEstimate, Parameters

Expand Down Expand Up @@ -140,6 +140,6 @@ results["judged"] = BenchmarkTools.judge(results["primary"], results["against"])
@test begin
mdpath = joinpath(dirname(@__FILE__), "report.md")
open(mdpath, "r") do file
readstring(file) == sprint(io -> Nanosoldier.printreport(io, job, results))
read(file, String) == sprint(io -> Nanosoldier.printreport(io, job, results))
end
end

0 comments on commit 6f8e875

Please sign in to comment.