-
Notifications
You must be signed in to change notification settings - Fork 56
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
[QUESTION] pycatia perfo vs VBA #205
Comments
Some more information / context? I don't understand why there would be any difference as they're both accessing the COM object. |
Same for me. But it is just a constatation. |
I noticed the same, especially when dealing with many many user ref props. It's on my schedule to investigate this problem, but what I've found out so far isn't consistent, so I think I'm on a goose chase for now. An interesting fact tho: I didn't have any perfomance issues when I used a very stripped version of pycatia. But I didn't test it under the same premisses as I do now. |
Yes.
Nope. Believe it or not I rarely do any CATIA scripting, pycatia or VBA. I've been thinking this over the past week or so and my guess is that any noticeable performance difference is probably in those class methods that use If only I / we / someone could figure out a way to remove the need for it. I've searched again today and no real luck. Lots of clues but nothing I can get to work. As a test for the speed I created a part with 500 points in: """
Creates n random points in a new geometric set 'points'.
Requires CATIA V5 to be running and a CATPart active.
"""
import time
from random import randint
from pycatia import catia
from pycatia.mec_mod_interfaces.part_document import PartDocument
MIN = 0
MAX = 10000
TOTAL_POINTS = 500
start = time.time()
caa = catia()
active_document = PartDocument(caa.active_document.com_object)
part = active_document.part
hsf = part.hybrid_shape_factory
hbs = part.hybrid_bodies
gs_points = hbs.add()
gs_points.name = 'points'
for i in range(1, TOTAL_POINTS+1):
new_point = hsf.add_new_point_coord(randint(MIN, MAX), randint(MIN, MAX), randint(MIN, MAX))
gs_points.append_hybrid_shape(new_point)
part.update()
end = time.time()
print(end-start) 11 seconds I then have a script that uses import time
from pycatia import catia
from pycatia.hybrid_shape_interfaces.point import Point
from pycatia.mec_mod_interfaces.part_document import PartDocument
from pycatia.enumeration.enumeration_types import geometrical_feature_type
from pycatia.space_analyses_interfaces.inertia import Inertia
start = time.time()
caa = catia()
application = caa.application
part_doc = PartDocument(application.active_document.com_object)
part = part_doc.part
spa_workbench = part_doc.spa_workbench()
hsf = part.hybrid_shape_factory
hbs = part.hybrid_bodies
hb_points = hbs.item('points')
shapes = hb_points.hybrid_shapes
for shape in shapes:
gft = hsf.get_geometrical_feature_type(shape)
gft_text = geometrical_feature_type[gft]
if gft_text == 'Point':
p = Point(shape.com_object)
coord = p.get_coordinates()
print(shape.name, coord)
end = time.time()
print(end-start) 23 seconds. For just 500 points this took my machine 23 seconds. I think that's slow? But I don't know. I tried writing the equivalent in VBA but gave up as I just never really learned that side of things and writing VBA makes me feel dirty. Perhaps one of you could so we can do a real comparison?
That framework looks pretty much identical to pycatia so why would it be any different? You've just got less modules which would possibly show a small difference in RAM usage and startup time. I doubt it would be enough to show a significance difference in execution time for a script hundreds/thousands of functions. But I'd be happy to see some evidence. Less conjecture and more examples my friends. ❤️ 😄 |
Also, for completeness we should time the point creation script too and create a VBA equivalent of that. This is because the point creation script doesn't use any edited above reply to include the point creation script time. |
Hi, |
No problem. 👍 |
I did some testing comparing your code to a VBA version. pycatia ~ 5s Something I noticed was that when using pycatia the display is refreshed. You can see the points created (if that makes sense). When using VBA however you don't. I tried caa.refresh_display = False, but no difference. Sub CATMain()
Dim MIN
Dim MAX
Dim TOTAL_POINTS
Dim i
Dim startTime
Dim endTime
Dim catia
Dim activeDocument
Dim part
Dim hybridShapeFactory
Dim hybridBodies
Dim gsPoints
Dim newPoint
MIN = 0
MAX = 10000
TOTAL_POINTS = 500
startTime = Timer
Set catia = GetObject(, "CATIA.Application")
Set activeDocument = catia.ActiveDocument
Set part = activeDocument.Part
Set hybridShapeFactory = part.HybridShapeFactory
Set hybridBodies = part.HybridBodies
Set gsPoints = hybridBodies.Add()
gsPoints.Name = "points"
For i = 1 To TOTAL_POINTS
Set newPoint = hybridShapeFactory.AddNewPointCoord(Int((MAX - MIN + 1) * Rnd + MIN), Int((MAX - MIN + 1) * Rnd + MIN), Int((MAX - MIN + 1) * Rnd + MIN))
gsPoints.AppendHybridShape newPoint
Next
part.Update()
endTime = Timer
MsgBox "Elapsed time: " & (endTime - startTime) & " seconds"
End Sub |
Great stuff. I'll have a play with this tomorrow. Interesting what you say about the screen refresh. There's a pycatia script I was running the other day that I swear was faster by disabling the refresh_display, seemed to work. That was generating points I'm sure. Also, we should really remove the random point generation outside of the timing. Probably won't make a noticeable difference but would be more scientific. |
Correction: |
So, thanks to this I got exposed to dealing with early and late bindings for the first time. I will never be the same. Hahaha I did a test with a mix off early bindings, did not do much ~0.3s (NOTE: if you run this you have to clear gen_py afterwards otherwise it get stuck to early-bindings). After creating the bindings I commented it out: from win32com.client import Dispatch, CastTo
from win32com.client.dynamic import DumbDispatch
from timeit import default_timer as timer
from random import randint
def GetRightDispatch(o):
return Dispatch(DumbDispatch(o))
MIN = 0
MAX = 10000
TOTAL_POINTS = 500
start = timer()
caa = Dispatch('CATIA.Application')
caa.RefreshDisplay = False
active_document = caa.ActiveDocument
part = Dispatch(active_document.Part)
#part = GetRightDispatch(active_document.Part)
#part = CastTo(part, "Part")
hsf = Dispatch(part.HybridShapeFactory)
#hsf = GetRightDispatch(part.HybridShapeFactory)
#hsf = CastTo(hsf, "HybridShapeFactory")
hbs = Dispatch(part.HybridBodies)
#hbs = GetRightDispatch(part.HybridBodies)
#hbs = CastTo(hbs, "HybridBodies")
gs_points = hbs.Add()
gs_points.Name = 'points'
for i in range(1, TOTAL_POINTS+1):
new_point = hsf.AddNewPointCoord(i, i, i)
gs_points.AppendHybridShape(new_point)
part.Update()
end = timer()
caa.RefreshDisplay = True
print(end - start) When running both scripts, yours and this, I noted that (at random) the Geometrical Set was collapsed when the points was created. |
Interesting. Thanks so much for posting your findings. I stated:
It wasn't generating points, it was for speeding up the drawing of a template into the Drawing background for my little side project pycatia-tools (shamless plug). Jumping about from project to project is frying my little brain. 😃 |
Finally had the time to play around a bit with this issue. I wrote 3 scripts, one with
I added all scripts as zip so I don't clutter this issue with code: time_comp_240707.zip Setup:
Results:
Some things I found noteworthy:
Sidenotes:
Edit: Corrected values in result table |
Great work @deloarts.
That does make sense to me. Like a database lookup by id rather than string.
A noticeable difference? That does surprise me. Recently, to pycatia's dispatch method I added pythoncom.CoInitialize(). This was so I could use pycatia in a GUI application (wouldn't work without it). Could you run your manual dispatch version of the script with this added? If this is slowing things down I'll update pycatia to make that call optional. I'll do it myself later this week using your script if you haven't time. It didn't help prevent the behavior I have noted below. So, this may or may not be related ... I've just run a script opening and closing a document a 1000 times in a for loop and I noticed that CATIA V5 kind of freezes every so often (no obvious pattern I can see). The times were not consistent at all! So, I did a bit of playing: import time
import statistics
from pathlib import Path
from pycatia import catia
def open_document(file: Path, number_of_tries:int):
times = []
caa = catia()
caa.logger.disabled = True
documents = caa.documents
for i in range(number_of_tries):
start = time.time()
document = documents.open(test_file)
document.close()
end = time.time()
times.append(end-start)
return times
test_file = Path(r'C:\Users\evereux\cloud\pycatia\__archive__\Part1.CATPart')
number_of_tries = 100
times = open_document(test_file, number_of_tries)
print(f'TIMES_REUSE: The fastest opening time was {min(times)}.')
print(f'TIMES_REUSE: The slowest opening time was {max(times)}.')
print(f'TIMES_REUSE: The slowest opening time was {statistics.mean(times)}.')
|
Just another thought .. when comparing VB versus Python I don't think we should allow anything to output to terminal as this will slow things down. For example, disable logging I think I'm the only one that has done that above though. d'oh. |
Hello, Tests done with python, python_alt, vb.net, catvba for 500 and 5000 points (yes, my laptop is very efficient and the results are more significant with 5000 points 😜)
You will find below used scripts for these tests. Python import time
from random import randint
##########################################################
# insert syspath to project folder so examples can be run.
# for development purposes.
import os
import sys
from pathlib import Path
sys.path.insert(0, os.path.abspath('..\\pycatia'))
##########################################################
from pycatia import catia
from pycatia.mec_mod_interfaces.part_document import PartDocument
from pycatia.mec_mod_interfaces.part import Part
from pycatia.hybrid_shape_interfaces.hybrid_shape_factory import HybridShapeFactory
from pycatia.mec_mod_interfaces.hybrid_bodies import HybridBodies
def cat_main():
min_val = 0
max_val = 10000
total_points = 5000
start_time = time.time()
# Get the CATIA application and active document
cat = catia()
cat.refresh_display = False
# docs = Documents(cat.documents.com_object)
part_doc = PartDocument(cat.active_document.com_object)
part = Part(part_doc.part.com_object)
hybrid_shape_factory = HybridShapeFactory(part.hybrid_shape_factory.com_object)
hybrid_bodies = HybridBodies(part.hybrid_bodies.com_object)
# Create a new hybrid body and set its name
gs_points = hybrid_bodies.add()
[gs_points.name](https://github.com/evereux/pycatia/issues/gs_points.name) = "points"
for i in range(1, total_points +1):
# Generate random coordinates for each point
x, y, z = (randint(min_val, max_val), randint(min_val, max_val), randint(min_val, max_val))
# Add a new point to the hybrid body
new_point = hybrid_shape_factory.add_new_point_coord(x, y, z)
gs_points.append_hybrid_shape(new_point)
part.update()
end_time = time.time()
elapsed_time = end_time - start_time
# cat.refresh_display = True
print(f"Elapsed time: {elapsed_time:.2f} seconds")
if __name__ == "__main__":
cat_main() Python_alt from win32com.client import Dispatch, CastTo
from win32com.client.dynamic import DumbDispatch
from timeit import default_timer as timer
from random import randint
def GetRightDispatch(o):
return Dispatch(DumbDispatch(o))
MIN = 0
MAX = 10000
TOTAL_POINTS = 5000
start = timer()
caa = Dispatch('CATIA.Application')
caa.RefreshDisplay = False
active_document = caa.ActiveDocument
part = Dispatch(active_document.Part)
#part = GetRightDispatch(active_document.Part)
#part = CastTo(part, "Part")
hsf = Dispatch(part.HybridShapeFactory)
#hsf = GetRightDispatch(part.HybridShapeFactory)
#hsf = CastTo(hsf, "HybridShapeFactory")
hbs = Dispatch(part.HybridBodies)
#hbs = GetRightDispatch(part.HybridBodies)
#hbs = CastTo(hbs, "HybridBodies")
gs_points = hbs.Add()
gs_points.Name = 'points'
for i in range(1, TOTAL_POINTS+1):
# Generate random coordinates for each point
x, y, z = (randint(MIN, MAX), randint(MIN, MAX), randint(MIN, MAX))
# Add a new point to the hybrid body
new_point = hsf.AddNewPointCoord(x, y, z)
gs_points.AppendHybridShape(new_point)
part.Update()
end = timer()
caa.RefreshDisplay = True
print(end - start) Vb.net Imports System.Diagnostics
Imports MECMOD
Imports INFITF
Imports PARTITF
Imports HybridShapeTypeLib
Module Module1
Sub Main()
Dim MIN
Dim MAX
Dim TOTAL_POINTS
Dim i As Integer
Dim startTime
Dim endTime
Dim CATIA As Application
MIN = 0
MAX = 10000
TOTAL_POINTS = 500
startTime = Timer
CATIA = GetObject(, "CATIA.Application")
CATIA.RefreshDisplay = False
' Récupérer le document actif
Dim partDocument As PartDocument
partDocument = CATIA.ActiveDocument
' Récupérer la partie active
Dim part As Part
part = partDocument.Part
' Récupérer la collection des bodies
Dim bodies As Bodies
bodies = part.Bodies
' Créer un nouveau set géométrique
Dim hybridBodies As HybridBodies
hybridBodies = part.HybridBodies
Dim hybridBody As HybridBody
hybridBody = hybridBodies.Add()
hybridBody.Name = "points"
' Créer un point
Dim hybridShapeFactory As HybridShapeFactory
hybridShapeFactory = part.HybridShapeFactory
Dim point As HybridShapePointCoord
Dim random As New Random()
Dim x As Double
Dim y As Double
Dim z As Double
For i = 1 To TOTAL_POINTS
x = random.NextDouble() * 1000
y = random.NextDouble() * 1000
z = random.NextDouble() * 1000
point = hybridShapeFactory.AddNewPointCoord(x, y, z)
' Ajouter le point au set géométrique
hybridBody.AppendHybridShape(point)
Next
' Mettre à jour la partie
part.Update()
endTime = Timer
CATIA.RefreshDisplay = True
MsgBox("Temps d'exécution : " & (endTime - startTime) & " Secondes")
End Sub
End Module Catvba Sub CATMain()
Dim MIN
Dim MAX
Dim TOTAL_POINTS
Dim i
Dim startTime
Dim endTime
Dim catia
Dim activeDocument
Dim part
Dim hybridShapeFactory
Dim hybridBodies
Dim gsPoints
Dim newPoint
MIN = 0
MAX = 10000
TOTAL_POINTS = 500
startTime = Timer
Set catia = GetObject(, "CATIA.Application")
Set activeDocument = catia.activeDocument
Set part = activeDocument.part
Set hybridShapeFactory = part.hybridShapeFactory
Set hybridBodies = part.hybridBodies
Set gsPoints = hybridBodies.Add()
gsPoints.Name = "points"
For i = 1 To TOTAL_POINTS
Set newPoint = hybridShapeFactory.AddNewPointCoord(Int((MAX - MIN + 1) * Rnd + MIN), Int((MAX - MIN + 1) * Rnd + MIN), Int((MAX - MIN + 1) * Rnd + MIN))
gsPoints.AppendHybridShape newPoint
Next
part.Update
endTime = Timer
MsgBox "Elapsed time: " & (endTime - startTime) & " seconds"
End Sub Best regards |
Thanks @Djey51!
you're not kidding! 😄 |
Hello,
Is there some optimization to follow to obtain better performances with pycatia?
When I use the same macro developed in python with pycatia than one developed in VBA, I can see that the pycatia one is slower (next to 2x) than the VBA one.
Do you have some tips and tricks for me please?
Thanks
The text was updated successfully, but these errors were encountered: