DenisHen Posté(e) le 25 avril 2017 Posté(e) le 25 avril 2017 Bonjour à tous. Jusqu'à présent, j'avais une routine en LiSP qui fonctionnait très bien. Elle plaçait quelques données dans différents attributs des blocs. Cette macro ne m'a jamais posé problème, car je traitais que quelques blocs, mais là, j'ai 8500 blocs à traiter, et le code se met soudain à ralentir. Il traitait plus de cent blocs/seconde, mais arrivé à environ 4000 blocs, il se met sérieusement à ralentir et à 5000 bloc, il n'en traite plus que un par seconde... Arrivé à 5200, c'est 1 toutes les deux secondes... Et c'est de pire en pire... Si quelqu'un a une idée, une astuce voir un conseil, je suis preneur... Voici la boucle qui ralenti...: (princ "\nRemplissage des données géographiques des blocs.") (if (setq ss (ssget "_X" '((0 . "INSERT")))) (progn (setq i 0) (while (setq ent (ssname ss i)) (setq i (1+ i)) (if (= (cdr (assoc 0 elst)) "INSERT") (progn (setq elst (entget ent) dxf10 (assoc 10 elst) att (entget (entnext ent)) Coord (cdr (assoc 10 elst)) NomBlk (cdr (assoc 2 elst)) ) ;_ Fin de setq (princ "\nTraitement : ") (princ i) (ade_projsetsrc (ade_projgetwscode)) (ade_projsetdest "LL-RGF93") (setq pntLLRGF93 (ade_projptforward Coord)) ;;Ecriture des coordonnées dans un fichier CSV (write-line (strcat NomBlk "," (rtos (car pntLLRGF93) 2 15) "," (rtos (cadr pntLLRGF93) 2 15)) FileCSV) (while (/= (cdr (assoc 0 att)) "SEQEND") (cond ((= (cdr (assoc 2 att)) "X") (setq att (subst (cons 1 (rtos (car pntLLRGF93) 2 15)) (assoc 1 att) att)) (entmod att) ) ;_ Fin de cond ((= (cdr (assoc 2 att)) "Y") (setq att (subst (cons 1 (rtos (cadr pntLLRGF93) 2 15)) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "Z-TN") (setq att (subst (cons 1 (rtos (caddr Coord) 2 3)) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "NOMENTRGEO") (setq att (subst (cons 1 "CERENE") (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "DATERELEVE") (setq Now (menucmd "M=$(edtime,$(getvar,date),DD/MO/YYYY)")) (setq att (subst (cons 1 Now) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "NOMPRESTACERTIGEO") (setq att (subst (cons 1 NomOp) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "MARQUEAPP") (setq att (subst (cons 1 NomMateriel) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "NUMSERIEAPP") (setq att (subst (cons 1 NumMateriel) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "NUMSERIE") (setq att (subst (cons 1 NumMateriel) (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "INCERTXY") (setq att (subst (cons 1 "5cm") (assoc 1 att) att)) (entmod att) ) ((= (cdr (assoc 2 att)) "INCERTZ") (setq att (subst (cons 1 "5cm") (assoc 1 att) att)) (entmod att) ) ) ;_ Fin de cond (setq att (entget (entnext (cdr (assoc -1 att))))) ) ;_ Fin de while ) ;_ Fin de progn ) ;_ Fin de if ) ;_ Fin de while ) ;_ Fin de progn ) ;_ Fin de if Windows 11 / AutoCAD 2024 Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net). Davantage d'avantages, avantagent davantage (Bobby Lapointe). La connaissance s'accroît quand on la partage (Socrate). Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)
(gile) Posté(e) le 25 avril 2017 Posté(e) le 25 avril 2017 Salut, Tu dois pouvoir supprimer certaines chose inutiles comme le test :(if (= (cdr (assoc 0 elst)) "INSERT") vu que tu utilises un filtre de sélection (par ailleurs, la variable elst n'est pas renseignée à ce stade...). La variable dxf10 semble inutile. Tu peux aussi créer une variable (setq tag (cdr (assoc 2 att))) avant le (cond ...) pour éviter d'évaluer (cdr (assoc 2 att)) à chaque fois. Mais je ne suis pas certain que tout ça te fasse gagner énormément. Par ailleurs, je ne sais pas ce que font les fonctions LISP spécifque MAP (ade_*) et donc si elles sont "couteuses". Un autre truc à essayer, serait de stocker les données de chaque bloc dans une liste pendant la boucle (une chaîne de caractères par ligne) et d'écrire le fichier CSV à partir de cette liste dans une autre boucle (foreach). Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Patrick_35 Posté(e) le 25 avril 2017 Posté(e) le 25 avril 2017 Salut Peut-être en utilisant le vlispEssaye ceci (non testé) (princ "\nRemplissage des données géographiques des blocs.") (setq doc (vla-get-activedocument (vlax-get-acad-object))) (and (ssget "_X" '((0 . "INSERT")))) (progn (vlax-for ent (setq sel (vla-get-activeselectionset doc)) (ade_projsetsrc (ade_projgetwscode)) (ade_projsetdest "LL-RGF93") (setq pntLLRGF93 (ade_projptforward Coord)) ;;Ecriture des coordonnées dans un fichier CSV (write-line (strcat (vla-get-name ent) "," (rtos (car pntLLRGF93) 2 15) "," (rtos (cadr pntLLRGF93) 2 15)) FileCSV) (foreach att (vlax-invoke ent 'getattributes) (cond ((= (vla-get-tagstring att) "X") (vla-put-textstring att (rtos (car pntLLRGF93) 2 15)) ) ;_ Fin de cond ((= (vla-get-tagstring att) "Y") (vla-put-textstring att (rtos (cadr pntLLRGF93) 2 15)) ) ((= (vla-get-tagstring att) "Z-TN") (vla-put-textstring att (rtos (caddr Coord) 2 3)) ) ((= (vla-get-tagstring att) "NOMENTRGEO") (vla-put-textstring att "CERENE") ) ((= (vla-get-tagstring att) "DATERELEVE") (vla-put-textstring att (menucmd "M=$(edtime,$(getvar,date),DD/MO/YYYY)")) ) ((= (vla-get-tagstring att) "NOMPRESTACERTIGEO") (vla-put-textstring att NomOp) ) ((= (vla-get-tagstring att) "MARQUEAPP") (vla-put-textstring att NomMateriel) ) ((= (vla-get-tagstring att) "NUMSERIEAPP") (vla-put-textstring att NumMateriel) ) ((= (vla-get-tagstring att) "NUMSERIE") (vla-put-textstring att NumMateriel) ) ((= (vla-get-tagstring att) "INCERTXY") (vla-put-textstring att "5cm") ) ((= (vla-get-tagstring att) "INCERTZ") (vla-put-textstring att "5cm") ) ) ) ) (vla-delete sel) ) ) @+ Les Lisps de PatrickLe but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.Joseph Joubert, 1754-1824
DenisHen Posté(e) le 25 avril 2017 Auteur Posté(e) le 25 avril 2017 Bonjour à vous, et merci messieurs pour votre aide... En fait, dans ma routine, j'insérais les 8500 blocs, puis attribuais les 11 valeurs aux 8500 blocs et ensuite, écrivais les coordonnées des blocs dans un fichier .csv. Trois boucles... Mais grace à la réponse de (gile) sur un autre post, je fais tout en une seule fois, et ça ne prend que quelques minutes... EN une boucle... Encore merci à vous deux qui, tel des Zorro du LiSP, venez à notre secours... ;) Denis... Windows 11 / AutoCAD 2024 Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net). Davantage d'avantages, avantagent davantage (Bobby Lapointe). La connaissance s'accroît quand on la partage (Socrate). Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)
(gile) Posté(e) le 25 avril 2017 Posté(e) le 25 avril 2017 Puisqu'on parle d'optimisation, j'ai fait quelques tests avec benchmark dans le sens de ce que propose Patrick_35. Et j'étais curieux de voir ce que donnait la "nouvelle" fonction setpropertyvalue. J'ai donc écrit 3 fonctions qui établissent la valeur d'un attribut avec entmod (foo), vla-put-Textstring (bar) et setpropertyvalue (baz) : (defun foo (ent tag val / elst) (while (and (setq ent (entnext ent)) (= (cdr (assoc 0 (setq elst (entget ent)))) "ATTRIB") ) (if (= (cdr (assoc 2 elst)) tag) (entmod (subst (cons 1 val) (assoc 1 elst) elst)) ) ) ) (defun bar (blk tag val / atts) (foreach att (vlax-invoke blk 'GetAttributes) (if (= (vla-get-TagString att) tag) (vla-put-TextString att val) ) ) ) (defun baz (blk tag val) (vl-catch-all-apply 'setpropertyvalue (list blk tag val)) ) Sur un bloc avec 2 attributs, on note que si l'utilisation de Visual LISP est un peu plus rapide que entmod, c'est setpropertyvalue qui semble la plus rapide._$ (benchmark '((foo blk "ATT1" "FOO") (bar vl_blk "ATT1" "BAR") (baz blk "ATT1" "BAZ"))) Benchmarking .................Elapsed milliseconds / relative speed for 16384 iteration(s): (BAZ BLK "ATT2" "BAZ")........1404 / 1.46 <fastest> (BAR VL_BLK "ATT2" "BAR").....1748 / 1.17 (FOO BLK "ATT2" "FOO")........2043 / 1 <slowest> Mais avec un bloc ayant 12 attributs (de ATT1 à ATT12), l'écart se creuse :_$ (benchmark '((foo blk "ATT12" "FOO") (bar vl_blk "ATT12" "BAR") (baz blk "ATT12" "BAZ"))) Benchmarking .................Elapsed milliseconds / relative speed for 16384 iteration(s): (BAZ BLK "ATT12" "BAZ")........1389 / 2.73 <fastest> (BAR VL_BLK "ATT12" "BAR").....3400 / 1.12 (FOO BLK "ATT12" "FOO")........3791 / 1 <slowest> J'ai voulu pousser un peu avec une fonction utilisant entmod dans une fonction optimisée. Le fait d'utiliser une boucle (while ...) permet de sortir de la boucle dès que l'attribut a été trouvé. (defun foo2 (blk tag val / ent elst) (setq ent (entnext blk)) (while (and ent (= (cdr (assoc 0 (setq elst (entget ent)))) "ATTRIB") ) (if (= (cdr (assoc 2 elst)) tag) (progn (entmod (subst (cons 1 val) (assoc 1 elst) elst)) (setq ent nil) ) (setq ent (entnext ent)) ) ) ) Toujours avec le bloc ayant 12 attributs, mais en ciblant le premier bloc (condition optimale pour foo2)._$ (benchmark '((foo2 blk "ATT1" "FOO") (bar vl_blk "ATT1" "BAR") (baz blk "ATT1" "BAZ"))) Benchmarking .................Elapsed milliseconds / relative speed for 16384 iteration(s): (BAZ BLK "ATT1" "BAZ")........1373 / 2.48 <fastest> (FOO2 BLK "ATT1" "FOO").......1419 / 2.4 (BAR VL_BLK "ATT1" "BAR").....3401 / 1 <slowest>en ciblant le dernier bloc, la performance est logiquement équivalent à celle de foo qui parcourt tous les attributs. Ceci tendrait donc à montrer que l'utilisation de setpropertyvalue avec un étiquette d'attribut est équivalent à un accès direct, probablement dû l'utilisation dans l'implémentation d'une table de hachage ou d'un dictionnaire. Maintenant, il n'est pas certain que pour établir les valeurs de tous (ou presque) les attributs d'un bloc setpropertyvalue soit plus efficace si la table de hachage doit être recréée à chaque attribut... Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Patrick_35 Posté(e) le 25 avril 2017 Posté(e) le 25 avril 2017 Ceci tendrait donc à montrer que l'utilisation de setpropertyvalue avec un étiquette d'attribut est équivalent à un accès direct, probablement dû l'utilisation dans l'implémentation d'une table de hachage ou d'un dictionnaire. Maintenant, il n'est pas certain que pour établir les valeurs de tous (ou presque) les attributs d'un bloc setpropertyvalue soit plus efficace si la table de hachage doit être recréée à chaque attribut...Comme quoi, il ne faut pas rester sur ses acquis. Merci (gile) @+ Les Lisps de PatrickLe but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.Joseph Joubert, 1754-1824
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant