realthunder/FreeCAD_assembly3

Moving parts is very slow, adding more parts makes it exponentially slower

abetis opened this issue · 3 comments

Hi,

I started working on an assembly, added only 21 parts, all with attachment constraints except 1 part that have 1 axis of freedom for movement (sliding on another part).
All parts are imported from STEP files.

Moving the part that should slide to see how the constraints work refreshes the screen VERY slow, close to the unusable area.
Was about to blame the solver for the slowness.
Disabled some constraints, leaving 2 groups of attached parts to each other. No constraints that prevent movement.
One group of parts are attached to a fixed part. Second group has only 7 parts attached to each other that are free to move in space.
The second group would still move very unreasonable slow.

The tests were done on official 0.20.1 binary:

OS: Ubuntu 20.04.5 LTS (ubuntu:GNOME/ubuntu)
Word size of FreeCAD: 64-bit
Version: 0.20.1.29410 (Git) AppImage
Build type: Release
Branch: (HEAD detached at 0.20.1)
Hash: f5d13554ecc7a456fb6e970568ae5c74ba727563
Python 3.10.5, Qt 5.15.4, Coin 4.0.0, Vtk 9.1.0, OCC 7.6.2
Locale: English/United States (en_US)
Installed mods: 
  * Assembly4 0.12.4
  * Assembly3 0.11.3

Added some traces to the Assembly3 code and figured out that most of the time is spent in recompute() function.
Cloned FreeCAD/master to compile it in debug to see the timings of the recompute, apparently the version I pulled is 0.21, but the behavior was the same:

OS: Ubuntu 20.04.5 LTS (ubuntu:GNOME/ubuntu)
Word size of FreeCAD: 64-bit
Version: 0.21.30735 (Git)
Build type: Debug
Branch: test
Hash: 7c51aa9749eddcfc0981feea3c3468560b88db22
Python 3.8.10, Qt 5.12.8, Coin 4.0.0, Vtk 7.1.1, OCC 7.3.0
Locale: English/United States (en_US)
Installed mods: 
  * Assembly4 0.12.4
  * Assembly3 0.11.3

Added traces to both C++ core functions and some in Assembly3 python code I came to conclusion that the slowdown in caused by the design that C++ and Python objects should always be synced. Apparently C++ ==> Python calls are not that fast as we want it to be, or the code executed in Python domain is very slow (we know it is, but the slowdown is way beyond my expectation).

So the Asm3 Python code calls core's C++ recompute(), which does some loops to prepare the objects that have to be recomputed and call their feature's recompute() function, which in turn calls extension's of those features (the execute function), which are implemented in Python...
Also, the fact that both C++ and Python objects always want to stay in sync, every change in a property, like "touched" or Placement cause immediate call to the other side to update the values, which adds alot of overhead.

With no constraints disabled, my test model have only 21 parts. FreeCAD's recompute function prepare 109 features to recompute (constraints, attachment elements and so on).
Each feature cause several ping-pong interactions between C++ and Python code to stay in sync.
I don't want to think how will it behave with hundreds of parts in the assembly :(

Forum thread with my findings:
https://forum.freecadweb.org/viewtopic.php?f=20&t=72904

Unless there is some magic in the code, I don't see any solution besides moving the code that is involved in the real-time behavior like the move operation to one side of the code, preferably to C++ to be faster.
That slowdown is a real negative factor comparing to other CAD solutions.
Python is great for the GUI and management operations like add/change/remove, but not good for computational stuff that affect the user experience.

I'll be happy to help with coding, but will need some guidance in preparing the infrastructure for the code where it should be moved to and etc...

Attaching tested assembly. Try to move the top carret.
Asm3-TimingTest.zip

More info added.
https://forum.freecadweb.org/viewtopic.php?f=20&t=72904&p=637066#p637066

Right now moving/recomputing a newly added link takes more than 10 seconds :(

Is there anything I can do to push further that issue?
More tests? Trying something in the code? Add traces?