Author Topic: How to process SelectionSet faster?  (Read 6627 times)

0 Members and 1 Guest are viewing this topic.

litss

  • Guest
How to process SelectionSet faster?
« on: November 30, 2012, 03:53:42 AM »
I got a huge amount of triangles (3D face) need to be processed, which is over 100,000 elements. I am currently using the following stratigy:

Code: [Select]
(princ "\nPlease select 3Dface triangle:")
(setq ss1 (ssget ))
(setq n 0)
(repeat (sslength ss1)
(setq ent (ssname n ss1))
........
(setq n (1+ n))
)

But it is too time consuming. Almost half an hour to get all vertex coordinates from each element. Why whould it be so slow? Is there any way to make it faster?

Thanks.


Tharwat

  • Swamp Rat
  • Posts: 707
  • Hypersensitive
Re: How to process SelectionSet faster?
« Reply #1 on: November 30, 2012, 04:07:50 AM »
Code: [Select]
(if (setq ss1 (ssget ))
(repeat (setq n (sslength ss1))
(setq ent (ssname ss1 (setq n (1- n))))
........
     )
)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: How to process SelectionSet faster?
« Reply #2 on: November 30, 2012, 04:21:38 AM »
What are you doing inside the loop? The entget might be where most of the time is wasted. If so could your routine be redesigned not to need entget? I.e. just generate a new list to pass to entmod? Or even use the new properties methods.
 
