Explorar el Código

Profiling Important functions

Snej69420 hace 5 meses
padre
commit
4636d88f75
Se han modificado 4 ficheros con 106 adiciones y 83 borrados
  1. 2 2
      Manifest.toml
  2. 2 0
      Project.toml
  3. 67 44
      src/AtomicDEVS.jl
  4. 35 37
      src/CoupledDEVS.jl

+ 2 - 2
Manifest.toml

@@ -2,7 +2,7 @@
 
 julia_version = "1.12.5"
 manifest_format = "2.0"
-project_hash = "3eaafecfbb2d7d25f95ed19f70dbaa863e0efabc"
+project_hash = "a73af7a22a2484ade5c46b10bf5f4e0bc3ada032"
 
 [[deps.AbstractTrees]]
 git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177"
@@ -172,7 +172,7 @@ uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
 version = "4.1.1"
 
 [[deps.DEVS2Agents]]
-deps = ["Agents", "ArgParse", "BenchmarkTools", "CSV", "DataFrames", "DataStructures", "DelimitedFiles", "FunctionWrappers", "InteractiveUtils", "Printf", "Test", "TimerOutputs"]
+deps = ["Agents", "ArgParse", "BenchmarkTools", "CSV", "DataFrames", "DataStructures", "DelimitedFiles", "FunctionWrappers", "InteractiveUtils", "Printf", "Test"]
 path = "."
 uuid = "073a0784-fe80-4c04-b3c3-fb0686668e26"
 version = "0.1.0"

+ 2 - 0
Project.toml

@@ -15,6 +15,7 @@ FunctionWrappers = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e"
 InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
 Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
 Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
 
 [compat]
 BenchmarkTools = "1.8.0"
@@ -26,3 +27,4 @@ FunctionWrappers = "1.1.3"
 InteractiveUtils = "1.11.0"
 Printf = "1.11.0"
 Test = "1.11.0"
+TimerOutputs = "0.5.29"

+ 67 - 44
src/AtomicDEVS.jl

@@ -1,6 +1,8 @@
 import DataStructures
 using BenchmarkTools
 using InteractiveUtils
+using TimerOutputs
+const Timer = TimerOutput()
 
 @enum Transitions NONE INTERNAL EXTERNAL CONFLUENT
 
@@ -27,57 +29,64 @@ time_advance(agent, model) = error("time_advance not implemented for $(typeof(ag
 output!(agent, model) = nothing
 
 function simulate_devs!(model, duration::Float64=Inf)
-    if model.logging !== nothing && isempty(model.event_logs)
-        if model.logging == ""
-            print_initial_conditions(model)
-        else
-            log_initial_conditions!(model)
+#     @timeit Timer "Simulation Loop" begin
+        if model.logging !== nothing && isempty(model.event_logs)
+            if model.logging == ""
+                print_initial_conditions(model)
+            else
+                log_initial_conditions!(model)
+            end
         end
-    end
 
-    function stop_condition(model, step_number)
-        queue = getfield(model, :event_queue)
-        isempty(queue) && return true
-        next_time = first(queue)[2]
-        return next_time > duration || next_time == Inf
-    end
+        function stop_condition(model, step_number)
+            queue = getfield(model, :event_queue)
+            isempty(queue) && return true
+            next_time = first(queue)[2]
+            return next_time > duration || next_time == Inf
+        end
 
-    step!(model, stop_condition)
+        step!(model, stop_condition)
 
-    if model.logging !== nothing
-        if model.logging == ""
-            print_trace(model)
-        else
-            export_trace_to_csv(model, model.logging)
+        if model.logging !== nothing
+            if model.logging == ""
+                print_trace(model)
+            else
+                export_trace_to_csv(model, model.logging)
+            end
         end
-    end
+#     end
+#     show(Timer)
+#     println()
+#     reset_timer!(Timer)
 end
 
 function send_message!(agent, model, port::Symbol, msg)
-    if model.logging !== nothing
-        if !haskey(model.out_log, agent.id)
-            model.out_log[agent.id] = Dict{Symbol, Vector{Any}}()
-        end
-        if !haskey(model.out_log[agent.id], port)
-            model.out_log[agent.id][port] = Any[]
+#     @timeit Timer "Send Message" begin
+        if model.logging !== nothing
+            if !haskey(model.out_log, agent.id)
+                model.out_log[agent.id] = Dict{Symbol, Vector{Any}}()
+            end
+            if !haskey(model.out_log[agent.id], port)
+                model.out_log[agent.id][port] = Any[]
+            end
+            push!(model.out_log[agent.id][port], msg)
         end
-        push!(model.out_log[agent.id][port], msg)
-    end
 
-    routes_tuple = getproperty(agent.out_ports, port)
-    for route_vec in routes_tuple
-        for (target_array, Z_func, target_id) in route_vec
+        routes_tuple = getproperty(agent.out_ports, port)
+        for route_vec in routes_tuple
+            for (target_array, Z_func, target_id) in route_vec
 
-            translated_msg = Z_func(msg)
-            push!(target_array, translated_msg)
+                translated_msg = Z_func(msg)
+                push!(target_array, translated_msg)
 
-            target_agent = model[target_id]
-            if !target_agent.is_receiving
-                target_agent.is_receiving = true
-                push!(model.active_receivers, target_id)
+                target_agent = model[target_id]
+                if !target_agent.is_receiving
+                    target_agent.is_receiving = true
+                    push!(model.active_receivers, target_id)
+                end
             end
         end
-    end
+#     end
 end
 
 function route_outputs!(model)
@@ -133,14 +142,12 @@ end
     current_time,
     triggering_agent_id
 ) where {A}
-
     # imminent already handled
     if a.is_imminent
         return
     end
 
     e = current_time - a.last_event_time
-
     external_transition!(a, model, e, a.inbox)
 
     a.last_event_time = current_time
@@ -160,6 +167,12 @@ function transition!(model, current_time, triggering_agent_id)
     empty!(model.requeue_buffer)
 
     for id in model.imminent
+#         @timeit Timer "Process Imminent" process_imminent!(
+#             model[id],
+#             model,
+#             current_time,
+#             triggering_agent_id
+#         )
         process_imminent!(
             model[id],
             model,
@@ -169,6 +182,12 @@ function transition!(model, current_time, triggering_agent_id)
     end
 
     for id in model.active_receivers
+#         @timeit Timer "Process Receivers" process_receiver!(
+#             model[id],
+#             model,
+#             current_time,
+#             triggering_agent_id
+#         )
         process_receiver!(
             model[id],
             model,
@@ -188,10 +207,13 @@ function transition!(model, current_time, triggering_agent_id)
     empty!(model.imminent)
     empty!(model.active_receivers)
 
-    for req_id in model.requeue_buffer
-        agent = model[req_id]
-        Agents.add_event!(agent, model)
-    end
+#     @timeit Timer "Requeue Events" begin
+        for req_id in model.requeue_buffer
+            agent = model[req_id]
+            Agents.add_event!(agent, model)
+#             @timeit Timer "Agents.jl Add Event" Agents.add_event!(agent, model)
+        end
+#     end
 end
 
 function devs_step!(agent, model)
@@ -224,10 +246,11 @@ function devs_step!(agent, model)
     end
 
     if is_last_in_batch && !isempty(model.imminent)
+#         @timeit Timer "Route Outputs" route_outputs!(model)
+#         @timeit Timer "Transitions" transition!(model, current_time, agent.id)
         route_outputs!(model)
         transition!(model, current_time, agent.id)
     end
-
 end
 
 function engine_timing(agent, model)

+ 35 - 37
src/CoupledDEVS.jl

@@ -1,5 +1,7 @@
 @enum port_type INPUT OUTPUT
 using FunctionWrappers: FunctionWrapper
+using TimerOutputs
+const Builder = TimerOutput()
 
 struct Route{OutMsg}
     deliver!::FunctionWrapper{Cvoid, Tuple{OutMsg}}
@@ -184,23 +186,11 @@ function build_standalone_agents(top_model::CoupledDEVS; routing_tables=Dict{Int
     current_id = Ref(1)
 
     instantiate_tree!(top_model, string(top_model.name), path_to_id, agent_list, current_id, routing_tables)
+#     @timeit Builder "Instantiate Tree" instantiate_tree!(top_model, string(top_model.name), path_to_id, agent_list, current_id, routing_tables)
 
     return agent_list, path_to_id
 end
 
-function initialize_abm(agent_list::Vector{Any}, events::Tuple, path_to_id::Dict{String, Int}, logging::Union{Nothing, String})
-    concrete_types = unique(typeof.(agent_list))
-    AgentUnion = Union{concrete_types...}
-
-    props = DEVSProperties(logging=logging, path_to_id=path_to_id)
-
-    model = EventQueueABM(AgentUnion, events; properties = props)
-    for agent in agent_list
-        add_agent!(agent, model)
-    end
-    return model
-end
-
 function build_global_links!(node::CoupledDEVS, current_path::String, links::Dict)
     for (source, s_port, target, t_port, Z) in node.couplings
         full_source = source == :self ? current_path : (current_path == :self ? string(source) : "$current_path.$source")
@@ -324,29 +314,37 @@ function build_routing_tables(couplings::Dict, agent_list)
 end
 
 function compile_devs(top_model::CoupledDEVS; logging::Union{Nothing, String}=nothing)
-    dummy_agents, path_to_id = build_standalone_agents(top_model)
-
-    # Resolve direct couplings using raw data (NO EventQueueABM creation!)
-    couplings = resolve_direct_couplings(top_model, path_to_id, dummy_agents)
-
-    routing_tables = build_routing_tables(couplings, dummy_agents)
-
-    final_agents, final_paths = build_standalone_agents(top_model; routing_tables=routing_tables)
-
-    unique_types = unique(typeof(a) for a in final_agents)
-    AgentUnion = Union{unique_types...}
-
-    final_props = DEVSProperties(
-        couplings = couplings,
-        logging = logging,
-        path_to_id = final_paths
-    )
-    final_model = EventQueueABM(AgentUnion, (UniversalEvent, ); properties = final_props)
-
-    typed_agents = Vector{AgentUnion}(final_agents)
-    for agent in typed_agents
-        add_agent!(agent, final_model)
-    end
-
+#     @timeit Builder "Compile DEVS" begin
+        dummy_agents, path_to_id = build_standalone_agents(top_model)
+#         @timeit Builder "Build Dummy Agents" dummy_agents, path_to_id = build_standalone_agents(top_model)
+
+        # Resolve direct couplings using raw data (NO EventQueueABM creation!)$
+        couplings = resolve_direct_couplings(top_model, path_to_id, dummy_agents)
+        routing_tables = build_routing_tables(couplings, dummy_agents)
+        final_agents, final_paths = build_standalone_agents(top_model; routing_tables=routing_tables)
+#         @timeit Builder "Resolve Couplings" couplings = resolve_direct_couplings(top_model, path_to_id, dummy_agents)
+#         @timeit Builder "Build Routing Tables" routing_tables = build_routing_tables(couplings, dummy_agents)
+#         @timeit Builder "Build Final Agents" final_agents, final_paths = build_standalone_agents(top_model; routing_tables=routing_tables)
+
+        unique_types = unique(typeof(a) for a in final_agents)
+        AgentUnion = Union{unique_types...}
+
+        final_props = DEVSProperties(
+            couplings = couplings,
+            logging = logging,
+            path_to_id = final_paths
+        )
+        final_model = EventQueueABM(AgentUnion, (UniversalEvent, ); properties = final_props)
+#         @timeit Builder "Build Model" final_model = EventQueueABM(AgentUnion, (UniversalEvent, ); properties = final_props)
+
+        typed_agents = Vector{AgentUnion}(final_agents)
+        for agent in typed_agents
+            add_agent!(agent, final_model)
+#             @timeit Builder "Agents.jl Add Agent" add_agent!(agent, final_model)
+        end
+#     end
+#     show(Builder)
+#     println()
+#     reset_timer!(Builder)
     return final_model
 end