Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Problems When Receiving Streaming Data #40

Closed
sanssecours opened this issue Mar 2, 2023 · 5 comments
Closed

Performance Problems When Receiving Streaming Data #40

sanssecours opened this issue Mar 2, 2023 · 5 comments
Labels
performance Problems regarding the performance of code
Milestone

Comments

@sanssecours
Copy link
Member

sanssecours commented Mar 2, 2023

Description

It seems that the “new” Network class (based on python-can) might have some performance issues, if we use the PCAN interface (standard interface for PEAK CAN adapter on macOS and Windows) to stream data to the computer. After some amount of time the code throws a PcanCanOperationError declaring that the “receive queue was read too late”.

The same code works fine using the SocketCAN interface on Linux.

Steps to Reproduce

  1. Install ICOc in development mode

    pip install -e .[dev,test]
    
  2. Check out commit 4b260bce for test script new.py

  3. Execute the following command in the repository

    python mytoolit/experiments/new.py

Expected Result

The script finishes without any problems.

Actual Result

After a certain amount of time the script prints the an error message that looks like this:

Exception in thread can.notifier for bus "PCAN_USBBUS1":
Traceback (most recent call last):
  File "…threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "…threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "…site-packages/can/notifier.py", line 122, in _rx_thread
    msg = bus.recv(self.timeout)
          ^^^^^^^^^^^^^^^^^^^^^^
  File "…site-packages/can/bus.py", line 98, in recv
    msg, already_filtered = self._recv_internal(timeout=time_left)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "…site-packages/can/interfaces/pcan/pcan.py", line 472, in _recv_internal
    raise PcanCanOperationError(self._get_formatted_error(result[0]))
can.interfaces.pcan.pcan.PcanCanOperationError: The receive queue was read too late

Additional Information

I tested the script three times on all of the (more or less) supported operating systems. One reason behind the failure (on macOS and Windows) might be the additional code (on top of python-can) in this repository. However replacing it with something like pass did not solve the problem (on macOS) when I tried. The CPU utilization stayed pretty much the same as far as I can tell.

Regarding the CPU usage: Please take the values below with a grain of salt. I “measured” the CPU utilization using the graphical system monitor software provided by the different operating systems. This process is obviously not very accurate, especially since modern systems contain multiple CPU cores. In the case of the M1 machine below, these cores even have very different performance characteristics.

Linux

System

Test Results

CPU Usage: ~ 80% CPU (of single core)

Test Result
Test 1 ✅ Works
Test 2 ✅ Works
Test 3 ✅ Works

macOS

System

CPU Usage: ~ 60% – 65% (of single core)

Test Result
Test 1 ❌ Failure after ca. 44 seconds
Test 2 ❌ Failure after ca. 2 minutes 45 seconds
Test 3 ❌ Failure after ca. 3 minutes 57 seconds

Windows

System

Test Results

CPU Usage: ~ 60% – 80% (of single core)

Test Result
Test 1 ❌ Failure after ca. 1 min 10 seconds
Test 2 ❌ Failure after ca. 1 min 10 seconds
Test 3 ❌ Failure after ca. 1 min 4 seconds
@sanssecours sanssecours added the performance Problems regarding the performance of code label Mar 2, 2023
@sanssecours sanssecours changed the title Performance Problems When Receiving Streaming Data Using the PCAN (Basic) Interface Performance Problems When Receiving Streaming Data May 9, 2023
@sanssecours
Copy link
Member Author

Update

The same problem also occurs with the SocketCAN interface on Linux. The only difference seems to be that the SocketCAN backend drops CAN packets without raising an exception. That is also the reason why I thought everything was working fine.

Lessons Learned

Always check the measurement data for lost packages.

sanssecours added a commit that referenced this issue Feb 1, 2024
sanssecours added a commit that referenced this issue Feb 14, 2024
sanssecours added a commit that referenced this issue Feb 22, 2024
@sanssecours sanssecours mentioned this issue Feb 22, 2024
3 tasks
@sanssecours
Copy link
Member Author

sanssecours commented Feb 22, 2024

Performance Measurement

Measuring performance on one of the efficiency cores of the M1 MacBook with:

taskpolicy -b fish -c 'icon measure -t 10 -n Test-STH'

showed about 30% performance usage without any code in AsyncStreamBuffer.on_message_received.

@sanssecours
Copy link
Member Author

sanssecours commented Feb 29, 2024

Ideas to Improve Performance

We are already working on ideas to improve the performance in the branch 🐌, which should also be the basis for version 2.0 of the package (see also issue #51). Currently we simplified the data structure returned by the streaming API to keep the performance problems in check.

Other ideas:

  • Look into applying a message filter for the streaming data: This should be faster than the current version of checking the CAN identifier in the on_message_received method
  • Remove units from stored data

Note: It might make sense to count the number of instructions for a certain number of messages

sanssecours added a commit that referenced this issue Feb 29, 2024
sanssecours added a commit that referenced this issue Apr 24, 2024
sanssecours added a commit that referenced this issue Jul 30, 2024
sanssecours added a commit that referenced this issue Jul 30, 2024
sanssecours added a commit that referenced this issue Aug 14, 2024
sanssecours added a commit that referenced this issue Aug 14, 2024
sanssecours added a commit that referenced this issue Aug 21, 2024
sanssecours added a commit that referenced this issue Aug 21, 2024
sanssecours added a commit that referenced this issue Aug 27, 2024
sanssecours added a commit that referenced this issue Aug 27, 2024
sanssecours added a commit that referenced this issue Aug 28, 2024
sanssecours added a commit that referenced this issue Aug 28, 2024
sanssecours added a commit that referenced this issue Sep 9, 2024
sanssecours added a commit that referenced this issue Sep 9, 2024
sanssecours added a commit that referenced this issue Sep 11, 2024
sanssecours added a commit that referenced this issue Sep 11, 2024
@sanssecours sanssecours added this to the 2.0.0 milestone Sep 16, 2024
@sanssecours
Copy link
Member Author

In theory the latest changes (currently in the branch 🌱; planned for release 2.0) should impove the performance slightly. Another big advantage of the new code is that it raises an exception, if the buffer for streaming data exceeds a certain fixed size (currently 10 000 elements).

@sanssecours
Copy link
Member Author

With the addition of a performance test to the extended manual tests I will close this issue for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Problems regarding the performance of code
Projects
None yet
Development

No branches or pull requests

1 participant