discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

"use" results in 3x more run time than "include"

A
adrianv
Thu, Apr 18, 2019 11:26 AM

boxcarmib wrote

It does appear that the obvious solution is to simply ignore "use" and
always use "include".  Is there some disadvantage to this approach?  I

I use “use” over include in that it allows me to keep test invocations in
library files. Include as you know will execute any 0-level commands it
encounters when being included… where as “use” only loads the
function/module definitions and executes nothing.

Yeah, that's the theory.  But since it doesn't actually work that way it not
such a clear advantage.  I guess it depends on whether your test
invocations assign any variables.  In the file I was working using, the
presence test invocations (which made top level variable assignments) slowed
down my code from 5 s to 10.5 minutes.

--
Sent from: http://forum.openscad.org/

boxcarmib wrote >> It does appear that the obvious solution is to simply ignore "use" and >> always use "include". Is there some disadvantage to this approach? I > > I use “use” over include in that it allows me to keep test invocations in > library files. Include as you know will execute any 0-level commands it > encounters when being included… where as “use” only loads the > function/module definitions and executes nothing. Yeah, that's the theory. But since it doesn't actually work that way it not such a clear advantage. I guess it depends on whether your test invocations assign any variables. In the file I was working using, the presence test invocations (which made top level variable assignments) slowed down my code from 5 s to 10.5 minutes. -- Sent from: http://forum.openscad.org/
A
adrianv
Thu, Apr 18, 2019 12:00 PM

There are several things I don't understand here.  if my to level does
"use<library.scad>" and that file in turn has the statement
"use<sublib.scad>" then you avoid namespace clutter because sublib.scad is
not made available to the top level.
What happens if I have lib1.scad, lib2.scad, ..., .libN.scad and they all
run "use<sublib.scad>"?  Does sublib.scad get read in N times?  Or it's in
the cache and it doesn't need to be re-read?

I would assume that if you changed "use" to "include" in this example then
definitely the file would be read every time.

I don't understand the issue about dependencies.  What is the concern?
With "include" the file gets read again and the definitions replace the old
values (which are the same), right?  I tried creating circular "use"
statements and everything seemed to work.  With circular "include"
statements I get "Can't open include file...."  But I can't tell if it
loaded the file a hundred times or what.  Is there a max depth?  Are
circular library dependencies a real concern?

If "used" files are cached then why is it so much slower to call functions
in a large used library?  I am finding the behavior pretty odd.  I tried
tweaking my example as follows.  I placed my quant() function in a separate
file, so I have basically

use<quant.scad>
use<hugelib.scad>

This runs fast.  So just creating a large cache with a big library doesn't
create a slow down.  If I define quant() in both files then it depends on
the "use" order.  If hugelib is second then it is slow.  If quant.scad is
second, it's fast.  The last definition holds.  I would expect that if
definitions are cached then a slowdown would have to depend on cache size,
and that wouldn't depend on the order of "use" statements.  Is there a
separate cache entry for each "used" file and a large entry (lots of
functions) makes retrieval slow?  How is it different when a function is in
this cache vs just being defined at the top level?  Where does it go then?

To get ten thousand references to the same file due to the include tree
would seem to require a very deep include tree with lots of files all using
files that use other files that use the same thing.  Is that how your code
is structured?  The code I'm working on the library files are including
files to only one more level of depth.

nophead wrote

Yes used files are cached so a second use simple looks up the name and
finds it already parsed in the cache.

On Thu, 18 Apr 2019, 09:37 A. Craig West, <

acraigwest@

> wrote:

The other use case for use vs include is dependencies. There doesn't
appear to be a way to prevent multiple inclusions of the same file. I'm
not
sure if it helps, but at least in theory use is better in this case. I
don't know how to prevent circular dependencies, though.

On Wed, 17 Apr 2019, 03:58 nop head, <

nop.head@

> wrote:

The reason l haven't noticed is that l simply don't have thousands of
function calls across file boundaries. My projects typically spend a
second
or two running the script and then a few minutes doing CSG in CGAL.

I also recently moved all my test code to their own file, so my used
files don't have any tests in them. I did this so that l can
automatically
run them to produce images.

The reason include would cause my files to be parsed multiple times is
because a lot of them are used in every other library file. This would
lead
to them being parsed tens of thousands of times due to tree explosion. I
know this because I had to fix the module cache dependency checking
which
was calling stat ten thousand times.

