Author Topic: Demand Loading Files - a solution  (Read 8698 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Demand Loading Files - a solution
« Reply #15 on: April 21, 2012, 11:40:07 AM »
I look forward to Comments

Since you asked for feedback, here is my constructive criticism and suggestions:



Problem:
Code - Auto/Visual Lisp: [Select]
  1. (setq cmdpfile (strcat "\"" cmdfile "\""))
  2.  
  3. ...
  4.  
  5. "(if (KDUB:autoloaderFindFile "
  6. cmdpfile
  7. ")"

This will fail if the user provides a filepath containing backslashes instead of forward-slashes, i.e.:

Code - Auto/Visual Lisp: [Select]
  1. (KDUB:autolspload "C:\\MyFolder\\MyLISP.lsp" '(("c:mylisp")))

This is the same bug that is present in the AutoLISP autoload function.

Possible Solution:

Code - Auto/Visual Lisp: [Select]
  1. (setq cmdpfile (strcat "\"" (vl-string-translate "\\" "/" cmdfile) "\""))



Suggestion:

Use of foreach over mapcar to iterate over variable cmdlst.

foreach will outperform mapcar when compiled, and will not require the anonymous lambda function so may be clearer. Also, since you are not using the return of mapcar, in my opinion, the code is more readable using foreach.



Suggestion:

Code - Auto/Visual Lisp: [Select]
  1.            ...
  2.                  varlst (cdr cmdlst1)
  3.                  arglst ""
  4.            )
  5.            (if varlst
  6.               (foreach var varlst
  7.                  (setq arglst (strcat arglst var " "))
  8.               )
  9.            )
  10.            ...
  11.                        " ("
  12.                        arglst
  13.                        " / tst)"

This could be shortened to perhaps:

Code - Auto/Visual Lisp: [Select]
  1. (setq arglst (vl-princ-to-string (append (cdr cmdlst1) '("/" "tst"))))



Suggestion:

To avoid the issues encountered with escaping backslashes and converting the argument list to a string, consider replacing this:

Code - Auto/Visual Lisp: [Select]
  1. (if (not (eval (read cmdnam)))
  2.               (eval
  3.                  (read
  4.                     (strcat
  5.                        "(defun "
  6.                        cmdnam
  7.                        " ("
  8.                        arglst
  9.                        " / tst)"
  10.                        "(princ \"\nInitializing....\")"
  11.                        "(setq tst "
  12.                        cmdnam
  13.                        ")"
  14.                        "(if (KDUB:autoloaderFindFile "
  15.                        cmdpfile
  16.                        ")"
  17.                        (if (= (strcase apptyp) "LSP")
  18.                           (strcat "(progn (load " cmdpfile ")")
  19.                           (strcat "(progn (ARXload "
  20.                                   cmdpfile
  21.                                   ")"
  22.                           )
  23.                        )
  24.                        "(if (/= tst "
  25.                        cmdnam
  26.                        ")"
  27.                        "("
  28.                        cmdnam
  29.                        " "
  30.                        arglst
  31.                        ")"
  32.                        "(KDUB:autoloaderNoReDefun "
  33.                        "\""
  34.                        apptyp
  35.                        "\""
  36.                        " "
  37.                        "\""
  38.                        cmdnam
  39.                        "\""
  40.                        ")
  41.                              )
  42.                          )"
  43.                        "(KDUB:autoloaderNoFile "
  44.                        cmdpfile
  45.                        ")
  46.                            )"
  47.                        ")"
  48.                     )
  49.                  )
  50.               )
  51.            )

With something like:

Code - Auto/Visual Lisp: [Select]
  1. (if (not (eval (setq cmdsym (read cmdnam))))
  2.             (eval
  3.                 (list 'defun cmdsym (append varlst '(/ tst))
  4.                    '(princ "\nInitializing....")
  5.                     (list 'setq 'tst cmdsym)
  6.                     (list 'if (list 'KDUB:autoloaderFindFile cmdfile)
  7.                         (list 'progn
  8.                             (if (= (strcase apptyp) "LSP")
  9.                                 (list 'load    cmdfile)
  10.                                 (list 'arxload cmdfile)
  11.                             )
  12.                             (list 'if (list '/= 'tst cmdsym)
  13.                                 (cons cmdsym varlst)
  14.                                 (list 'KDUB:autoloaderNoReDefun apptyp cmdnam)
  15.                             )
  16.                         )
  17.                         (list 'KDUB:autoloaderNoFile cmdfile)
  18.                     )
  19.                 )
  20.             )
  21.         )

So the function may become:

Code - Auto/Visual Lisp: [Select]
  1. (defun KDUB:autoloader ( apptyp cmdfile cmdlst / cmdnam cmdsym varlst )
  2.     (foreach cmdlst1 cmdlst
  3.         (setq cmdnam (car cmdlst1)
  4.               varlst (mapcar 'read (cdr cmdlst1))
  5.         )
  6.         (if (not (eval (setq cmdsym (read cmdnam))))
  7.             (eval
  8.                 (list 'defun cmdsym (append varlst '(/ tst))
  9.                    '(princ "\nInitializing....")
  10.                     (list 'setq 'tst cmdsym)
  11.                     (list 'if (list 'KDUB:autoloaderFindFile cmdfile)
  12.                         (list 'progn
  13.                             (if (= (strcase apptyp) "LSP")
  14.                                 (list 'load    cmdfile)
  15.                                 (list 'arxload cmdfile)
  16.                             )
  17.                             (list 'if (list '/= 'tst cmdsym)
  18.                                 (cons cmdsym varlst)
  19.                                 (list 'KDUB:autoloaderNoReDefun apptyp cmdnam)
  20.                             )
  21.                         )
  22.                         (list 'KDUB:autoloaderNoFile cmdfile)
  23.                     )
  24.                 )
  25.             )
  26.         )
  27.     )
  28.     nil
  29. )



Niggle:

You have an extra "\"" in this function:

Code - Auto/Visual Lisp: [Select]
  1. (DEFUN KDUB:autoloaderNoReDefun (apptyp cmdnam)
  2.  (ALERT (STRCAT "Syntax error in KDUB:Auto"
  3.                 (STRCASE apptyp)
  4.                 "Load for function/command:\n\n\""
  5.                 "\""
  6.                 (STRCASE cmdnam)
  7.                 "\""
  8.         )
  9.  )
  10. )



Take from my comments what you will :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Demand Loading Files - a solution
« Reply #16 on: April 25, 2012, 08:40:24 AM »
Take from my comments what you will :-)

Or take nothing

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Demand Loading Files - a solution
« Reply #17 on: April 25, 2012, 08:42:20 AM »

 :oops: Thanks Lee for the comments.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

andrew_nao

  • Guest
Re: Demand Loading Files - a solution
« Reply #18 on: April 25, 2012, 09:06:03 AM »
is faster startup the only benefit of loading personal files with a partial menuload
rather then having your files load in "yourmenu.mnl"?

right now i have files loading from ALL over. some from acaddoc, some from "mymenu.mnl" and some functions put in a lisp file that is loaded AFTER acad is opened.
its a mess IMO and i would like to clean it up but my menu is sooooo customized that i dont load any enterprise or partial menus, just 1 main custom menu and thats it.


seeing this post caught my attention so i will be following it and re-reading it over and over

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Demand Loading Files - a solution
« Reply #19 on: April 25, 2012, 09:15:10 AM »
I'd use a 'Startup.mnu" and MNL which has the sole responsibility of managing the load stubs and alias definitions.


There is a new method of Autoloading files in 2013 which involves using specific folders and XML files to control the loading.
The system looks interesting but may not be suitable for the casual customiser.

Regards
Kerry
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Demand Loading Files - a solution
« Reply #20 on: April 30, 2012, 03:46:43 AM »
is faster startup the only benefit of loading personal files with a partial menuload
rather then having your files load in "yourmenu.mnl"?
There's no efficiency benefit between adding your code to a "Custom".MNL, or AcadDoc.LSP, or S::Startup, or whatever else (or at least negligible).

The main issue about where you place these startup loading calls is about "portability". It's much easier to maintain your code if it's in one place, and having it in a MNL linked with your own partial MNU/CUI/CUIx makes it a "quick" task to install your lisps (and other) into another PC / Upgrade. I.e. instead of "debugging" each item to see if you need to copy-n-paste yet another portion of code into your new Acad.LSP or (G-forbid) adding yet another LSP into your Stratup-Suite ... you can simply load your MNU/CUI(x) as partial into the new ACad. That way you still get the full new CUI from your version of ACad (including all the new commands) and on top of that all your customizations. If you simply recreate a new Primary CUI/MNU you'd either miss out on some of the upgrade features or have to import them each time you upgrade.

Regarding adding a path to your support folders: It's no a bad idea, as it makes these load calls a lot simpler. Just remember to ensure that such paths are actually available. A lot of slow loading is due to paths in the support folders not being available (e.g. Network not connected / faulty, or even just a renamed path somewhere). If such path is not available, acad still tries to load the file by searching through each of those support folders - waiting for Winblows to error out an tell acad it's not found (for each of those folders) - thus it could drastically slow down startup and opening of DWGs  :realmad: , even with the fastest possible PC. The idea around obtaining the path from the CUI is twofold: (1) It makes installation even easier as there's only one thing to do (i.e. load the CUI); (2) If the path cannot be found, then the CUI would not have been loaded in the first place - so less slow loading (theoretically  :pissed: ).

Regarding use of load as opposed to autoload: Generally there's not much difference - especially with large RAM and fast PCs. I just tend to try not to load unnecessary stuff as much as possible. The AutoLoad idea makes for one case where you can have the function available but not yet loaded into RAM. Unfortunately its a lot more complex, and as shown has quite a few problems of its own (not insurmountable but still  ::) ). My rule of thumb is to load everything which needs to be loaded from the start (e.g. reactors, aliases, redefinitions of commands, etc.) and autoload those things which are only used once in a while (e.g. special extra commands, library functions only needed in special cases, etc.). That way I can have all my commands / library functions run smoothly with a minimal impact on load times and RAM use.

But definitely you need to keep your customizations as structured as possible. A messy list of LSPs and folders can only steer you into trouble, no matter what method you use to load them. A little bit of forethought could save endless headaches later. It becomes an exponential task with larger collections of customizations, but the debugging is also expounded, not to mention compounded  :lmao: . So why not make your later life easier by putting some planning in beforehand?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Demand Loading Files - a solution
« Reply #21 on: April 30, 2012, 04:47:49 AM »

Quote from: irneb
Regarding use of load as opposed to autoload: Generally there's not much difference - especially with large RAM and fast PCs.

It becomes significant if the user loads a half dozen (or more) drawings per session regularly and also uses some arx/.net applications full time.

You last paragraph covers it for me .. along with being able to 'drop' my system into a temporary machine in a matter of seconds ... important when contracting in a clients office.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.