Or could your routine be redesigned to use vla-objects? If so then using Method 5 from Lee's samples here might be faster.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: How to process SelectionSet faster?
« Reply #3 on: November 30, 2012, 04:35:53 AM »
E.g. here's something which uses the new properties functions (since 2012), it would return a list of lists (each nested list is the 4 vertex points of each selected 3dFace):
Code - Auto/Visual Lisp: [Select]
  1. (defun c:Test  (/ ss n vectors en)
  2.   (if (setq ss (ssget '((0 . "3DFACE"))))
  3.     (repeat (setq n (sslength ss))
  4.       (setq en      (ssname ss (setq n (1- n)))
  5.             vectors (cons
  6.                       (mapcar '(lambda (idx)
  7.                                  (mapcar '(lambda (dim)
  8.                                             (getpropertyvalue en "Coordinates" idx dim))
  9.                                          '("X" "Y" "Z")))
  10.                               '(0 1 2 3))
  11.                       vectors))))
  12.   vectors)
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

David Bethel

  • Swamp Rat
  • Posts: 656
Re: How to process SelectionSet faster?
« Reply #4 on: November 30, 2012, 06:57:53 AM »
Getting AutoLISP to do anything 100,000 times is time consuming. 

Can you filter the (ssget) call?

Can you divide and conquer based on point locations (ssget "C" ....)

Are you using known slow processes ? ie  append   member   

-David
R12 Dos - A2K

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How to process SelectionSet faster?
« Reply #5 on: November 30, 2012, 08:30:21 AM »
I agree with David.
Also use function
Code: [Select]
(mapcar (function (lambda (dim)AND compile your code!!!!!!


I believe the while loop is faster than repeat.
Code: [Select]
       (setq i -1)
       (while (setq ename (ssname ss (setq i (1+ i))))
         (setq result (cons ename result))
       )
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12905
  • London, England
Re: How to process SelectionSet faster?
« Reply #6 on: November 30, 2012, 09:08:41 AM »
I believe the while loop is faster than repeat.

repeat will be faster when compiled  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How to process SelectionSet faster?
« Reply #7 on: November 30, 2012, 11:12:48 AM »
Thanks Lee, all my test were uncompiled.  :-(
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

BlackBox

  • King Gator
  • Posts: 3770
Re: How to process SelectionSet faster?
« Reply #8 on: November 30, 2012, 12:15:07 PM »
Perhaps I've overlooked something, but for such a large selection, why not instead just iterate the ActiveSelectionSet Object  :??

Code - Auto/Visual Lisp: [Select]
  1.                          (vla-get-activedocument
  2.                            (vlax-get-acad-object)
  3.                            )
  4.                          )
  5.                     )
  6.   ;; <-- Do work
  7.   )
  8.  
"How we think determines what we do, and what we do determines what we get."

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: How to process SelectionSet faster?
« Reply #9 on: November 30, 2012, 11:16:26 PM »
RM, that was my suggestion. But it depends on what's going on inside the loop. If he needs to convert to and fro between ename, dxf data list and vla-object - then it might not be faster at all. That's why i gave the sample using the new properties function. Thus he can still use the normal selection set handling, but not need to use the time consuming entget / entmod - those take time since they get (and usually set) using the entire DXF data list, whereas the properties functions only use the relevant property value.

Good points about using function & compiling. Actually the while / repeat thing is pretty strange. I'd have imagined that repeat would be faster even uncompiled - since it only checks once. But I think what happens is internally it uses a counter and checks that. Whereas when it's compiled it uses a CPU register to repeat itself by the required number of times - i.e. lots faster than an if statement.

Anyhoo ... I don't think we can get much faster without further input from the OP. Simply iterating through a selection set is usually the least time consuming part of the program. Usually it's the data extraction / modification / manipulation which takes the lion's share of the cpu time. So until we know what he wants to do inside each iteration we can't give definitive answers.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: How to process SelectionSet faster?
« Reply #10 on: December 01, 2012, 12:31:49 AM »
Tried to figure out which is the fastest iteration through a selection set - without actually doing anything. So used both the while & repeat loops on getting the dxf list (entget) as well as only the ename in preparation for getpropertyvalue. Also added the vlax selection set iteration.
Code: [Select]
Testing on selection set of 1000 entities
Benchmarking ....... done for 1024 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(SSTEST_WHILEPROP)                            1024      1029      1029    168.80
(SSTEST_REPEATPROP)                           1024      1185      1185    146.58
(SSTEST_VLA)                                   256      1902      7608     22.83
(SSTEST_WHILEDXF)                              128      1857     14856     11.69
(SSTEST_REPEATDXF)                             128      1919     15352     11.31
(SSTEST_VLA_PROP)                               16      1077     68928      2.52
(SSTEST_VLA_DXF)                                 8      1357    173696      1.00
--------------------------------------------------------------------------------
And compiled
Code: [Select]
Testing on selection set of 1000 entities
Benchmarking ....... done for 2048 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(SSTEST_REPEATPROP)                           2048      1280      1280    284.00
(SSTEST_WHILEPROP)                            2048      1577      1577    230.51
(SSTEST_VLA)                                   256      1888     15104     24.07
(SSTEST_WHILEDXF)                              128      1794     28704     12.66
(SSTEST_REPEATDXF)                             128      1809     28944     12.56
(SSTEST_VLA_PROP)                               16      1075    137600      2.64
(SSTEST_VLA_DXF)                                 8      1420    363520      1.00
--------------------------------------------------------------------------------
It doesn't seem as if the difference between repeat & while is significant in comparison to what you actually do inside / outside the loop. As expected the convert from vla-object is simply stupidly slow (even with compiling). Pure VLA is about 2x faster than working with DXF data, but the ename only is 100x faster than that.

But that's only giving half the story. See what happens if I add a piece of code to each of the defuns. I'm adding a piece which extracts the Layer Name / LayerEname:
Code - Auto/Visual Lisp: [Select]
  1. (cdr (assoc 8 ed)) ;For the dxf defuns
  2. (vla-get-Layer eo) ;For the vla defun
  3. (getpropertyvalue en "LayerId") ;For the Prop defuns - returns the ename of the layer, not the layer name
Here's the test results
Code: [Select]
Testing on selection set of 1000 entities
Benchmarking ....... done for 64 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(SSTEST_WHILEDXF)                               64      1202      1202      9.14
(SSTEST_REPEATDXF)                              64      1233      1233      8.91
(SSTEST_VLA)                                    16      1154      4616      2.38
(SSTEST_WHILEPROP)                              16      1700      6800      1.62
(SSTEST_REPEATPROP)                             16      1701      6804      1.61
(SSTEST_VLA_PROP)                                8      1372     10976      1.00
(SSTEST_VLA_DXF)                                 8      1373     10984      1.00
--------------------------------------------------------------------------------
_$ (vlisp-compile 'st "SelectTest.LSP")
T
_$ (load "SelectTest.FAS")
SSTEST_VLA_PROP
_$ (c:RunSSTest)

Testing on selection set of 1000 entities
Benchmarking ....... done for 128 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(SSTEST_WHILEDXF)                              128      1918      1918     11.32
(SSTEST_REPEATDXF)                             128      1950      1950     11.13
(SSTEST_VLA)                                    16      1139      9112      2.38
(SSTEST_REPEATPROP)                             16      1606     12848      1.69
(SSTEST_WHILEPROP)                              16      1654     13232      1.64
(SSTEST_VLA_DXF)                                 8      1342     21472      1.01
(SSTEST_VLA_PROP)                                8      1357     21712      1.00
--------------------------------------------------------------------------------
See what I mean by it's more important about the internals of the loop than the loop itself? E.g. unexpectedly the dxf actually becomes faster than the vla - by 5x. And the prop becomes stupidly slow - nearly comparable to the converted defuns.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How to process SelectionSet faster?
« Reply #11 on: December 01, 2012, 07:38:38 AM »
Interesting test.  8-)
Thanks irneb
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: How to process SelectionSet faster?
« Reply #12 on: December 01, 2012, 08:27:30 AM »
Glad to. Actually I wanted to find out if those new functions are faster - as I woud've expected. From this it actually seems a lot slower than using the entget or even vla.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: How to process SelectionSet faster?
« Reply #13 on: December 01, 2012, 08:54:21 AM »
Actually it even becomes stranger than that. Trying to test more in line with what the OP had I altered the code to extract the vertex points of 3dFace entities.

It seems here the vla method does the trick:
Code: [Select]
Testing on selection set of 1000 entities
Benchmarking ....... done for 32 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(SSTEST_VLA)                                    32      1654      1654     27.46
(SSTEST_WHILEDXF)                               16      1404      2808     16.18
(SSTEST_REPEATDXF)                              16      1420      2840     15.99
(SSTEST_VLA_DXF)                                 8      1670      6680      6.80
(SSTEST_VLA_PROP)                                2      1622     25952      1.75
(SSTEST_REPEATPROP)                              2      1747     27952      1.63
(SSTEST_WHILEPROP)                               2      2839     45424      1.00
--------------------------------------------------------------------------------
And when compiled it seems more pronounced
Code: [Select]
Testing on selection set of 1000 entities
Benchmarking ....... done for 16 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(SSTEST_VLA)                                    16      1060      1060     22.72
(SSTEST_WHILEDXF)                               16      2029      2029     11.87
(SSTEST_REPEATDXF)                              16      2058      2058     11.70
(SSTEST_VLA_DXF)                                 4      1279      5116      4.71
(SSTEST_REPEATPROP)                              1      1014     16224      1.48
(SSTEST_VLA_PROP)                                1      1076     17216      1.40
(SSTEST_WHILEPROP)                               2      3011     24088      1.00
--------------------------------------------------------------------------------
It must be that optimized method of generating the list of points.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: How to process SelectionSet faster?
« Reply #14 on: December 01, 2012, 11:02:46 AM »
irneb
Your sstest_vla returns wrong result (you typed cords instead coords...)

Here are another 2 functions to test
Code: [Select]
(defun SSTest_ForeachDXF (/ en ed lst)
  (foreach x (ssnamex ss)
    (setq lst (cons
((lambda (en)
   (list
     (cdr (assoc 10 en))
     (cdr (assoc 11 en))
     (cdr (assoc 12 en))
     (cdr (assoc 13 en))
   )
)
  (entget (cadr x))
)
lst
      )
    )
  )
)


(defun SSTest_MapcarDXF ()
  (mapcar
    (function
      (lambda (x)
((lambda (en)
   (list
     (cdr (assoc 10 en))
     (cdr (assoc 11 en))
     (cdr (assoc 12 en))
     (cdr (assoc 13 en))
     )
   )
  (entget (cadr x)))
)
      )
    (ssnamex ss)
    )
  )
Note the differences in colecting coords...
Using
Code: [Select]
(mapcar (function (lambda (code) (cdr (assoc code ed)))) '(10 11 12 13))will place my functions at the very bottom benchmark list