Skip to content

Commit 425b440

Browse files
authored
Merge pull request #219 from JuliaControl/test_bench
bench: added allocation benchmarks on CI
2 parents b3c8b0f + 9bee990 commit 425b440

File tree

7 files changed

+149
-93
lines changed

7 files changed

+149
-93
lines changed

.github/workflows/Benchmark.yml

Lines changed: 0 additions & 38 deletions
This file was deleted.

.github/workflows/benchmark.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Benchmark this PR
2+
on:
3+
pull_request_target:
4+
branches: [ main ]
5+
permissions:
6+
pull-requests: write # needed to post comments
7+
jobs:
8+
bench:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: MilesCranmer/AirspeedVelocity.jl@action-v1
12+
with:
13+
julia-version: '1'

benchmark/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[deps]
22
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
3+
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
34
DAQP = "c47d62df-3981-49c8-9651-128b1cd08617"
45
FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41"
56
Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"

benchmark/benchmarks.jl

Lines changed: 135 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,141 @@
11
using BenchmarkTools
2-
using Random
2+
using ModelPredictiveControl, ControlSystemsBase, LinearAlgebra
3+
4+
Ts = 400.0
5+
sys = [ tf(1.90,[1800.0,1]) tf(1.90,[1800.0,1]) tf(1.90,[1800.0,1]);
6+
tf(-0.74,[800.0,1]) tf(0.74,[800.0,1]) tf(-0.74,[800.0,1]) ]
37

48
const SUITE = BenchmarkGroup()
59

6-
SUITE["utf8"] = BenchmarkGroup(["string", "unicode"])
7-
teststr = String(join(rand(MersenneTwister(1), 'a':'d', 10^4)))
8-
SUITE["utf8"]["replace"] = @benchmarkable replace($teststr, "a" => "b")
9-
SUITE["utf8"]["join"] = @benchmarkable join($teststr, $teststr)
10-
SUITE["utf8"]["plots"] = BenchmarkGroup()
11-
12-
SUITE["trigonometry"] = BenchmarkGroup(["math", "triangles"])
13-
SUITE["trigonometry"]["circular"] = BenchmarkGroup()
14-
for f in (sin, cos, tan)
15-
for x in (0.0, pi)
16-
SUITE["trigonometry"]["circular"][string(f), x] = @benchmarkable ($f)($x)
17-
end
10+
## ==================================================================================
11+
## ================== SimModel benchmarks ===========================================
12+
## ==================================================================================
13+
linmodel = setop!(LinModel(sys, Ts, i_d=[3]), uop=[10, 50], yop=[50, 30], dop=[5])
14+
function f!(ẋ, x, u, d, p)
15+
mul!(ẋ, p.A, x)
16+
mul!(ẋ, p.Bu, u, 1, 1)
17+
mul!(ẋ, p.Bd, d, 1, 1)
18+
return nothing
19+
end
20+
function h!(y, x, d, p)
21+
mul!(y, p.C, x)
22+
mul!(y, p.Dd, d, 1, 1)
23+
return nothing
1824
end
25+
nonlinmodel = NonLinModel(f!, h!, Ts, 2, 4, 2, 1, p=linmodel, solver=nothing)
26+
nonlinmodel = setop!(nonlinmodel, uop=[10, 50], yop=[50, 30], dop=[5])
27+
u, d, y = [10, 50], [5], [50, 30]
28+
29+
SUITE["SimModel"]["allocation"] = BenchmarkGroup(["allocation"])
30+
SUITE["SimModel"]["allocation"]["LinModel_updatestate!"] = @benchmarkable(
31+
updatestate!($linmodel, $u, $d),
32+
samples=1
33+
)
34+
SUITE["SimModel"]["allocation"]["LinModel_evaloutput"] = @benchmarkable(
35+
evaloutput($linmodel, $d),
36+
samples=1
37+
)
38+
SUITE["SimModel"]["allocation"]["NonLinModel_updatestate!"] = @benchmarkable(
39+
updatestate!($nonlinmodel, $u, $d),
40+
samples=1
41+
)
42+
SUITE["SimModel"]["allocation"]["NonLinModel_evaloutput"] = @benchmarkable(
43+
evaloutput($nonlinmodel, $d),
44+
samples=1
45+
)
46+
47+
SUITE["SimModel"]["allocation"]["NonLinModel_linearize!"] = @benchmarkable(
48+
linearize!($linmodel, $nonlinmodel),
49+
samples=1
50+
)
51+
52+
## ==================================================================================
53+
## ================== StateEstimator benchmarks =====================================
54+
## ==================================================================================
55+
skf = SteadyKalmanFilter(linmodel)
56+
SUITE["StateEstimator"]["allocation"] = BenchmarkGroup(["allocation"])
57+
SUITE["StateEstimator"]["allocation"]["SteadyKalmanFilter_preparestate!"] = @benchmarkable(
58+
preparestate!($skf, $y, $d),
59+
samples=1
60+
)
61+
SUITE["StateEstimator"]["allocation"]["SteadyKalmanFilter_updatestate!"] = @benchmarkable(
62+
updatestate!($skf, $u, $y, $d),
63+
setup=preparestate!($skf, $y, $d),
64+
samples=1
65+
)
66+
SUITE["StateEstimator"]["allocation"]["SteadyKalmanFilter_evaloutput"] = @benchmarkable(
67+
evaloutput($skf, $d),
68+
setup=preparestate!($skf, $y, $d),
69+
samples=1
70+
)
71+
72+
kf = KalmanFilter(linmodel, nint_u=[1, 1], direct=false)
73+
SUITE["StateEstimator"]["allocation"]["KalmanFilter_preparestate!"] = @benchmarkable(
74+
preparestate!($kf, $y, $d),
75+
samples=1
76+
)
77+
SUITE["StateEstimator"]["allocation"]["KalmanFilter_updatestate!"] = @benchmarkable(
78+
updatestate!($kf, $u, $y, $d),
79+
setup=preparestate!($kf, $y, $d),
80+
samples=1
81+
)
82+
83+
lo = Luenberger(linmodel, nint_u=[1, 1])
84+
#SUITE["StateEstimator"]["allocation"]["Luenberger_preparestate!"] = @benchmarkable(
85+
# preparestate!($lo, $y, $d),
86+
# samples=1
87+
#)
88+
SUITE["StateEstimator"]["allocation"]["Luenberger_updatestate!"] = @benchmarkable(
89+
updatestate!($lo, $u, $y, $d),
90+
setup=preparestate!($lo, $y, $d),
91+
samples=1
92+
)
93+
94+
im = InternalModel(nonlinmodel)
95+
SUITE["StateEstimator"]["allocation"]["InternalModel_preparestate!"] = @benchmarkable(
96+
preparestate!($im, $y, $d),
97+
samples=1
98+
)
99+
SUITE["StateEstimator"]["allocation"]["InternalModel_updatestate!"] = @benchmarkable(
100+
updatestate!($im, $u, $y, $d),
101+
setup=preparestate!($im, $y, $d),
102+
samples=1
103+
)
104+
105+
ukf = UnscentedKalmanFilter(nonlinmodel)
106+
SUITE["StateEstimator"]["allocation"]["UnscentedKalmanFilter_preparestate!"] = @benchmarkable(
107+
preparestate!($ukf, $y, $d),
108+
samples=1
109+
)
110+
SUITE["StateEstimator"]["allocation"]["UnscentedKalmanFilter_updatestate!"] = @benchmarkable(
111+
updatestate!($ukf, $u, $y, $d),
112+
setup=preparestate!($ukf, $y, $d),
113+
samples=1
114+
)
115+
SUITE["StateEstimator"]["allocation"]["UnscentedKalmanFilter_evaloutput"] = @benchmarkable(
116+
evaloutput($ukf, $d),
117+
setup=preparestate!($ukf, $y, $d),
118+
samples=1
119+
)
120+
121+
ekf = ExtendedKalmanFilter(linmodel, nint_u=[1, 1], direct=false)
122+
SUITE["StateEstimator"]["allocation"]["ExtendedKalmanFilter_preparestate!"] = @benchmarkable(
123+
preparestate!($ekf, $y, $d),
124+
samples=1
125+
)
126+
SUITE["StateEstimator"]["allocation"]["ExtendedKalmanFilter_updatestate!"] = @benchmarkable(
127+
updatestate!($ekf, $u, $y, $d),
128+
setup=preparestate!($ekf, $y, $d),
129+
samples=1
130+
)
19131

20-
SUITE["trigonometry"]["hyperbolic"] = BenchmarkGroup()
21-
for f in (sin, cos, tan)
22-
for x in (0.0, pi)
23-
SUITE["trigonometry"]["hyperbolic"][string(f), x] = @benchmarkable ($f)($x)
24-
end
25-
end
132+
## ==================================================================================
133+
## ================== PredictiveController benchmarks ===============================
134+
## ==================================================================================
135+
empc = ExplicitMPC(linmodel, Mwt=[1, 1], Nwt=[0.1, 0.1], Lwt=[0.1, 0.1])
136+
SUITE["PredictiveController"]["allocation"] = BenchmarkGroup(["allocation"])
137+
SUITE["PredictiveController"]["allocation"]["ExplicitMPC_moveinput!"] = @benchmarkable(
138+
moveinput!($empc, $y, $d),
139+
setup=preparestate!($empc, $y, $d),
140+
samples=1
141+
)

test/1_test_sim_model.jl

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,9 @@ end
108108
u, d = [10, 50], Float64[]
109109
@test updatestate!(linmodel1, u) zeros(2)
110110
@test updatestate!(linmodel1, u, d) zeros(2)
111-
@test_skip @allocations(updatestate!(linmodel1, u)) == 0
112111
@test linmodel1.x0 zeros(2)
113112
@test evaloutput(linmodel1) linmodel1() [50,30]
114113
@test evaloutput(linmodel1, Float64[]) linmodel1(Float64[]) [50,30]
115-
@test_skip @allocations(evaloutput(linmodel1)) == 0
116114
x = initstate!(linmodel1, [10, 60])
117115
@test evaloutput(linmodel1) [50 + 19.0, 30 + 7.4]
118116
@test preparestate!(linmodel1) x # new method
@@ -283,11 +281,9 @@ end
283281
u, d = zeros(2), Float64[]
284282
@test updatestate!(nonlinmodel, u) zeros(2)
285283
@test updatestate!(nonlinmodel, u, d) zeros(2)
286-
@test_skip @allocations(updatestate!(nonlinmodel, u)) == 0
287284
@test nonlinmodel.x0 zeros(2)
288285
@test evaloutput(nonlinmodel) nonlinmodel() zeros(2)
289286
@test evaloutput(nonlinmodel, d) nonlinmodel(Float64[]) zeros(2)
290-
@test_skip @allocations(evaloutput(nonlinmodel)) == 0
291287

292288
x = initstate!(nonlinmodel, [0, 10]) # do nothing for NonLinModel
293289
@test evaloutput(nonlinmodel) [0, 0]
@@ -375,19 +371,6 @@ end
375371
h2!(y, x, _, _) = (y .= x)
376372
nonlinmodel4 = NonLinModel(f2!,h2!,Ts,1,1,1,0,solver=nothing,jacobian=AutoFiniteDiff())
377373
@test_nowarn linearize(nonlinmodel4, x=[1], u=[2])
378-
379-
function f3!(xnext, x, u, d, _)
380-
xnext .= x.*u .+ x.*d
381-
end
382-
function h3!(y, x, d, _)
383-
y .= x.*d
384-
end
385-
nonlinmodel4 = NonLinModel(f3!, h3!, Ts, 1, 1, 1, 1, solver=nothing)
386-
linmodel4 = linearize(nonlinmodel4; x, u, d)
387-
# return nothing (see this issue : https://github.com/JuliaLang/julia/issues/51112):
388-
linearize2!(linmodel, model) = (linearize!(linmodel, model); nothing)
389-
linearize2!(linmodel4, nonlinmodel4)
390-
@test_skip @allocations(linearize2!(linmodel4, nonlinmodel4)) == 0
391374
end
392375

393376
@testitem "NonLinModel real time simulations" setup=[SetupMPCtests] begin

test/2_test_state_estim.jl

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,9 @@ end
7171
preparestate!(kalmanfilter1, y)
7272
@test updatestate!(kalmanfilter1, u, y, d) zeros(4)
7373
@test kalmanfilter1.x̂0 zeros(4)
74-
@test_skip @allocations(preparestate!(kalmanfilter1, y)) == 0
75-
@test_skip @allocations(updatestate!(kalmanfilter1, u, y)) == 0
7674
preparestate!(kalmanfilter1, y)
7775
@test evaloutput(kalmanfilter1) kalmanfilter1() [50, 30]
7876
@test evaloutput(kalmanfilter1, d) kalmanfilter1(d) [50, 30]
79-
@test_skip @allocations(evaloutput(kalmanfilter1, d)) == 0
8077
@test initstate!(kalmanfilter1, [10, 50], [50, 30+1]) [zeros(3); [1]]
8178
linmodel2 = LinModel(append(tf(1, [1, 0]), tf(2, [10, 1])), 1.0)
8279
kalmanfilter2 = SteadyKalmanFilter(linmodel2, nint_u=[1, 1], direct=false)
@@ -205,12 +202,9 @@ end
205202
preparestate!(kalmanfilter1, y)
206203
@test updatestate!(kalmanfilter1, u, y, d) zeros(4)
207204
@test kalmanfilter1.x̂0 zeros(4)
208-
@test_skip @allocations(preparestate!(kalmanfilter1, y)) == 0
209-
@test_skip @allocations(updatestate!(kalmanfilter1, u, y)) == 0
210205
preparestate!(kalmanfilter1, y)
211206
@test evaloutput(kalmanfilter1) kalmanfilter1() [50, 30]
212207
@test evaloutput(kalmanfilter1, d) kalmanfilter1(d) [50, 30]
213-
@test_skip @allocations(evaloutput(kalmanfilter1, d)) == 0
214208
@test initstate!(kalmanfilter1, [10, 50], [50, 30+1]) [zeros(3); [1]]
215209
setstate!(kalmanfilter1, [1,2,3,4], diagm(.1:.1:.4))
216210
@test kalmanfilter1.x̂0 [1,2,3,4]
@@ -326,12 +320,9 @@ end
326320
preparestate!(lo1, y)
327321
@test updatestate!(lo1, u, y, d) zeros(4)
328322
@test lo1.x̂0 zeros(4)
329-
@test_skip @allocations(preparestate!(lo1, y)) == 0
330-
@test_skip @allocations(updatestate!(lo1, u, y)) == 0
331323
preparestate!(lo1, y)
332324
@test evaloutput(lo1) lo1() [50, 30]
333325
@test evaloutput(lo1, d) lo1(d) [50, 30]
334-
@test_skip @allocations(evaloutput(lo1, d)) == 0
335326
@test initstate!(lo1, [10, 50], [50, 30+1]) [zeros(3); [1]]
336327
setstate!(lo1, [1,2,3,4])
337328
@test lo1.x̂0 [1,2,3,4]
@@ -457,11 +448,8 @@ end
457448
@test updatestate!(internalmodel1, u, y, d) zeros(2)
458449
@test internalmodel1.x̂d internalmodel1.x̂0 zeros(2)
459450
@test internalmodel1.x̂s ones(2)
460-
@test_skip @allocations(preparestate!(internalmodel1, y)) == 0
461-
@test_skip @allocations(updatestate!(internalmodel1, u, y)) == 0
462451
preparestate!(internalmodel1, y)
463452
@test evaloutput(internalmodel1, d) [51,31]
464-
@test_skip @allocations(evaloutput(internalmodel1, d)) == 0
465453
@test initstate!(internalmodel1, [10, 50], [50, 30]) zeros(2)
466454
@test internalmodel1.x̂s zeros(2)
467455
setstate!(internalmodel1, [1,2])
@@ -593,12 +581,9 @@ end
593581
preparestate!(ukf1, y)
594582
@test updatestate!(ukf1, u, y, d) zeros(4) atol=1e-9
595583
@test ukf1.x̂0 zeros(4) atol=1e-9
596-
@test_skip @allocations(preparestate!(ukf1, y)) == 0
597-
@test_skip @allocations(updatestate!(ukf1, u, y)) == 0
598584
preparestate!(ukf1, y)
599585
@test evaloutput(ukf1) ukf1() [50, 30]
600586
@test evaloutput(ukf1, d) ukf1(d) [50, 30]
601-
@test_skip @allocations(evaloutput(ukf1, d)) == 0
602587
@test initstate!(ukf1, [10, 50], [50, 30+1]) zeros(4) atol=1e-9
603588
setstate!(ukf1, [1,2,3,4], diagm(.1:.1:.4))
604589
@test ukf1.x̂0 [1,2,3,4]
@@ -752,12 +737,9 @@ end
752737
preparestate!(ekf1, y)
753738
@test updatestate!(ekf1, u, y, d) zeros(4) atol=1e-9
754739
@test ekf1.x̂0 zeros(4) atol=1e-9
755-
@test_skip @allocations(preparestate!(ekf1, y)) == 0
756-
@test_skip @allocations(updatestate!(ekf1, u, y)) == 0
757740
preparestate!(ekf1, y)
758741
@test evaloutput(ekf1) ekf1() [50, 30]
759742
@test evaloutput(ekf1, d) ekf1(d) [50, 30]
760-
@test_skip @allocations(evaloutput(ekf1, d)) == 0
761743
@test initstate!(ekf1, [10, 50], [50, 30+1]) zeros(4);
762744
setstate!(ekf1, [1,2,3,4], diagm(.1:.1:.4))
763745
@test ekf1.x̂0 [1,2,3,4]

test/3_test_predictive_control.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,6 @@ end
496496
@test u [1] atol=1e-2
497497
u = mpc1(r)
498498
@test u [1] atol=1e-2
499-
@test_skip @allocations(moveinput!(mpc1, r)) == 0
500499
info = getinfo(mpc1)
501500
@test info[:u] u
502501
@test info[:Ŷ][end] r[1] atol=1e-2

0 commit comments

Comments
 (0)