DLR-RM / DLR-RM/RAFCON

Address performance issues related to large objects workflows

Open
#898 6 comments 1 reaction 0 assignees View on GitHub
Dominant language
Python
Stars
212
Forks
39
PR merge metrics
No merged PRs in 30d

Description

I would like to propose a couple of enhancements that address multiple performance issues, one related to a performance issue in GVM and a couple related to deepcopy when using flow ports between states. I understand that the RAFCON team has previously expressed a preference to retain the use of deepcopy for safety reasons. However, I propose the introduction of optional configuration flags to provide users with greater flexibility in optimizing performance while preserving the current behavior by default.

Below are the specific instances where significant performance bottlenecks have been observed:

---

### 1. **Global Variable Manager - gvm.set\_variable delay**

**File:** `source/rafcon/core/global_variable_manager.py:112`

**Issue:**
When setting a global variable, the following line serializes the value to generate a message string. For large objects, this serialization takes several seconds to complete:

```python
logger.debug("Global variable '{}' was set to value '{}' with type '{}'".format(key, value, data_type.__name__))
```

**Proposed Solution:**
Serialize the message **only if debug logging is enabled**, as shown below:

```python
if logger.isEnabledFor(10): # DEBUG level is 10
logger.debug("Global variable '{}' was set to value '{}' with type '{}'".format(key, value, data_type.__name__))
```

This change avoids unnecessary serialization when debug logging is disabled, leading to significant performance improvements.

---

### 2. **Output Port Delay**

**File:** `source/rafcon/core/execution/execution_history_items.py:176`

**Issue:**
When generating `ScopedDataItem` for use in the data flow, a deepcopy is performed, which takes around **500-800 ms per trajectory** (using MoveIt2 trajectories as a large complex object):

```python
self.child_state_input_output_data = copy.deepcopy(child_state_input_output_data)
```

**Proposed Solution:**
Introduce an option to **skip deepcopy** for users who do not require it.

```python
if use_deepcopy: # use_deepcopy could be a configurable flag in the execution context
self.child_state_input_output_data = copy.deepcopy(child_state_input_output_data)
else:
self.child_state_input_output_data = child_state_input_output_data
```

This change would maintain backward compatibility, as `use_deepcopy` would default to `True`, but allow users to enable somehow this flag for significant performance gains.

---

### 3. **Input Port Delay**

**File:** `source/rafcon/core/states/container_state.py:1474`

**Issue:**
When retrieving input data for state execution, a deepcopy is performed on `ScopedDataItem` data from the data flow, leading to an additional **500-800 ms delay** in our case sending a moveit2 trajectory:

```python
actual_value = deepcopy(self.scoped_data[key].value)
```

**Proposed Solution:**
Optionally **disable deepcopy** using a similar approach to the output port delay fix:

```python
if use_deepcopy: # use_deepcopy could be a configurable flag in the execution context
actual_value = deepcopy(self.scoped_data[key].value)
else:
actual_value = self.scoped_data[key].value
```

Again, this approach maintains current behavior by default but gives users the flexibility to avoid the deepcopy overhead.

---

These proposed changes offer a significant reduction in execution time, especially for workflows with large data objects or high-frequency state transitions.

**Benefits:**

- **Backwards Compatibility**: Defaults to the current behavior (deepcopy enabled).
- **Performance Improvement**: Reduces delays in input/output processing and global variable handling.
- **User Flexibility**: Provides configurable flags for advanced users who can guarantee data immutability.

I would like to know if there is a feasible way to introduce this flag in the mentioned cases. Additionally, I propose applying the fix for point 1 directly, as it provides immediate performance benefits. Please let me know if this approach aligns with RAFCON's design principles, and I would be happy to assist in implementing or testing these changes.

Contributor guide

Open the contributing guide

Research direction

Review source/rafcon/core/global_variable_manager.py:112, source/rafcon/core/execution/execution_history_items.py:176, and source/rafcon/core/states/container_state.py:1474. Start by tracing how logging and execution context data flow through these locations, then determine how the requested options would be propagated. Done means avoiding unnecessary debug serialization and supporting optional deepcopy bypasses while retaining deepcopy behavior by default.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.