Browse Source

Performance improvements

Yentl Van Tendeloo 8 years ago
parent
commit
08e2a50fdb
1 changed files with 71 additions and 57 deletions
  1. 71 57
      models/SCCD_execute.alc

+ 71 - 57
models/SCCD_execute.alc

@@ -6,9 +6,9 @@ include "random.alh"
 include "library.alh"
 
 Element function resolve_function(location : String, data : Element):
-	if (bool_not(dict_in(data["operations"], location))):
-		dict_add(data["operations"], location, get_func_AL_model(import_node(location)))
-	return data["operations"][location]!
+	if (bool_not(dict_in(data["cache_operations"], location))):
+		dict_add(data["cache_operations"], location, get_func_AL_model(import_node(location)))
+	return data["cache_operations"][location]!
 
 Void function print_states(model : Element, data : Element):
 	Element classes
@@ -57,18 +57,18 @@ Element function filter_exists(model : Element, set : Element, attribute_name :
 
 	return result!
 
-Element function expand_current_state(model : Element, state : String, class_data : Element):
+Element function expand_current_state(model : Element, state : String, data : Element):
 	// Find the hierarchy of all current states, and select those that contain the currently selected state
 	Element result
 	Element current_states
 	result = create_node()
-	current_states = set_copy(class_data["states"])
+	current_states = set_copy(data["classes"][data["current_class"]]["states"])
 
 	Element hierarchy
 	String deep_state
 	while (read_nr_out(current_states) > 0):
 		deep_state = set_pop(current_states)
-		hierarchy = find_hierarchy(model, deep_state)
+		hierarchy = find_hierarchy(model, deep_state, data)
 		// Got the hierarchy of one of the states
 
 		if (set_in(hierarchy, state)):
@@ -77,19 +77,19 @@ Element function expand_current_state(model : Element, state : String, class_dat
 
 	return result!
 
-Element function expand_initial_state(model : Element, state : String, class_data : Element):
+Element function expand_initial_state(model : Element, state : String, data : Element):
 	String t
 	t = read_type(model, state)
 	if (t == "SCCD/CompositeState"):
 		// Recurse further in the composite
-		return expand_composite_state(model, state, class_data)!
+		return expand_composite_state(model, state, data)!
 	elif (t == "SCCD/ParallelState"):
 		// Split up all components
-		return expand_parallel_state(model, state, class_data)!
+		return expand_parallel_state(model, state, data)!
 	elif (t == "SCCD/HistoryState"):
 		// Reset the history
 		// This is not really an initial state, but it is called in exactly the same places
-		return class_data["history"][get_parent(model, state)]!
+		return data["classes"][data["current_class"]]["history"][get_parent(model, state)]!
 	else:
 		// Probably just an atomic, so return this one only
 		Element result
@@ -97,7 +97,7 @@ Element function expand_initial_state(model : Element, state : String, class_dat
 		set_add(result, state)
 		return result!
 
-Element function expand_composite_state(model : Element, composite_state : String, class_data : Element):
+Element function expand_composite_state(model : Element, composite_state : String, data : Element):
 	// Resolve all initial states from a single composite state
 	String initial
 
@@ -105,9 +105,9 @@ Element function expand_composite_state(model : Element, composite_state : Strin
 	initial = set_pop(filter(model, allAssociationDestinations(model, composite_state, "SCCD/composite_children"), "isInitial", True))
 
 	// Expand the initial state, depending on what it is
-	return expand_initial_state(model, initial, class_data)!
+	return expand_initial_state(model, initial, data)!
 
-Element function expand_parallel_state(model : Element, parallel_state : String, class_data : Element):
+Element function expand_parallel_state(model : Element, parallel_state : String, data : Element):
 	// Resolve all initial states from a single parallel state
 	Element children
 	Element result
@@ -117,7 +117,7 @@ Element function expand_parallel_state(model : Element, parallel_state : String,
 	result = create_node()
 
 	while (read_nr_out(children) > 0):
-		set_merge(result, expand_initial_state(model, set_pop(children), class_data))
+		set_merge(result, expand_initial_state(model, set_pop(children), data))
 
 	return result!
 
@@ -134,6 +134,11 @@ Void function start_class(model : Element, data : Element, class : String, ident
 	dict_add(class_handle, "type", class)
 	dict_add(class_handle, "ID", identifier)
 	dict_add(class_handle, "timers", create_node())
+	dict_add(data["classes"], class_handle["ID"], class_handle)
+
+	String prev_class
+	prev_class = data["current_class"]
+	dict_overwrite(data, "current_class", identifier)
 
 	// Add the current state of the class
 	String initial_state
@@ -176,13 +181,14 @@ Void function start_class(model : Element, data : Element, class : String, ident
 	set_add(init, "")
 	// Initial state before initialization is the set with an empty hierarchy
 	// Empty set would not find any difference between the source and target
-	execute_actions(model, init, set_copy(class_handle["states"]), attributes, data, "")
 
-	dict_add(data["classes"], class_handle["ID"], class_handle)
+	execute_actions(model, init, set_copy(class_handle["states"]), data, "")
+
+	dict_overwrite(data, "current_class", prev_class)
 
 	return!
 
-Element function get_enabled_transitions(model : Element, state : String, data : Element, class : String):
+Element function get_enabled_transitions(model : Element, state : String, data : Element):
 	// Returns all enabled transitions
 	Element result
 	Element to_filter
@@ -224,9 +230,9 @@ Element function get_enabled_transitions(model : Element, state : String, data :
 		// Check after
 		// Only an after if there was no event!
 		if (bool_and(element_eq(attr, read_root()), read_attribute(model, transition, "after"))):
-			if (dict_in(data["classes"][class]["timers"], transition)):
+			if (dict_in(data["classes"][data["current_class"]]["timers"], transition)):
 				// Registered timer already, let's check if it has expired
-				if (float_gt(data["classes"][class]["timers"][transition], data["time_sim"])):
+				if (float_gt(data["classes"][data["current_class"]]["timers"][transition], data["time_sim"])):
 					// Not enabled yet
 					continue!
 			else:
@@ -248,7 +254,7 @@ Element function get_enabled_transitions(model : Element, state : String, data :
 				param = set_pop(params)
 				if (element_neq(cond, read_root())):
 					// Got a condition to check first
-					if (bool_not(cond(data["classes"][class]["attributes"], param))):
+					if (bool_not(cond(data["classes"][data["current_class"]]["attributes"], param))):
 						// Condition failed, so skip
 						continue!
 				// Fine to add this one with the specified parameters
@@ -257,7 +263,7 @@ Element function get_enabled_transitions(model : Element, state : String, data :
 			// No event to think about, just add the transition
 			if (element_neq(cond, read_root())):
 				// Check the condition first
-				if (bool_not(cond(data["classes"][class]["attributes"], read_root()))):
+				if (bool_not(cond(data["classes"][data["current_class"]]["attributes"], read_root()))):
 					// Condition false, so skip
 					continue!
 			// Fine to add this one without event parameters (no event)
@@ -298,7 +304,7 @@ Void function process_raised_event(model : Element, event : Element, parameter_a
 
 	return !
 
-Element function execute_transition(model : Element, data : Element, class : String, transition_tuple : Element):
+Element function execute_transition(model : Element, data : Element, transition_tuple : Element):
 	// Execute the script (if any)
 	Element script
 	String transition
@@ -309,7 +315,7 @@ Element function execute_transition(model : Element, data : Element, class : Str
 	script = read_attribute(model, transition, "script")
 	if (element_neq(script, read_root())):
 		script = resolve_function(script, data)
-		script(data["classes"][class]["attributes"], event_parameter)
+		script(data["classes"][data["current_class"]]["attributes"], event_parameter)
 
 	// Raise events (if any)
 	Element events
@@ -323,17 +329,17 @@ Element function execute_transition(model : Element, data : Element, class : Str
 		if (element_neq(parameter_action, read_root())):
 			// Got a parameter to evaluate
 			parameter_action = resolve_function(parameter_action, data)
-			parameter_action = parameter_action(data["classes"][class]["attributes"], event_parameter)
+			parameter_action = parameter_action(data["classes"][data["current_class"]]["attributes"], event_parameter)
 
 		process_raised_event(model, event, parameter_action, data)
 
 	// Find new set of states
 	Element target_states
 	Element source_states
-	source_states = expand_current_state(model, readAssociationSource(model, transition), data["classes"][class])
-	target_states = expand_initial_state(model, readAssociationDestination(model, transition), data["classes"][class])
+	source_states = expand_current_state(model, readAssociationSource(model, transition), data)
+	target_states = expand_initial_state(model, readAssociationDestination(model, transition), data)
 
-	execute_actions(model, source_states, target_states, data["classes"][class], data, readAssociationSource(model, transition))
+	execute_actions(model, source_states, target_states, data, readAssociationSource(model, transition))
 
 	return target_states!
 
@@ -351,7 +357,10 @@ Boolean function step_class(model : Element, data : Element, class : String):
 	String current_state
 	Boolean found
 
-	states = set_copy(data["classes"][class]["states"])
+	// Notify everyone of the current class
+	dict_overwrite(data, "current_class", class)
+
+	states = set_copy(data["classes"][data["current_class"]]["states"])
 	new_states = create_node()
 	transitioned = False
 
@@ -360,21 +369,21 @@ Boolean function step_class(model : Element, data : Element, class : String):
 		found = False
 
 		// Loop over the hierarchy of this state and try to apply transitions
-		hierarchy = find_hierarchy(model, state)
+		hierarchy = find_hierarchy(model, state, data)
 		while (read_nr_out(hierarchy) > 0):
 			current_state = list_pop(hierarchy, 0)
-			transitions = get_enabled_transitions(model, current_state, data, class)
+			transitions = get_enabled_transitions(model, current_state, data)
 
 			if (read_nr_out(transitions) > 0):
 				// Found an enabled transition, so store that one
 				transition = random_choice(transitions)
 				
 				// Execute transition
-				set_merge(new_states, execute_transition(model, data, class, transition))
+				set_merge(new_states, execute_transition(model, data, transition))
 
 				// When leaving an orthogonal component, we must also pop all related states that might be processed in the future!
 				Element leaving
-				leaving = expand_current_state(model, current_state, data["classes"][class])
+				leaving = expand_current_state(model, current_state, data)
 				set_difference(states, leaving)
 
 				transitioned = True
@@ -386,7 +395,7 @@ Boolean function step_class(model : Element, data : Element, class : String):
 			set_add(new_states, state)
 			
 	// Update states
-	dict_overwrite(data["classes"][class], "states", new_states)
+	dict_overwrite(data["classes"][data["current_class"]], "states", new_states)
 
 	return transitioned!
 
@@ -399,20 +408,22 @@ String function get_parent(model : Element, state : String):
 	else:
 		return ""!
 
-Element function find_hierarchy(model : Element, state : String):
-	if (state == ""):
-		return create_node()!
-	else:
+Element function find_hierarchy(model : Element, state : String, data : Element):
+	// Try to cache as much as possible!
+	if (bool_not(dict_in(data["cache_hierarchy"], state))):
 		Element result
-		String parent
-
-		parent = get_parent(model, state)
-		// We have a parent, so take the parent list first
-		result = find_hierarchy(model, parent)
-		list_append(result, state)
-		return result!
-
-Void function execute_actions(model : Element, source_states : Element, target_states : Element, class_data : Element, data : Element, transition_source : String):
+		if (state == ""):
+			result = create_node()
+		else:
+			String parent
+			parent = get_parent(model, state)
+			// We have a parent, so take the parent list first
+			result = find_hierarchy(model, parent, data)
+			list_append(result, state)
+		dict_add(data["cache_hierarchy"], state, result)
+	return dict_copy(data["cache_hierarchy"][state])!
+
+Void function execute_actions(model : Element, source_states : Element, target_states : Element, data : Element, transition_source : String):
 	Element exit
 	Element entry
 	exit = create_node()
@@ -431,11 +442,11 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 
 	hierarchy_sources = create_node()
 	while (read_nr_out(source_states) > 0):
-		set_add(hierarchy_sources, find_hierarchy(model, set_pop(source_states)))
+		set_add(hierarchy_sources, find_hierarchy(model, set_pop(source_states), data))
 
 	hierarchy_targets = create_node()
 	while (read_nr_out(target_states) > 0):
-		set_add(hierarchy_targets, find_hierarchy(model, set_pop(target_states)))
+		set_add(hierarchy_targets, find_hierarchy(model, set_pop(target_states), data))
 
 	all_hierarchies = set_copy(hierarchy_sources)
 	set_merge(all_hierarchies, hierarchy_targets)
@@ -453,7 +464,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 
 	if (transition_source != ""):
 		// Find out the level of the transition_source by fetching its hierarchy
-		transition_depth = list_len(find_hierarchy(model, transition_source)) - 1
+		transition_depth = list_len(find_hierarchy(model, transition_source, data)) - 1
 
 		// Now check for the least common ancestor
 		while (bool_not(finished)):
@@ -557,14 +568,14 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 
 		// Set history when leaving
 		if (read_type(model, state) == "SCCD/CompositeState"):
-			dict_overwrite(class_data["history"], state, expand_current_state(model, state, class_data))
+			dict_overwrite(data["classes"][data["current_class"]]["history"], state, expand_current_state(model, state, data))
 
 		// Do exit actions
 		action = read_attribute(model, state, "onExitScript")
 		if (element_neq(action, read_root())):
 			// Got a script, so execute!
 			action = resolve_function(action, data)
-			action(class_data["attributes"])
+			action(data["classes"][data["current_class"]]["attributes"])
 
 		// Raise events
 		events = allAssociationDestinations(model, state, "SCCD/onExitRaise")
@@ -576,7 +587,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 			if (element_neq(parameter_action, read_root())):
 				// Got a parameter to evaluate
 				parameter_action = resolve_function(parameter_action, data)
-				parameter_action = parameter_action(class_data["attributes"])
+				parameter_action = parameter_action(data["classes"][data["current_class"]]["attributes"])
 
 			process_raised_event(model, event, parameter_action, data)
 
@@ -584,7 +595,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 		Element timed_transitions
 		timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
 		while (read_nr_out(timed_transitions) > 0):
-			dict_delete(class_data["timers"], set_pop(timed_transitions))
+			dict_delete(data["classes"][data["current_class"]]["timers"], set_pop(timed_transitions))
 
 	// Then do entry actions
 	while (read_nr_out(entry) > 0):
@@ -595,7 +606,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 		if (element_neq(action, read_root())):
 			// Got a script, so execute!
 			action = resolve_function(action, data)
-			action(class_data["attributes"])
+			action(data["classes"][data["current_class"]]["attributes"])
 
 		// Raise events
 		events = allAssociationDestinations(model, state, "SCCD/onEntryRaise")
@@ -607,7 +618,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 			if (element_neq(parameter_action, read_root())):
 				// Got a parameter to evaluate
 				parameter_action = resolve_function(parameter_action, data)
-				parameter_action = parameter_action(class_data["attributes"])
+				parameter_action = parameter_action(data["classes"][data["current_class"]]["attributes"])
 
 			process_raised_event(model, event, parameter_action, data)
 
@@ -619,7 +630,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
 		while (read_nr_out(timed_transitions) > 0):
 			transition = set_pop(timed_transitions)
 			after = resolve_function(read_attribute(model, transition, "after"), data)
-			dict_add(class_data["timers"], transition, float_addition(data["time_sim"], after(class_data["attributes"])))
+			dict_add(data["classes"][data["current_class"]]["timers"], transition, float_addition(data["time_sim"], after(data["classes"][data["current_class"]]["attributes"])))
 
 	return !
 
@@ -662,7 +673,9 @@ Boolean function main(model : Element):
 	Element data
 	data = create_node()
 	dict_add(data, "classes", create_node())
-	dict_add(data, "operations", create_node())
+	dict_add(data, "cache_operations", create_node())
+	dict_add(data, "cache_hierarchy", create_node())
+	dict_add(data, "current_class", "")
 	
 	Float time_0
 	Float time_sim
@@ -715,6 +728,7 @@ Boolean function main(model : Element):
 
 		time_wallclock = time() - time_0
 		timeout = time_sim - time_wallclock
+		log("Pause for: " + cast_v2s(timeout))
 
 	// We should never get here!
 	return False!