Repository: RedHatInsights/insights-core

Issue:
component run order inefficiency
insights-core sorts the loaded components for every archive it analyzes. This is inefficient if there are many components and the library is embedded in a system that analyzes many archives. There should be an option either for the framework itself to sort the components once and know it doesn't have to do it again, or clients should be able to handle component sorting themselves so they can cache the result.


Discussion:

Resolving patch:
diff --git a/insights/core/dr.py b/insights/core/dr.py
--- a/insights/core/dr.py
+++ b/insights/core/dr.py
@@ -1013,7 +1013,7 @@ def run_order(graph):
     return toposort_flatten(graph, sort=False)
 
 
-def _determine_components(components):
+def determine_components(components):
     if isinstance(components, dict):
         return components
 
@@ -1033,27 +1033,17 @@ def _determine_components(components):
         return COMPONENTS[components]
 
 
-def run(components=None, broker=None):
-    """
-    Executes components in an order that satisfies their dependency
-    relationships.
+_determine_components = determine_components
 
-    Keyword Args:
-        components: Can be one of a dependency graph, a single component, a
-            component group, or a component type. If it's anything other than a
-            dependency graph, the appropriate graph is built for you and before
-            evaluation.
-        broker (Broker): Optionally pass a broker to use for evaluation. One is
-            created by default, but it's often useful to seed a broker with an
-            initial dependency.
-    Returns:
-        Broker: The broker after evaluation.
+
+def run_components(ordered_components, components, broker):
     """
-    components = components or COMPONENTS[GROUPS.single]
-    components = _determine_components(components)
-    broker = broker or Broker()
+    Runs a list of preordered components using the provided broker.
 
-    for component in run_order(components):
+    This function allows callers to order components themselves and cache the
+    result so they don't incur the toposort overhead on every run.
+    """
+    for component in ordered_components:
         start = time.time()
         try:
             if (component not in broker and component in components and
@@ -1081,9 +1071,31 @@ def run(components=None, broker=None):
     return broker
 
 
+def run(components=None, broker=None):
+    """
+    Executes components in an order that satisfies their dependency
+    relationships.
+
+    Keyword Args:
+        components: Can be one of a dependency graph, a single component, a
+            component group, or a component type. If it's anything other than a
+            dependency graph, the appropriate graph is built for you and before
+            evaluation.
+        broker (Broker): Optionally pass a broker to use for evaluation. One is
+            created by default, but it's often useful to seed a broker with an
+            initial dependency.
+    Returns:
+        Broker: The broker after evaluation.
+    """
+    components = components or COMPONENTS[GROUPS.single]
+    components = determine_components(components)
+    broker = broker or Broker()
+    return run_components(run_order(components), components, broker)
+
+
 def generate_incremental(components=None, broker=None):
     components = components or COMPONENTS[GROUPS.single]
-    components = _determine_components(components)
+    components = determine_components(components)
     for graph in get_subgraphs(components):
         yield graph, broker or Broker()
 


Test patch: