Skip to content

Commit 04963d9

Browse files
authored
Merge pull request #129 from VirtualPlantLab/benchmarks-github-action
Benchmark tracking via Github action
2 parents 0827567 + 0804e74 commit 04963d9

10 files changed

Lines changed: 410 additions & 205 deletions

.github/workflows/CI.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ jobs:
4040
- uses: julia-actions/cache@v2
4141
- uses: julia-actions/julia-buildpkg@v1
4242
- uses: julia-actions/julia-runtest@v1
43+
env:
44+
JULIA_NUM_THREADS: 4
4345
- uses: julia-actions/julia-processcoverage@v1
4446
- uses: codecov/codecov-action@v5
4547
with:
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: BenchmarksAndDownstream
2+
on:
3+
push:
4+
branches:
5+
- main
6+
- benchmarks-github-action
7+
tags: "*"
8+
workflow-dispatch:
9+
permissions:
10+
# deployments permission to deploy GitHub pages website
11+
deployments: write
12+
# contents permission to update benchmark contents in gh-pages branch
13+
contents: write
14+
jobs:
15+
test:
16+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
17+
runs-on: ${{ matrix.os }}
18+
timeout-minutes: 60
19+
env:
20+
GROUP: ${{ matrix.package.group }}
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
version:
25+
- "1"
26+
os:
27+
- ubuntu-latest
28+
- macOS-latest
29+
- windows-latest
30+
arch:
31+
- x64
32+
package:
33+
- {user: VEZY, repo: PlantSimEngine.jl, group: Downstream}
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: julia-actions/setup-julia@v2
37+
with:
38+
version: ${{ matrix.version }}
39+
arch: ${{ matrix.arch }}
40+
# TODO handle breaking changes the way downstream tests do ?
41+
# NOTE : manifest toml file is removed otherwise git whines about untracked changes when switching branches for the gh-pages commit
42+
- name: Run benchmarks
43+
run: |
44+
cd test/downstream
45+
julia --project --threads 4 --color=yes -e '
46+
using Pkg;
47+
Pkg.instantiate();
48+
include("test-all-benchmarks.jl")'
49+
rm Manifest.toml
50+
- name: Store benchmark result
51+
uses: benchmark-action/github-action-benchmark@v1
52+
with:
53+
name: Julia benchmark result
54+
tool: 'julia'
55+
output-file-path: ${{ github.workspace }}/test/downstream/output.json
56+
# Use personal access token instead of GITHUB_TOKEN due to https://github.community/t/github-action-not-triggering-gh-pages-upon-push/16096
57+
github-token: ${{ secrets.GITHUB_TOKEN }}
58+
auto-push: true
59+
# Show alert with commit comment on detecting possible performance regression
60+
alert-threshold: '130%'
61+
comment-on-alert: true
62+
fail-on-alert: true
63+
alert-comment-cc-users: '@Samuel-AMAP, @VEZY'
64+
65+
- uses: julia-actions/julia-processcoverage@v1
66+
- uses: codecov/codecov-action@v5
67+
with:
68+
token: ${{ secrets.CODECOV_TOKEN }}
69+
files: lcov.info
70+
fail_ci_if_error: false

test/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
[deps]
22
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3+
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
34
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
45
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
6+
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
57
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
68
MultiScaleTreeGraph = "dd4a991b-8a45-4075-bede-262ee62d5583"
79
PlantMeteo = "4630fe09-e0fb-4da5-a846-781cb73437b6"
10+
PlantSimEngine = "9a576370-710b-4269-adf9-4f603a9c6423"
811
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
912
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
1013
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

test/downstream/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
33
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
44
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
5+
MultiScaleTreeGraph = "dd4a991b-8a45-4075-bede-262ee62d5583"
56
PlantBiophysics = "7ae8fcfa-76ad-4ec6-9ea7-5f8f5e2d6ec9"
67
PlantMeteo = "4630fe09-e0fb-4da5-a846-781cb73437b6"
8+
PlantSimEngine = "9a576370-710b-4269-adf9-4f603a9c6423"
79
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
810
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
911
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#############################################
2+
### Simulation with many organs in the MTG (but only a few different types of organs)
3+
4+
5+
PlantSimEngine.@process "organ_crazy_emergence" verbose = false
6+
7+
"""
8+
ToyInternodeCrazyEmergence(;init_TT=0.0, TT_emergence = 300)
9+
10+
Computes the organ emergence based on cumulated thermal time since last event.
11+
"""
12+
struct ToyInternodeCrazyEmergence <: AbstractOrgan_Crazy_EmergenceModel
13+
TT_emergence::Float64
14+
end
15+
16+
ToyInternodeCrazyEmergence(; TT_emergence=300.0) = ToyInternodeCrazyEmergence(TT_emergence)
17+
18+
PlantSimEngine.inputs_(m::ToyInternodeCrazyEmergence) = (TT_cu=-Inf,)
19+
PlantSimEngine.outputs_(m::ToyInternodeCrazyEmergence) = (TT_cu_emergence=0.0,)
20+
21+
function PlantSimEngine.run!(m::ToyInternodeCrazyEmergence, models, status, meteo, constants=nothing, sim_object=nothing)
22+
23+
#root = get_root(status.node)
24+
25+
#if nleaves(root) > 10000
26+
# return nothing
27+
#end
28+
29+
if length(MultiScaleTreeGraph.children(status.node)) == 1 && status.TT_cu - status.TT_cu_emergence >= m.TT_emergence
30+
31+
status_new_internode = add_organ!(status.node, sim_object, "<", "Internode", 2, index=1)
32+
add_organ!(status_new_internode.node, sim_object, "+", "Leaf", 2, index=1)
33+
status_new_internode.TT_cu_emergence = status.TT_cu
34+
elseif (length(MultiScaleTreeGraph.children(status.node)) >= 2 && length(MultiScaleTreeGraph.children(status.node)) < 7) && status.TT_cu - status.TT_cu_emergence >= m.TT_emergence
35+
status_new_internode = add_organ!(status.node, sim_object, "<", "Internode", 2, index=1)
36+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=4)
37+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=5)
38+
status_new_internode.TT_cu_emergence = status.TT_cu
39+
elseif (length(MultiScaleTreeGraph.children(status.node)) >= 7 && length(MultiScaleTreeGraph.children(status.node)) < 30) && status.TT_cu - status.TT_cu_emergence >= m.TT_emergence
40+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=6)
41+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=7)
42+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=8)
43+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=9)
44+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=10)
45+
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=11)
46+
47+
end
48+
49+
return nothing
50+
end
51+
52+
53+
# Wrapped this into a function so that it doesn't plague the benchmark with variables on a global scope
54+
#@check_allocs
55+
function do_benchmark_on_heavier_mtg()
56+
mtg = import_mtg_example();
57+
58+
# Example meteo, 365 timesteps :
59+
meteo_day = read_weather(joinpath(pkgdir(PlantSimEngine), "examples/meteo_day.csv"), duration=Day)
60+
61+
#similar to the mtg growth test but with a much lower emergence threshold
62+
mapping = Dict(
63+
"Scene" => ToyDegreeDaysCumulModel(),
64+
"Plant" => (
65+
MultiScaleModel(
66+
model=ToyLAIModel(),
67+
mapping=[
68+
:TT_cu => "Scene",
69+
],
70+
),
71+
PlantSimEngine.Examples.Beer(0.6),
72+
MultiScaleModel(
73+
model=ToyCAllocationModel(),
74+
mapping=[
75+
:carbon_assimilation => ["Leaf"],
76+
:carbon_demand => ["Leaf", "Internode"],
77+
:carbon_allocation => ["Leaf", "Internode"]
78+
],
79+
),
80+
MultiScaleModel(
81+
model=ToyPlantRmModel(),
82+
mapping=[:Rm_organs => ["Leaf" => :Rm, "Internode" => :Rm],],
83+
),
84+
),
85+
"Internode" => (
86+
MultiScaleModel(
87+
model=ToyCDemandModel(optimal_biomass=10.0, development_duration=200.0),
88+
mapping=[:TT => "Scene",],
89+
),
90+
MultiScaleModel(
91+
model=ToyInternodeCrazyEmergence(TT_emergence=1.0),
92+
mapping=[:TT_cu => "Scene"],
93+
),
94+
ToyMaintenanceRespirationModel(1.5, 0.06, 25.0, 0.6, 0.004),
95+
Status(carbon_biomass=1.0)
96+
),
97+
"Leaf" => (
98+
MultiScaleModel(
99+
model=ToyAssimModel(),
100+
mapping=[:soil_water_content => "Soil", :aPPFD => "Plant"],
101+
),
102+
MultiScaleModel(
103+
model=ToyCDemandModel(optimal_biomass=10.0, development_duration=200.0),
104+
mapping=[:TT => "Scene",],
105+
),
106+
ToyMaintenanceRespirationModel(2.1, 0.06, 25.0, 1.0, 0.025),
107+
Status(carbon_biomass=1.0)
108+
),
109+
"Soil" => (
110+
ToySoilWaterModel(),
111+
),
112+
)
113+
114+
out_vars = Dict(
115+
"Leaf" => (:carbon_assimilation, :carbon_demand, :soil_water_content, :carbon_allocation),
116+
"Internode" => (:carbon_allocation, :TT_cu_emergence),
117+
"Plant" => (:carbon_allocation,),
118+
"Soil" => (:soil_water_content,),
119+
)
120+
121+
out = run!(mtg, mapping, meteo_day, outputs=out_vars, executor=SequentialEx());
122+
end
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using Pkg
2+
Pkg.activate(dirname(@__FILE__))
3+
Pkg.develop(PackageSpec(path=dirname(dirname(@__DIR__))))
4+
Pkg.instantiate()
5+
6+
using PlantSimEngine
7+
using PlantSimEngine.Examples
8+
using DataFrames, CSV
9+
using MultiScaleTreeGraph
10+
using PlantMeteo, Statistics
11+
12+
# Include the example dummy processes:
13+
using PlantSimEngine.Examples
14+
15+
using BenchmarkTools
16+
using Dates
17+
18+
suite_name = "bench_"
19+
20+
if Sys.iswindows()
21+
suite_name = suite_name * "windows"
22+
elseif Sys.isapple()
23+
suite_name = suite_name * "mac"
24+
elseif Sys.islinux()
25+
suite_name = suite_name * "linux"
26+
end
27+
suite = BenchmarkGroup()
28+
suite[suite_name] = BenchmarkGroup(["PSE", "PBP"])#, "XPalm"])
29+
30+
# "PSE benchmark"
31+
include("test-PSE-benchmark.jl")
32+
suite[suite_name]["PSE"] = @benchmarkable do_benchmark_on_heavier_mtg()
33+
34+
# "PBP benchmark"
35+
include("test-plantbiophysics.jl")
36+
suite[suite_name]["PBP"] = @benchmarkable benchmark_plantbiophysics()
37+
38+
leaf, meteo = setup_benchmark_plantbiophysics_multitimestep()
39+
suite[suite_name]["PBP_multiple_timesteps_MT"] = @benchmarkable benchmark_plantbiophysics_multitimestep_MT($leaf, $meteo)
40+
suite[suite_name]["PBP_multiple_timesteps_ST"] = @benchmarkable benchmark_plantbiophysics_multitimestep_ST($leaf, $meteo)
41+
42+
# "XPalm benchmark"
43+
#include("test-xpalm.jl")
44+
#suite[suite_name]["XPalm"] = @benchmarkable xpalm_default_param_run() seconds = 120
45+
46+
tune!(suite)
47+
results = run(suite, verbose=true)
48+
BenchmarkTools.save(dirname(@__FILE__) * "/output.json", median(results))

0 commit comments

Comments
 (0)