So I have a very different use case to Adrian. Most of my code is making
models of real world objects with CSG. Only a few need swept polyhedra
and
even that only calls functions hundreds of times, not thousands.

Other functions like screw_clearance_radius get called for each screw in
a project, and there are only hundreds of those in a large project.

On Wed, 17 Apr 2019, 01:32 A. Craig West, <

acraigwest@

> wrote:

I believe "include" doesn't properly track relative directories when
including other files, while "use" does, although this may have been
resolved at some point. I haven't checked lately

On Tue, 16 Apr 2019, 20:12 Hugo Jackson, <

hugo@

> wrote:

It does appear that the obvious solution is to simply ignore "use"

and

always use "include".  Is there some disadvantage to this approach?

I

I use “use” over include in that it allows me to keep test invocations
in library files. Include as you know will execute any 0-level
commands it
encounters when being included… where as “use” only loads the
function/module definitions and executes nothing.

suppose you lose the ability to "use" files from a library and not

expose

their contents to the to level "user".  Nophead reported a slight
slowdown...do to reparsing?  I'm not sure I understand why that

would

happen.

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

Discuss@.openscad

Discuss@.openscad

Discuss@.openscad

Discuss@.openscad

There are several things I don't understand here. if my to level does "use<library.scad>" and that file in turn has the statement "use<sublib.scad>" then you avoid namespace clutter because sublib.scad is not made available to the top level. What happens if I have lib1.scad, lib2.scad, ..., .libN.scad and they all run "use<sublib.scad>"? Does sublib.scad get read in N times? Or it's in the cache and it doesn't need to be re-read? I would assume that if you changed "use" to "include" in this example then definitely the file would be read every time. I don't understand the issue about dependencies. What is the concern? With "include" the file gets read again and the definitions replace the old values (which are the same), right? I tried creating circular "use" statements and everything seemed to work. With circular "include" statements I get "Can't open include file...." But I can't tell if it loaded the file a hundred times or what. Is there a max depth? Are circular library dependencies a real concern? If "used" files are cached then why is it so much slower to call functions in a large used library? I am finding the behavior pretty odd. I tried tweaking my example as follows. I placed my quant() function in a separate file, so I have basically use<quant.scad> use<hugelib.scad> This runs fast. So just creating a large cache with a big library doesn't create a slow down. If I define quant() in *both* files then it depends on the "use" order. If hugelib is second then it is slow. If quant.scad is second, it's fast. The last definition holds. I would expect that if definitions are cached then a slowdown would have to depend on cache size, and that wouldn't depend on the order of "use" statements. Is there a separate cache entry for each "used" file and a large entry (lots of functions) makes retrieval slow? How is it different when a function is in this cache vs just being defined at the top level? Where does it go then? To get ten thousand references to the same file due to the include tree would seem to require a very deep include tree with lots of files all using files that use other files that use the same thing. Is that how your code is structured? The code I'm working on the library files are including files to only one more level of depth. nophead wrote > Yes used files are cached so a second use simple looks up the name and > finds it already parsed in the cache. > > On Thu, 18 Apr 2019, 09:37 A. Craig West, &lt; > acraigwest@ > &gt; wrote: > >> The other use case for use vs include is dependencies. There doesn't >> appear to be a way to prevent multiple inclusions of the same file. I'm >> not >> sure if it helps, but at least in theory use is better in this case. I >> don't know how to prevent circular dependencies, though. >> >> On Wed, 17 Apr 2019, 03:58 nop head, &lt; > nop.head@ > &gt; wrote: >> >>> The reason l haven't noticed is that l simply don't have thousands of >>> function calls across file boundaries. My projects typically spend a >>> second >>> or two running the script and then a few minutes doing CSG in CGAL. >>> >>> I also recently moved all my test code to their own file, so my used >>> files don't have any tests in them. I did this so that l can >>> automatically >>> run them to produce images. >>> >>> The reason include would cause my files to be parsed multiple times is >>> because a lot of them are used in every other library file. This would >>> lead >>> to them being parsed tens of thousands of times due to tree explosion. I >>> know this because I had to fix the module cache dependency checking >>> which >>> was calling stat ten thousand times. >>> >>> So I have a very different use case to Adrian. Most of my code is making >>> models of real world objects with CSG. Only a few need swept polyhedra >>> and >>> even that only calls functions hundreds of times, not thousands. >>> >>> Other functions like screw_clearance_radius get called for each screw in >>> a project, and there are only hundreds of those in a large project. >>> >>> On Wed, 17 Apr 2019, 01:32 A. Craig West, &lt; > acraigwest@ > &gt; wrote: >>> >>>> I believe "include" doesn't properly track relative directories when >>>> including other files, while "use" does, although this may have been >>>> resolved at some point. I haven't checked lately >>>> >>>> On Tue, 16 Apr 2019, 20:12 Hugo Jackson, &lt; > hugo@ > &gt; wrote: >>>> >>>>> > It does appear that the obvious solution is to simply ignore "use" >>>>> and >>>>> > always use "include". Is there some disadvantage to this approach? >>>>> I >>>>> >>>>> I use “use” over include in that it allows me to keep test invocations >>>>> in library files. Include as you know will execute any 0-level >>>>> commands it >>>>> encounters when being included… where as “use” only loads the >>>>> function/module definitions and executes nothing. >>>>> >>>>> >>>>> > suppose you lose the ability to "use" files from a library and not >>>>> expose >>>>> > their contents to the to level "user". Nophead reported a slight >>>>> > slowdown...do to reparsing? I'm not sure I understand why that >>>>> would >>>>> > happen. >>>>> > >>>>> > >>>>> > >>>>> > >>>>> > -- >>>>> > Sent from: http://forum.openscad.org/ >>>>> > >>>>> > _______________________________________________ >>>>> > OpenSCAD mailing list >>>>> > > Discuss@.openscad >>>>> > >>>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>>> >>>>> >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> > Discuss@.openscad >>>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> > Discuss@.openscad >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> > Discuss@.openscad >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> > Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
NH
nop head
Thu, Apr 18, 2019 7:42 PM

