Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions benchmark/benchmarks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ if SUPPORTS_COMPOSITE_OBJECT_BENCHMARKS
) setup = (data = setup_status_registry_benchmark($nobjects))
end

include(joinpath(@__DIR__, "test-selector-resolution-benchmark.jl"))
const SELECTOR_RESOLUTION_BENCHMARK_PHYTOMERS = 2_048
SUITE[suite_name]["PSE_selector_subtree_tip_2048"] =
@benchmarkable benchmark_subtree_selector_resolution(
data,
data.tip_context,
) setup = (data = setup_subtree_selector_resolution_benchmark(
$SELECTOR_RESOLUTION_BENCHMARK_PHYTOMERS,
))
SUITE[suite_name]["PSE_selector_subtree_root_2048"] =
@benchmarkable benchmark_subtree_selector_resolution(
data,
data.root_context,
) setup = (data = setup_subtree_selector_resolution_benchmark(
$SELECTOR_RESOLUTION_BENCHMARK_PHYTOMERS,
))

include(joinpath(@__DIR__, "test-organ-lifecycle-benchmark.jl"))
for nobjects in (32, 256, 1_024)
SUITE[suite_name]["PSE_organ_adaptation_$(nobjects)"] =
Expand All @@ -76,6 +93,12 @@ if SUPPORTS_COMPOSITE_OBJECT_BENCHMARKS
) setup = (data = setup_organ_refresh_benchmark(
$nobjects,
)) evals = 1
SUITE[suite_name]["PSE_organ_status_recipe_refresh_$(nobjects)"] =
@benchmarkable benchmark_status_recipe_refresh_after_add!(
data,
) setup = (data = setup_organ_status_recipe_refresh_benchmark(
$nobjects,
)) evals = 1
SUITE[suite_name]["PSE_organ_add_refresh_$(nobjects)"] =
@benchmarkable benchmark_add_and_refresh!(
data,
Expand Down Expand Up @@ -334,6 +357,10 @@ if SUPPORTS_COMPOSITE_OBJECT_BENCHMARKS
target_count=$target_count,
))
end
SUITE[suite_name]["PSE_call_binding_signature_4096"] =
@benchmarkable benchmark_call_binding_signature(
binding,
) setup = (binding = setup_call_binding_signature_benchmark(4_096))
SUITE[suite_name]["PSE_lifecycle_small"] =
@benchmarkable benchmark_lifecycle_event(
simulation,
Expand Down
11 changes: 11 additions & 0 deletions benchmark/test-hard-call-path-benchmark.jl
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,17 @@ end

benchmark_compiled_hard_call_step(simulation) = step!(simulation)

function setup_call_binding_signature_benchmark(target_count::Int=4_096)
simulation = setup_compiled_hard_call_step(
kind=:many,
target_count=target_count,
)
return only(simulation.compiled.call_bindings)
end

Base.@noinline benchmark_call_binding_signature(binding) =
PlantSimEngine._call_bindings_signature((binding,))

function benchmark_compiled_hard_call_invocation(
context::T;
repeats=1,
Expand Down
72 changes: 72 additions & 0 deletions benchmark/test-organ-lifecycle-benchmark.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@ function PlantSimEngine.run!(
return nothing
end

PlantSimEngine.@process "organ_lifecycle_status_recipe" verbose = false

struct OrganLifecycleStatusRecipeModel <:
AbstractOrgan_Lifecycle_Status_RecipeModel end

const ORGAN_LIFECYCLE_RECIPE_OUTPUT_NAMES =
ntuple(index -> Symbol(:recipe_output_, index), 32)
const ORGAN_LIFECYCLE_RECIPE_INPUT_NAMES =
ntuple(index -> Symbol(:recipe_input_, index), 32)

PlantSimEngine.outputs_(::OrganLifecycleStatusRecipeModel) =
NamedTuple{ORGAN_LIFECYCLE_RECIPE_OUTPUT_NAMES}(
ntuple(_ -> 0.0, length(ORGAN_LIFECYCLE_RECIPE_OUTPUT_NAMES)),
)

PlantSimEngine.inputs_(::OrganLifecycleStatusRecipeModel) =
NamedTuple{ORGAN_LIFECYCLE_RECIPE_INPUT_NAMES}(
ntuple(
_ -> PlantSimEngine.Default(1.0),
length(ORGAN_LIFECYCLE_RECIPE_INPUT_NAMES),
),
)

function PlantSimEngine.run!(
::OrganLifecycleStatusRecipeModel,
status,
environment,
constants=nothing,
context=nothing,
)
return nothing
end

_organ_lifecycle_status(node) =
PlantSimEngine.Status(node=node, signal=0.0)

Expand Down Expand Up @@ -61,6 +94,20 @@ Base.@noinline function benchmark_adapt_organ_model(topology)
)
end

Base.@noinline function benchmark_adapt_organ_status_recipe_model(topology)
return PlantSimEngine.CompositeModel(
topology.root;
applications=(
PlantSimEngine.ModelSpec(
OrganLifecycleStatusRecipeModel();
name=:organ_lifecycle_status_recipe,
on=PlantSimEngine.Many(scale=:Leaf),
),
),
status=node -> PlantSimEngine.Status(node=node),
)
end

function setup_organ_lifecycle_benchmark(
nobjects::Int;
start_simulation::Bool=false,
Expand All @@ -86,6 +133,15 @@ function setup_organ_refresh_benchmark(nobjects::Int)
return merge(data, (; status))
end

function setup_organ_status_recipe_refresh_benchmark(nobjects::Int)
topology = setup_organ_topology_benchmark(nobjects)
model = benchmark_adapt_organ_status_recipe_model(topology)
PlantSimEngine.Advanced.refresh_bindings!(model)
data = merge(topology, (; model))
benchmark_add_status_recipe_organ!(data)
return data
end

Base.@noinline function benchmark_add_organ!(data)
return PlantSimEngine.add_organ!(
data.plant,
Expand All @@ -98,11 +154,27 @@ Base.@noinline function benchmark_add_organ!(data)
)
end

Base.@noinline function benchmark_add_status_recipe_organ!(data)
return PlantSimEngine.add_organ!(
data.plant,
data.model,
"+",
:Leaf,
2;
index=data.nobjects + 1,
)
end

Base.@noinline function benchmark_refresh_after_add!(data)
PlantSimEngine.Advanced.refresh_bindings!(data.model)
return data.model
end

Base.@noinline function benchmark_status_recipe_refresh_after_add!(data)
PlantSimEngine.Advanced.refresh_bindings!(data.model)
return data.model
end

Base.@noinline function benchmark_add_and_refresh!(data)
status = benchmark_add_organ!(data)
PlantSimEngine.Advanced.refresh_bindings!(data.model)
Expand Down
52 changes: 52 additions & 0 deletions benchmark/test-selector-resolution-benchmark.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using PlantSimEngine

"""
Build an XPalm-shaped chain where every phytomer owns one reproductive organ.
The newest phytomer has a two-object subtree, while the oldest phytomer spans
the complete chain, so the same selector benchmarks both the bounded
scope-first path and its registry-index fallback.
"""
function setup_subtree_selector_resolution_benchmark(nphytomers::Int=2_048)
nphytomers > 0 || throw(ArgumentError("`nphytomers` must be positive."))
objects = Object[
Object(:scene; scale=:Scene),
Object(:plant; scale=:Plant, parent=:scene),
]
previous_phytomer_id = :plant
for index in 1:nphytomers
phytomer_id = Symbol(:phytomer_, index)
male_id = Symbol(:male_, index)
push!(
objects,
Object(
phytomer_id;
scale=:Phytomer,
parent=previous_phytomer_id,
),
)
push!(
objects,
Object(male_id; scale=:Male, parent=phytomer_id),
)
previous_phytomer_id = phytomer_id
end

model = CompositeModel(objects...)
selector = Many(scale=:Male, within=Subtree())
return (
model=model,
selector=selector,
matcher=PlantSimEngine._compile_selector_matcher(model, selector),
tip_context=ObjectId(Symbol(:phytomer_, nphytomers)),
root_context=ObjectId(:phytomer_1),
)
end

Base.@noinline function benchmark_subtree_selector_resolution(data, context)
return PlantSimEngine._resolve_object_ids(
data.model,
data.selector,
data.matcher;
context=context,
)
end
24 changes: 24 additions & 0 deletions benchmark/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,26 @@ if benchmark_test_enabled("organ lifecycle benchmark API smoke")
:organ_lifecycle_leaf
].target_ids

recipe = setup_organ_status_recipe_refresh_benchmark(32)
benchmark_status_recipe_refresh_after_add!(recipe)
recipe_status = PlantSimEngine.model_status(
recipe.model,
PlantSimEngine.ObjectId(recipe.next_node_id),
)
@test propertynames(recipe_status) == (
:node,
ORGAN_LIFECYCLE_RECIPE_OUTPUT_NAMES...,
ORGAN_LIFECYCLE_RECIPE_INPUT_NAMES...,
)
@test all(
variable -> recipe_status[variable] == 0.0,
ORGAN_LIFECYCLE_RECIPE_OUTPUT_NAMES,
)
@test all(
variable -> recipe_status[variable] == 1.0,
ORGAN_LIFECYCLE_RECIPE_INPUT_NAMES,
)

combined = setup_organ_lifecycle_benchmark(32)
combined_status = benchmark_add_and_refresh!(combined)
@test PlantSimEngine.object_id(combined.model, combined_status) ==
Expand Down Expand Up @@ -858,13 +878,17 @@ if benchmark_test_enabled("internal-only benchmark suite assembly smoke")
@test haskey(suite, "PSE_status_read_write")
@test haskey(suite, "PSE_status_registry_lookup_32")
@test haskey(suite, "PSE_status_registry_sweep_1024")
@test haskey(suite, "PSE_selector_subtree_tip_2048")
@test haskey(suite, "PSE_selector_subtree_root_2048")
@test haskey(suite, "PSE_organ_adaptation_32")
@test haskey(suite, "PSE_organ_add_1024")
@test haskey(suite, "PSE_organ_refresh_1024")
@test haskey(suite, "PSE_organ_status_recipe_refresh_1024")
@test haskey(suite, "PSE_organ_add_refresh_1024")
@test haskey(suite, "PSE_organ_add_continue_1024")
@test haskey(suite, "PSE")
@test haskey(suite, "PSE_hard_calls_zero")
@test haskey(suite, "PSE_call_binding_signature_4096")
@test haskey(suite, "PSE_lifecycle_large")
@test haskey(suite, "PSE_immutable_scenario_none")
@test haskey(suite, "PSE_immutable_scenario_requests")
Expand Down
Loading
Loading