With use there is only one module cache entry for each used file and it is
only read from file once and parsed once regardless of how may times it is
used and from where.

They way I get a tree explosion is having a project where each file uses
all the files in my library. All all the files in my library use a global
file that uses several itself and several other library files. So it
creates a sort of fractal tree.

Symbol lookup is pretty quick I think because it uses maps. But if you have
a list of modules then it has to look for symbols in each one. So lots of
maps searches.

If you include then it gets parsed over and over again and I think creates
lots of copies of the functions and modules in different namespaces.

If you have recursive uses it simply ignores the recursion because it finds
in the cache. On the other hand with a recursive include it would loop
forever if it didn't error.

On Thu, 18 Apr 2019 at 13:01, adrianv avm4@cornell.edu wrote:

There are several things I don't understand here.  if my to level does
"use<library.scad>" and that file in turn has the statement
"use<sublib.scad>" then you avoid namespace clutter because sublib.scad is
not made available to the top level.
What happens if I have lib1.scad, lib2.scad, ..., .libN.scad and they all
run "use<sublib.scad>"?  Does sublib.scad get read in N times?  Or it's in
the cache and it doesn't need to be re-read?

I would assume that if you changed "use" to "include" in this example then
definitely the file would be read every time.

I don't understand the issue about dependencies.  What is the concern?
With "include" the file gets read again and the definitions replace the old
values (which are the same), right?  I tried creating circular "use"
statements and everything seemed to work.  With circular "include"
statements I get "Can't open include file...."  But I can't tell if it
loaded the file a hundred times or what.  Is there a max depth?  Are
circular library dependencies a real concern?

If "used" files are cached then why is it so much slower to call functions
in a large used library?  I am finding the behavior pretty odd.  I tried
tweaking my example as follows.  I placed my quant() function in a separate
file, so I have basically

use<quant.scad>
use<hugelib.scad>

This runs fast.  So just creating a large cache with a big library doesn't
create a slow down.  If I define quant() in both files then it depends
on
the "use" order.  If hugelib is second then it is slow.  If quant.scad is
second, it's fast.  The last definition holds.  I would expect that if
definitions are cached then a slowdown would have to depend on cache size,
and that wouldn't depend on the order of "use" statements.  Is there a
separate cache entry for each "used" file and a large entry (lots of
functions) makes retrieval slow?  How is it different when a function is
in
this cache vs just being defined at the top level?  Where does it go
then?

To get ten thousand references to the same file due to the include tree
would seem to require a very deep include tree with lots of files all using
files that use other files that use the same thing.  Is that how your code
is structured?  The code I'm working on the library files are including
files to only one more level of depth.

nophead wrote

Yes used files are cached so a second use simple looks up the name and
finds it already parsed in the cache.

On Thu, 18 Apr 2019, 09:37 A. Craig West, <

acraigwest@

> wrote:

The other use case for use vs include is dependencies. There doesn't
appear to be a way to prevent multiple inclusions of the same file. I'm
not
sure if it helps, but at least in theory use is better in this case. I
don't know how to prevent circular dependencies, though.

On Wed, 17 Apr 2019, 03:58 nop head, <

nop.head@

> wrote:

The reason l haven't noticed is that l simply don't have thousands of
function calls across file boundaries. My projects typically spend a
second
or two running the script and then a few minutes doing CSG in CGAL.

I also recently moved all my test code to their own file, so my used
files don't have any tests in them. I did this so that l can
automatically
run them to produce images.

The reason include would cause my files to be parsed multiple times is
because a lot of them are used in every other library file. This would
lead
to them being parsed tens of thousands of times due to tree explosion.

I

know this because I had to fix the module cache dependency checking
which
was calling stat ten thousand times.

So I have a very different use case to Adrian. Most of my code is

making

models of real world objects with CSG. Only a few need swept polyhedra
and
even that only calls functions hundreds of times, not thousands.

Other functions like screw_clearance_radius get called for each screw

in

a project, and there are only hundreds of those in a large project.

On Wed, 17 Apr 2019, 01:32 A. Craig West, <

acraigwest@

> wrote:

I believe "include" doesn't properly track relative directories when
including other files, while "use" does, although this may have been
resolved at some point. I haven't checked lately

On Tue, 16 Apr 2019, 20:12 Hugo Jackson, <

hugo@

> wrote:

It does appear that the obvious solution is to simply ignore "use"

and

always use "include".  Is there some disadvantage to this

approach?

I

I use “use” over include in that it allows me to keep test

invocations

in library files. Include as you know will execute any 0-level
commands it
encounters when being included… where as “use” only loads the
function/module definitions and executes nothing.

suppose you lose the ability to "use" files from a library and not

expose

their contents to the to level "user".  Nophead reported a slight
slowdown...do to reparsing?  I'm not sure I understand why that

would

happen.

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list

Discuss@.openscad


OpenSCAD mailing list

Discuss@.openscad


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

Discuss@.openscad

Discuss@.openscad

With use there is only one module cache entry for each used file and it is only read from file once and parsed once regardless of how may times it is used and from where. They way I get a tree explosion is having a project where each file uses all the files in my library. All all the files in my library use a global file that uses several itself and several other library files. So it creates a sort of fractal tree. Symbol lookup is pretty quick I think because it uses maps. But if you have a list of modules then it has to look for symbols in each one. So lots of maps searches. If you include then it gets parsed over and over again and I think creates lots of copies of the functions and modules in different namespaces. If you have recursive uses it simply ignores the recursion because it finds in the cache. On the other hand with a recursive include it would loop forever if it didn't error. On Thu, 18 Apr 2019 at 13:01, adrianv <avm4@cornell.edu> wrote: > There are several things I don't understand here. if my to level does > "use<library.scad>" and that file in turn has the statement > "use<sublib.scad>" then you avoid namespace clutter because sublib.scad is > not made available to the top level. > What happens if I have lib1.scad, lib2.scad, ..., .libN.scad and they all > run "use<sublib.scad>"? Does sublib.scad get read in N times? Or it's in > the cache and it doesn't need to be re-read? > > I would assume that if you changed "use" to "include" in this example then > definitely the file would be read every time. > > I don't understand the issue about dependencies. What is the concern? > With "include" the file gets read again and the definitions replace the old > values (which are the same), right? I tried creating circular "use" > statements and everything seemed to work. With circular "include" > statements I get "Can't open include file...." But I can't tell if it > loaded the file a hundred times or what. Is there a max depth? Are > circular library dependencies a real concern? > > If "used" files are cached then why is it so much slower to call functions > in a large used library? I am finding the behavior pretty odd. I tried > tweaking my example as follows. I placed my quant() function in a separate > file, so I have basically > > use<quant.scad> > use<hugelib.scad> > > This runs fast. So just creating a large cache with a big library doesn't > create a slow down. If I define quant() in *both* files then it depends > on > the "use" order. If hugelib is second then it is slow. If quant.scad is > second, it's fast. The last definition holds. I would expect that if > definitions are cached then a slowdown would have to depend on cache size, > and that wouldn't depend on the order of "use" statements. Is there a > separate cache entry for each "used" file and a large entry (lots of > functions) makes retrieval slow? How is it different when a function is > in > this cache vs just being defined at the top level? Where does it go > then? > > To get ten thousand references to the same file due to the include tree > would seem to require a very deep include tree with lots of files all using > files that use other files that use the same thing. Is that how your code > is structured? The code I'm working on the library files are including > files to only one more level of depth. > > > nophead wrote > > Yes used files are cached so a second use simple looks up the name and > > finds it already parsed in the cache. > > > > On Thu, 18 Apr 2019, 09:37 A. Craig West, &lt; > > > acraigwest@ > > > &gt; wrote: > > > >> The other use case for use vs include is dependencies. There doesn't > >> appear to be a way to prevent multiple inclusions of the same file. I'm > >> not > >> sure if it helps, but at least in theory use is better in this case. I > >> don't know how to prevent circular dependencies, though. > >> > >> On Wed, 17 Apr 2019, 03:58 nop head, &lt; > > > nop.head@ > > > &gt; wrote: > >> > >>> The reason l haven't noticed is that l simply don't have thousands of > >>> function calls across file boundaries. My projects typically spend a > >>> second > >>> or two running the script and then a few minutes doing CSG in CGAL. > >>> > >>> I also recently moved all my test code to their own file, so my used > >>> files don't have any tests in them. I did this so that l can > >>> automatically > >>> run them to produce images. > >>> > >>> The reason include would cause my files to be parsed multiple times is > >>> because a lot of them are used in every other library file. This would > >>> lead > >>> to them being parsed tens of thousands of times due to tree explosion. > I > >>> know this because I had to fix the module cache dependency checking > >>> which > >>> was calling stat ten thousand times. > >>> > >>> So I have a very different use case to Adrian. Most of my code is > making > >>> models of real world objects with CSG. Only a few need swept polyhedra > >>> and > >>> even that only calls functions hundreds of times, not thousands. > >>> > >>> Other functions like screw_clearance_radius get called for each screw > in > >>> a project, and there are only hundreds of those in a large project. > >>> > >>> On Wed, 17 Apr 2019, 01:32 A. Craig West, &lt; > > > acraigwest@ > > > &gt; wrote: > >>> > >>>> I believe "include" doesn't properly track relative directories when > >>>> including other files, while "use" does, although this may have been > >>>> resolved at some point. I haven't checked lately > >>>> > >>>> On Tue, 16 Apr 2019, 20:12 Hugo Jackson, &lt; > > > hugo@ > > > &gt; wrote: > >>>> > >>>>> > It does appear that the obvious solution is to simply ignore "use" > >>>>> and > >>>>> > always use "include". Is there some disadvantage to this > approach? > >>>>> I > >>>>> > >>>>> I use “use” over include in that it allows me to keep test > invocations > >>>>> in library files. Include as you know will execute any 0-level > >>>>> commands it > >>>>> encounters when being included… where as “use” only loads the > >>>>> function/module definitions and executes nothing. > >>>>> > >>>>> > >>>>> > suppose you lose the ability to "use" files from a library and not > >>>>> expose > >>>>> > their contents to the to level "user". Nophead reported a slight > >>>>> > slowdown...do to reparsing? I'm not sure I understand why that > >>>>> would > >>>>> > happen. > >>>>> > > >>>>> > > >>>>> > > >>>>> > > >>>>> > -- > >>>>> > Sent from: http://forum.openscad.org/ > >>>>> > > >>>>> > _______________________________________________ > >>>>> > OpenSCAD mailing list > >>>>> > > > > Discuss@.openscad > > >>>>> > > >>>>> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >>>>> > >>>>> > >>>>> _______________________________________________ > >>>>> OpenSCAD mailing list > >>>>> > > > Discuss@.openscad > > >>>>> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >>>>> > >>>> _______________________________________________ > >>>> OpenSCAD mailing list > >>>> > > > Discuss@.openscad > > >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >>>> > >>> _______________________________________________ > >>> OpenSCAD mailing list > >>> > > > Discuss@.openscad > > >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >>> > >> _______________________________________________ > >> OpenSCAD mailing list > >> > > > Discuss@.openscad > > >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >> > > > > _______________________________________________ > > OpenSCAD mailing list > > > Discuss@.openscad > > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >