discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Problem with large projects

JW
Jan Wieck
Sun, Jun 7, 2020 2:52 PM

On Sun, Jun 7, 2020 at 12:55 PM nop head nop.head@gmail.com wrote:

I have been designing a 3D printer on and off for a few years now. When I
came back to it recently, haing updated my library and OpenSCAD in the
meantime, I find it very slow to update the preview when I make a small
change. This is mainly the "Compiling design (CSG Tree generation)...",
i.e. when the code is instantiated and echo modules come out, before it
actually does any geometry. The geometry takes no time when nothing has
changed because it is all cached.

Considering that this is all CPU bound, have you tried getting a perf based
CPU flamegraph of the rendering process? My current OpenSCAD setup is
living in a docker container and I have never attempted to perf such, but
it would be an interesting thing to figure out.

Regards, Jan

I remember it being about 12 seconds, which wasn't too bad but now it is a
minute.

It is by far the biggest project I have done in OpenSCAD, and is broken up
into 21 files, not including the library. In contrast most of other
projects are just a single file or two or three and will do that part of
the compilation in less than a second. For example something like this uses
the same library and will do F5 with no changes in 1 second.

[image: image.png]

It only takes 53 seconds to draw the whole thing when first loaded. My
large project only takes 4 minutes to render from scratch, so whereas the
small project has a 53:1 difference between the first F5 and a second one.
The large project only has a 4:1 difference.

It is hard to see where the time is taken, it seems to be fairly slow all
over just due to splitting it into multiple files. I think the main problem
is a small file of global constants that gets included everywhere. Putting
an echo function in that file shows the constants are instantiated about
1/4 million times! In the smaller project it is instantiated 4700 times.
Still huge but it seems to explode when you have more files.

This is because whenever you call a module or function in a different file
it instantiates all the constants. Is this really necessary or can it be
fixed? I think it would make a huge difference to a project like this.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

--
Jan Wieck
Principal Database Engineer

On Sun, Jun 7, 2020 at 12:55 PM nop head <nop.head@gmail.com> wrote: > I have been designing a 3D printer on and off for a few years now. When I > came back to it recently, haing updated my library and OpenSCAD in the > meantime, I find it very slow to update the preview when I make a small > change. This is mainly the "Compiling design (CSG Tree generation)...", > i.e. when the code is instantiated and echo modules come out, before it > actually does any geometry. The geometry takes no time when nothing has > changed because it is all cached. > Considering that this is all CPU bound, have you tried getting a perf based CPU flamegraph of the rendering process? My current OpenSCAD setup is living in a docker container and I have never attempted to perf such, but it would be an interesting thing to figure out. Regards, Jan > > I remember it being about 12 seconds, which wasn't too bad but now it is a > minute. > > It is by far the biggest project I have done in OpenSCAD, and is broken up > into 21 files, not including the library. In contrast most of other > projects are just a single file or two or three and will do that part of > the compilation in less than a second. For example something like this uses > the same library and will do F5 with no changes in 1 second. > > [image: image.png] > > It only takes 53 seconds to draw the whole thing when first loaded. My > large project only takes 4 minutes to render from scratch, so whereas the > small project has a 53:1 difference between the first F5 and a second one. > The large project only has a 4:1 difference. > > It is hard to see where the time is taken, it seems to be fairly slow all > over just due to splitting it into multiple files. I think the main problem > is a small file of global constants that gets included everywhere. Putting > an echo function in that file shows the constants are instantiated about > 1/4 million times! In the smaller project it is instantiated 4700 times. > Still huge but it seems to explode when you have more files. > > This is because whenever you call a module or function in a different file > it instantiates all the constants. Is this really necessary or can it be > fixed? I think it would make a huge difference to a project like this. > > > > > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > -- Jan Wieck Principal Database Engineer
NH
nop head
Sun, Jun 7, 2020 4:53 PM

I have been designing a 3D printer on and off for a few years now. When I
came back to it recently, haing updated my library and OpenSCAD in the
meantime, I find it very slow to update the preview when I make a small
change. This is mainly the "Compiling design (CSG Tree generation)...",
i.e. when the code is instantiated and echo modules come out, before it
actually does any geometry. The geometry takes no time when nothing has
changed because it is all cached.

I remember it being about 12 seconds, which wasn't too bad but now it is a
minute.

It is by far the biggest project I have done in OpenSCAD, and is broken up
into 21 files, not including the library. In contrast most of other
projects are just a single file or two or three and will do that part of
the compilation in less than a second. For example something like this uses
the same library and will do F5 with no changes in 1 second.

[image: image.png]

It only takes 53 seconds to draw the whole thing when first loaded. My
large project only takes 4 minutes to render from scratch, so whereas the
small project has a 53:1 difference between the first F5 and a second one.
The large project only has a 4:1 difference.

It is hard to see where the time is taken, it seems to be fairly slow all
over just due to splitting it into multiple files. I think the main problem
is a small file of global constants that gets included everywhere. Putting
an echo function in that file shows the constants are instantiated about
1/4 million times! In the smaller project it is instantiated 4700 times.
Still huge but it seems to explode when you have more files.

This is because whenever you call a module or function in a different file
it instantiates all the constants. Is this really necessary or can it be
fixed? I think it would make a huge difference to a project like this.

I have been designing a 3D printer on and off for a few years now. When I came back to it recently, haing updated my library and OpenSCAD in the meantime, I find it very slow to update the preview when I make a small change. This is mainly the "Compiling design (CSG Tree generation)...", i.e. when the code is instantiated and echo modules come out, before it actually does any geometry. The geometry takes no time when nothing has changed because it is all cached. I remember it being about 12 seconds, which wasn't too bad but now it is a minute. It is by far the biggest project I have done in OpenSCAD, and is broken up into 21 files, not including the library. In contrast most of other projects are just a single file or two or three and will do that part of the compilation in less than a second. For example something like this uses the same library and will do F5 with no changes in 1 second. [image: image.png] It only takes 53 seconds to draw the whole thing when first loaded. My large project only takes 4 minutes to render from scratch, so whereas the small project has a 53:1 difference between the first F5 and a second one. The large project only has a 4:1 difference. It is hard to see where the time is taken, it seems to be fairly slow all over just due to splitting it into multiple files. I think the main problem is a small file of global constants that gets included everywhere. Putting an echo function in that file shows the constants are instantiated about 1/4 million times! In the smaller project it is instantiated 4700 times. Still huge but it seems to explode when you have more files. This is because whenever you call a module or function in a different file it instantiates all the constants. Is this really necessary or can it be fixed? I think it would make a huge difference to a project like this.
A
adrianv
Sun, Jun 7, 2020 5:32 PM

Yeah, when I posted about this a few months ago people seemed to think it
didn't matter.  The issue has been open for years and seems catastrophic to
me.

Our solution is to never use "use" and only use "include" which avoids the
problem.  I think there are other cases where "use" is slow as well, though
not as serious.

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

Yeah, when I posted about this a few months ago people seemed to think it didn't matter. The issue has been open for years and seems catastrophic to me. Our solution is to never use "use" and only use "include" which avoids the problem. I think there are other cases where "use" is slow as well, though not as serious. -- Sent from: http://forum.openscad.org/
NH
nop head
Sun, Jun 7, 2020 8:03 PM

Yes I remember that post. I seem to get away with it on all my projects
except this one. It also has a global file with constants at the project
level and they are positions of things with several function calls each to
other modules, so they are more costly. Each of the function calls likely
needs all the constants instantiated again and it explodes.

I can get the time down to 37 seconds by including sub assemblies instead
of using them but I had to add a bodge to stop them instantiating
themselves as I like to load a sub assembly when working on it.

I am on Windows so to profile OpenSCAD I think I would need to build it
with Visual Studio, which I have done before, but I am pretty sure the
problem is evaluating constants over and over again. Every single screw,
nut, washer, etc are calls to the library and the library includes its
global constants in every module as again, they all work standalone.

It is counter intuitive that making constants in a file module is slower
than working everything out inside functions. You would expect the constant
to be evaluated once when the file is first used, not every time a function
or module is called in it.

It might be faster to make all constants into functions but then you would
have a big tree of function calls that explode as nothing can be worked out
once and stored for later use.

On Sun, 7 Jun 2020 at 18:33, adrianv avm4@cornell.edu wrote:

Yeah, when I posted about this a few months ago people seemed to think it
didn't matter.  The issue has been open for years and seems catastrophic to
me.

Our solution is to never use "use" and only use "include" which avoids the
problem.  I think there are other cases where "use" is slow as well, though
not as serious.

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


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Yes I remember that post. I seem to get away with it on all my projects except this one. It also has a global file with constants at the project level and they are positions of things with several function calls each to other modules, so they are more costly. Each of the function calls likely needs all the constants instantiated again and it explodes. I can get the time down to 37 seconds by including sub assemblies instead of using them but I had to add a bodge to stop them instantiating themselves as I like to load a sub assembly when working on it. I am on Windows so to profile OpenSCAD I think I would need to build it with Visual Studio, which I have done before, but I am pretty sure the problem is evaluating constants over and over again. Every single screw, nut, washer, etc are calls to the library and the library includes its global constants in every module as again, they all work standalone. It is counter intuitive that making constants in a file module is slower than working everything out inside functions. You would expect the constant to be evaluated once when the file is first used, not every time a function or module is called in it. It might be faster to make all constants into functions but then you would have a big tree of function calls that explode as nothing can be worked out once and stored for later use. On Sun, 7 Jun 2020 at 18:33, adrianv <avm4@cornell.edu> wrote: > Yeah, when I posted about this a few months ago people seemed to think it > didn't matter. The issue has been open for years and seems catastrophic to > me. > > Our solution is to never use "use" and only use "include" which avoids the > problem. I think there are other cases where "use" is slow as well, though > not as serious. > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
NH
nop head
Sun, Jun 14, 2020 11:11 PM

Yes this has really become a problem for me. I have a list of
transformations that position screws in a shelf bracket that is reasonably
complex to calculate and since it generates the bracket and also positions
inserts and screws into it plus it needs to drill holes in 6 panels that it
mates with I need to reference it many times.

function shelf_screw_positions() = [
translate([z_axis_x + spine_width() / 2, box_depth / 2 - spine_depth()

  • spine_clearance + shelf_boss_r + eps])              * rotate([-90, 0,
    90]),
    translate([z_axis_x + spine_width() / 2, box_depth / 2 - shelf_boss_r -
    eps])                                                * rotate([-90, 0,
    90]),

    translate([-box_width / 4,              box_depth / 2])
    * rotate([-90, 0,
    0]),

    translate([box_width / 2,                box_depth / 2 -
    box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type) -
    eps]) * rotate([-90, 0, -90]),
    translate([box_width / 2,              -box_depth / 2 +
    box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type) +
    eps]) * rotate([-90, 0, -90]),

    translate([ 10, -box_depth / 2]) * rotate([-90, 0, 180]),
    translate([-10, -box_depth / 2]) * rotate([-90, 0, 180]),

    translate([-box_width / 2,              box_depth / 2 -
    box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type) -
    eps]) * rotate([-90, 0, 90]),
    translate([-box_width / 2,              -box_depth / 2 +
    box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type) +
    eps]) * rotate([-90, 0, 90]),

    translate([z_axis_x - spine_width() / 2, box_depth / 2 - spine_depth()

  • spine_clearance + shelf_boss_r + eps])              * rotate([-90, 0,
    -90]),
    translate([z_axis_x - spine_width() / 2, box_depth / 2 - shelf_boss_r -
    eps])                                                * rotate([-90, 0,
    -90]),
    ];

[image: image.png]

If I store it in a variable it gets calculated every time I call a function
or module in a file that includes its definition. If I wrap it in a
function it gets computed every time I use it. It is bonkers because it is
a constant, so only needs to be calculated once.

Adding this shelf to my project doubles the time it takes to do "Compiling
design (CSG Tree generation)...", from about 30 seconds to 1 minute simply
because this self touches six panels, which are all separate files in the
machine. Compared to the rest of the complexity of the machine it is
trivial but because it interacts with most of it it has a huge impact on
the speed and the time needed to see every change.

Is it true that the only way to have a constant calculated once is to make
my project into one massive file?

On Sun, 7 Jun 2020 at 21:03, nop head nop.head@gmail.com wrote:

Yes I remember that post. I seem to get away with it on all my projects
except this one. It also has a global file with constants at the project
level and they are positions of things with several function calls each to
other modules, so they are more costly. Each of the function calls likely
needs all the constants instantiated again and it explodes.

I can get the time down to 37 seconds by including sub assemblies instead
of using them but I had to add a bodge to stop them instantiating
themselves as I like to load a sub assembly when working on it.

I am on Windows so to profile OpenSCAD I think I would need to build it
with Visual Studio, which I have done before, but I am pretty sure the
problem is evaluating constants over and over again. Every single screw,
nut, washer, etc are calls to the library and the library includes its
global constants in every module as again, they all work standalone.

It is counter intuitive that making constants in a file module is slower
than working everything out inside functions. You would expect the constant
to be evaluated once when the file is first used, not every time a function
or module is called in it.

It might be faster to make all constants into functions but then you would
have a big tree of function calls that explode as nothing can be worked out
once and stored for later use.

On Sun, 7 Jun 2020 at 18:33, adrianv avm4@cornell.edu wrote:

Yeah, when I posted about this a few months ago people seemed to think it
didn't matter.  The issue has been open for years and seems catastrophic
to
me.

Our solution is to never use "use" and only use "include" which avoids the
problem.  I think there are other cases where "use" is slow as well,
though
not as serious.

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


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Yes this has really become a problem for me. I have a list of transformations that position screws in a shelf bracket that is reasonably complex to calculate and since it generates the bracket and also positions inserts and screws into it plus it needs to drill holes in 6 panels that it mates with I need to reference it many times. function shelf_screw_positions() = [ translate([z_axis_x + spine_width() / 2, box_depth / 2 - spine_depth() + spine_clearance + shelf_boss_r + eps]) * rotate([-90, 0, 90]), translate([z_axis_x + spine_width() / 2, box_depth / 2 - shelf_boss_r - eps]) * rotate([-90, 0, 90]), translate([-box_width / 4, box_depth / 2]) * rotate([-90, 0, 0]), translate([box_width / 2, box_depth / 2 - box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type) - eps]) * rotate([-90, 0, -90]), translate([box_width / 2, -box_depth / 2 + box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type) + eps]) * rotate([-90, 0, -90]), translate([ 10, -box_depth / 2]) * rotate([-90, 0, 180]), translate([-10, -box_depth / 2]) * rotate([-90, 0, 180]), translate([-box_width / 2, box_depth / 2 - box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type) - eps]) * rotate([-90, 0, 90]), translate([-box_width / 2, -box_depth / 2 + box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type) + eps]) * rotate([-90, 0, 90]), translate([z_axis_x - spine_width() / 2, box_depth / 2 - spine_depth() + spine_clearance + shelf_boss_r + eps]) * rotate([-90, 0, -90]), translate([z_axis_x - spine_width() / 2, box_depth / 2 - shelf_boss_r - eps]) * rotate([-90, 0, -90]), ]; [image: image.png] If I store it in a variable it gets calculated every time I call a function or module in a file that includes its definition. If I wrap it in a function it gets computed every time I use it. It is bonkers because it is a constant, so only needs to be calculated once. Adding this shelf to my project doubles the time it takes to do "Compiling design (CSG Tree generation)...", from about 30 seconds to 1 minute simply because this self touches six panels, which are all separate files in the machine. Compared to the rest of the complexity of the machine it is trivial but because it interacts with most of it it has a huge impact on the speed and the time needed to see every change. Is it true that the only way to have a constant calculated once is to make my project into one massive file? On Sun, 7 Jun 2020 at 21:03, nop head <nop.head@gmail.com> wrote: > Yes I remember that post. I seem to get away with it on all my projects > except this one. It also has a global file with constants at the project > level and they are positions of things with several function calls each to > other modules, so they are more costly. Each of the function calls likely > needs all the constants instantiated again and it explodes. > > I can get the time down to 37 seconds by including sub assemblies instead > of using them but I had to add a bodge to stop them instantiating > themselves as I like to load a sub assembly when working on it. > > I am on Windows so to profile OpenSCAD I think I would need to build it > with Visual Studio, which I have done before, but I am pretty sure the > problem is evaluating constants over and over again. Every single screw, > nut, washer, etc are calls to the library and the library includes its > global constants in every module as again, they all work standalone. > > It is counter intuitive that making constants in a file module is slower > than working everything out inside functions. You would expect the constant > to be evaluated once when the file is first used, not every time a function > or module is called in it. > > It might be faster to make all constants into functions but then you would > have a big tree of function calls that explode as nothing can be worked out > once and stored for later use. > > > On Sun, 7 Jun 2020 at 18:33, adrianv <avm4@cornell.edu> wrote: > >> Yeah, when I posted about this a few months ago people seemed to think it >> didn't matter. The issue has been open for years and seems catastrophic >> to >> me. >> >> Our solution is to never use "use" and only use "include" which avoids the >> problem. I think there are other cases where "use" is slow as well, >> though >> not as serious. >> >> >> >> >> -- >> Sent from: http://forum.openscad.org/ >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >
P
pproj@posteo.de
Mon, Jun 15, 2020 12:08 AM

I have my own "constructive" library (kind of a strong dialect of
openscad entirely written in openscad)  i have been using for many years
now for complex projects.
in that library all transformations are just functiontions producing
matrices, and a sequence of transformations is easily accumulated into a
single multmatrix by the library, so essentialy all your code below will
break down into a single multmatrix operation in the CSG tree. all the
calculation itself is not passed CSG, it is just matrix multiplications,
so essentially every combination of input variabled becomes one matrix
value and i think this will be chached right?
will this help the case? i am not 100% sure i understand your case
completely.
i planned to publish it anyway, but since the reaction to my work in
this group so far was never very enthusiastic, it seems it will probably
not pay of the effort of cleaning up and documenting the code.
but in case it  might help you with your problem i am happy to share it
with you, it has many other useful things like automatic
backwards(reverse) transformations, ability to mark parts of the code as
relevant to one design part or other, and then, render only certain
parts, or boolean them, or having "difference()" work over different
transformation origins (the components of the difference operation do
not have to have the same parent,like with normal difference() where the
subtracted componets are always ancestors of the difference()
element),selective hull(),...
 
On 15.06.20 01:11, nop head wrote:

Yes this has really become a problem for me. I have a list of
transformations that position screws in a shelf bracket that is
reasonably complex to calculate and since it generates the bracket and
also positions inserts and screws into it plus it needs to drill holes
in 6 panels that it mates with I need to reference it many times.

function shelf_screw_positions() = [
    translate([z_axis_x + spine_width() / 2, box_depth / 2 -
spine_depth() + spine_clearance + shelf_boss_r + eps])               *
rotate([-90, 0, 90]),
    translate([z_axis_x + spine_width() / 2, box_depth / 2 -
shelf_boss_r - eps])                                                 *
rotate([-90, 0, 90]),

    translate([-box_width / 4,               box_depth / 2])          
                                                           *
rotate([-90, 0,  0]),

    translate([box_width / 2,                box_depth / 2 -
box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type)

  • eps]) * rotate([-90, 0, -90]),
        translate([box_width / 2,               -box_depth / 2 +
    box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type)
  • eps]) * rotate([-90, 0, -90]),

    translate([ 10, -box_depth / 2]) * rotate([-90, 0, 180]),
    translate([-10, -box_depth / 2]) * rotate([-90, 0, 180]),

    translate([-box_width / 2,               box_depth / 2 -
box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type)

  • eps]) * rotate([-90, 0, 90]),
        translate([-box_width / 2,              -box_depth / 2 +
    box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type)
  • eps]) * rotate([-90, 0, 90]),

    translate([z_axis_x - spine_width() / 2, box_depth / 2 -
spine_depth() + spine_clearance + shelf_boss_r + eps])               *
rotate([-90, 0, -90]),
    translate([z_axis_x - spine_width() / 2, box_depth / 2 -
shelf_boss_r - eps])                                                 *
rotate([-90, 0, -90]),
];

image.png

If I store it in a variable it gets calculated every time I call a
function or module in a file that includes its definition. If I wrap
it in a function it gets computed every time I use it. It is bonkers
because it is a constant, so only needs to be calculated once.

Adding this shelf to my project doubles the time it takes to do
"Compiling design (CSG Tree generation)...", from about 30 seconds to
1 minute simply because this self touches six panels, which are all
separate files in the machine. Compared to the rest of the complexity
of the machine it is trivial but because it interacts with most of it
it has a huge impact on the speed and the time needed to see every change.

Is it true that the only way to have a constant calculated once is to
make my project into one massive file?

On Sun, 7 Jun 2020 at 21:03, nop head <nop.head@gmail.com
mailto:nop.head@gmail.com> wrote:

 Yes I remember that post. I seem to get away with it on all my
 projects except this one. It also has a global file with constants
 at the project level and they are positions of things with several
 function calls each to other modules, so they are more costly.
 Each of the function calls likely needs all the constants
 instantiated again and it explodes.

 I can get the time down to 37 seconds by including sub assemblies
 instead of using them but I had to add a bodge to stop them
 instantiating themselves as I like to load a sub assembly when
 working on it.

 I am on Windows so to profile OpenSCAD I think I would need to
 build it with Visual Studio, which I have done before, but I am
 pretty sure the problem is evaluating constants over and over
 again. Every single screw, nut, washer, etc are calls to the
 library and the library includes its global constants in every
 module as again, they all work standalone.  

 It is counter intuitive that making constants in a file module is
 slower than working everything out inside functions. You would
 expect the constant to be evaluated once when the file is first
 used, not every time a function or module is called in it.

 It might be faster to make all constants into functions but then
 you would have a big tree of function calls that explode as
 nothing can be worked out once and stored for later use.


 On Sun, 7 Jun 2020 at 18:33, adrianv <avm4@cornell.edu
 <mailto:avm4@cornell.edu>> wrote:

     Yeah, when I posted about this a few months ago people seemed
     to think it
     didn't matter.  The issue has been open for years and seems
     catastrophic to
     me. 

     Our solution is to never use "use" and only use "include"
     which avoids the
     problem.  I think there are other cases where "use" is slow as
     well, though
     not as serious. 




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

     _______________________________________________
     OpenSCAD mailing list
     Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org>
     http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I have my own "constructive" library (kind of a strong dialect of openscad entirely written in openscad)  i have been using for many years now for complex projects. in that library all transformations are just functiontions producing matrices, and a sequence of transformations is easily accumulated into a single multmatrix by the library, so essentialy all your code below will break down into a single multmatrix operation in the CSG tree. all the calculation itself is not passed CSG, it is just matrix multiplications, so essentially every combination of input variabled becomes one matrix value and i think this will be chached right? will this help the case? i am not 100% sure i understand your case completely. i planned to publish it anyway, but since the reaction to my work in this group so far was never very enthusiastic, it seems it will probably not pay of the effort of cleaning up and documenting the code. but in case it  might help you with your problem i am happy to share it with you, it has many other useful things like automatic backwards(reverse) transformations, ability to mark parts of the code as relevant to one design part or other, and then, render only certain parts, or boolean them, or having "difference()" work over different transformation origins (the components of the difference operation do not have to have the same parent,like with normal difference() where the subtracted componets are always ancestors of the difference() element),selective hull(),...   On 15.06.20 01:11, nop head wrote: > Yes this has really become a problem for me. I have a list of > transformations that position screws in a shelf bracket that is > reasonably complex to calculate and since it generates the bracket and > also positions inserts and screws into it plus it needs to drill holes > in 6 panels that it mates with I need to reference it many times. > > function shelf_screw_positions() = [ >     translate([z_axis_x + spine_width() / 2, box_depth / 2 - > spine_depth() + spine_clearance + shelf_boss_r + eps])               * > rotate([-90, 0, 90]), >     translate([z_axis_x + spine_width() / 2, box_depth / 2 - > shelf_boss_r - eps])                                                 * > rotate([-90, 0, 90]), > >     translate([-box_width / 4,               box_depth / 2])           >                                                            * > rotate([-90, 0,  0]), > >     translate([box_width / 2,                box_depth / 2 - > box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type) > - eps]) * rotate([-90, 0, -90]), >     translate([box_width / 2,               -box_depth / 2 + > box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type) > + eps]) * rotate([-90, 0, -90]), > >     translate([ 10, -box_depth / 2]) * rotate([-90, 0, 180]), >     translate([-10, -box_depth / 2]) * rotate([-90, 0, 180]), > >     translate([-box_width / 2,               box_depth / 2 - > box_intrusion(box_type) - shelf_boss_r - box_bezel_clearance(box_type) > - eps]) * rotate([-90, 0, 90]), >     translate([-box_width / 2,              -box_depth / 2 + > box_intrusion(box_type) + shelf_boss_r + box_bezel_clearance(box_type) > + eps]) * rotate([-90, 0, 90]), > >     translate([z_axis_x - spine_width() / 2, box_depth / 2 - > spine_depth() + spine_clearance + shelf_boss_r + eps])               * > rotate([-90, 0, -90]), >     translate([z_axis_x - spine_width() / 2, box_depth / 2 - > shelf_boss_r - eps])                                                 * > rotate([-90, 0, -90]), > ]; > > image.png > > If I store it in a variable it gets calculated every time I call a > function or module in a file that includes its definition. If I wrap > it in a function it gets computed every time I use it. It is bonkers > because it is a constant, so only needs to be calculated once. > > Adding this shelf to my project doubles the time it takes to do > "Compiling design (CSG Tree generation)...", from about 30 seconds to > 1 minute simply because this self touches six panels, which are all > separate files in the machine. Compared to the rest of the complexity > of the machine it is trivial but because it interacts with most of it > it has a huge impact on the speed and the time needed to see every change. > > Is it true that the only way to have a constant calculated once is to > make my project into one massive file? > > > On Sun, 7 Jun 2020 at 21:03, nop head <nop.head@gmail.com > <mailto:nop.head@gmail.com>> wrote: > > Yes I remember that post. I seem to get away with it on all my > projects except this one. It also has a global file with constants > at the project level and they are positions of things with several > function calls each to other modules, so they are more costly. > Each of the function calls likely needs all the constants > instantiated again and it explodes. > > I can get the time down to 37 seconds by including sub assemblies > instead of using them but I had to add a bodge to stop them > instantiating themselves as I like to load a sub assembly when > working on it. > > I am on Windows so to profile OpenSCAD I think I would need to > build it with Visual Studio, which I have done before, but I am > pretty sure the problem is evaluating constants over and over > again. Every single screw, nut, washer, etc are calls to the > library and the library includes its global constants in every > module as again, they all work standalone.   > > It is counter intuitive that making constants in a file module is > slower than working everything out inside functions. You would > expect the constant to be evaluated once when the file is first > used, not every time a function or module is called in it. > > It might be faster to make all constants into functions but then > you would have a big tree of function calls that explode as > nothing can be worked out once and stored for later use. > > > On Sun, 7 Jun 2020 at 18:33, adrianv <avm4@cornell.edu > <mailto:avm4@cornell.edu>> wrote: > > Yeah, when I posted about this a few months ago people seemed > to think it > didn't matter.  The issue has been open for years and seems > catastrophic to > me.  > > Our solution is to never use "use" and only use "include" > which avoids the > problem.  I think there are other cases where "use" is slow as > well, though > not as serious.  > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
RP
Ronaldo Persiano
Mon, Jun 15, 2020 12:15 AM

in that library all transformations are just functiontions producing
matrices, and a sequence of transformations is easily accumulated into a
single multmatrix by the library, so essentialy all your code below will
break down into a single multmatrix operation in the CSG tree. all the
calculation itself is not passed CSG, it is just matrix multiplications, so
essentially every combination of input variabled becomes one matrix value
and i think this will be chached right?

As far as I know, they will not be cached. Only solids, models, objects are
cached. Variables are not.

> > in that library all transformations are just functiontions producing > matrices, and a sequence of transformations is easily accumulated into a > single multmatrix by the library, so essentialy all your code below will > break down into a single multmatrix operation in the CSG tree. all the > calculation itself is not passed CSG, it is just matrix multiplications, so > essentially every combination of input variabled becomes one matrix value > and i think this will be chached right? > As far as I know, they will not be cached. Only solids, models, objects are cached. Variables are not.
NH
nop head
Mon, Jun 15, 2020 8:17 AM

Yes that is the problem. If you have some complex code that generates a
solid it is all run on every update, the parameters it generates are then
compared with the cached solids to see if the geometry needs updating. In
my project that takes no time at all but running all the code to generate
thousands of parts starts to take a long time. I think this is mainly
because every constant that isn't in your top level file gets evaluated
over and over again.

For isolation I have individual files that I can load on their own, for
example the z axis assembly, which is quite complex. At the start of the
file it has a lot of constants to work out positions, etc. It also includes
definitions of all the vitamins it uses, which are hundreds of lists.  It
also needs to export a few functions and modules to the rest of the
machine, which just export constants, like the total height.
However calling any of these means all the hundreds of constants it uses
are all evaluated over and over again. So even on a PC it starts to take
significant time. It really shouldn't take that long to evaluate a script
but the constant evaluation explosion does as soon as you separate a
project into lots of files.

On Mon, 15 Jun 2020 at 01:16, Ronaldo Persiano rcmpersiano@gmail.com
wrote:

in that library all transformations are just functiontions producing

matrices, and a sequence of transformations is easily accumulated into a
single multmatrix by the library, so essentialy all your code below will
break down into a single multmatrix operation in the CSG tree. all the
calculation itself is not passed CSG, it is just matrix multiplications, so
essentially every combination of input variabled becomes one matrix value
and i think this will be chached right?

As far as I know, they will not be cached. Only solids, models, objects
are cached. Variables are not.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Yes that is the problem. If you have some complex code that generates a solid it is all run on every update, the parameters it generates are then compared with the cached solids to see if the geometry needs updating. In my project that takes no time at all but running all the code to generate thousands of parts starts to take a long time. I think this is mainly because every constant that isn't in your top level file gets evaluated over and over again. For isolation I have individual files that I can load on their own, for example the z axis assembly, which is quite complex. At the start of the file it has a lot of constants to work out positions, etc. It also includes definitions of all the vitamins it uses, which are hundreds of lists. It also needs to export a few functions and modules to the rest of the machine, which just export constants, like the total height. However calling any of these means all the hundreds of constants it uses are all evaluated over and over again. So even on a PC it starts to take significant time. It really shouldn't take that long to evaluate a script but the constant evaluation explosion does as soon as you separate a project into lots of files. On Mon, 15 Jun 2020 at 01:16, Ronaldo Persiano <rcmpersiano@gmail.com> wrote: > in that library all transformations are just functiontions producing >> matrices, and a sequence of transformations is easily accumulated into a >> single multmatrix by the library, so essentialy all your code below will >> break down into a single multmatrix operation in the CSG tree. all the >> calculation itself is not passed CSG, it is just matrix multiplications, so >> essentially every combination of input variabled becomes one matrix value >> and i think this will be chached right? >> > > As far as I know, they will not be cached. Only solids, models, objects > are cached. Variables are not. > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
P
pproj@posteo.de
Mon, Jun 15, 2020 11:36 AM

i think one possible approach would be to do big Part of the  caching
yourself, that is use lookup tables.
so if all transformation sequences are accumulated into single matrices,
i would create a vector of matrices of all transformations you will
need, and write it out as long string into lookup.scad file
 this lookup.scad containing only single assignment of the lookup vector
of matrices: lookup=[[1,2,2,2,...}[5,34,887,87,..], yadda yadda];
then just include the lookup.scad and use the
multmatrix(lookup[indexofNeededVal])
in the main code
creating lookup tables is never the most elegant approach,but still,
flexible enough, and will probably save a lot of rendering time. 

On 15.06.20 10:17, nop head wrote:

Yes that is the problem. If you have some complex code that generates
a solid it is all run on every update, the parameters it generates are
then compared with the cached solids to see if the geometry needs
updating. In my project that takes no time at all but running all the
code to generate thousands of parts starts to take a long time. I
think this is mainly because every constant that isn't in your top
level file gets evaluated over and over again. 

For isolation I have individual files that I can load on their own,
for example the z axis assembly, which is quite complex. At the start
of the file it has a lot of constants to work out positions, etc. It
also includes definitions of all the vitamins it uses, which are
hundreds of lists.  It also needs to export a few functions and
modules to the rest of the machine, which just export constants, like
the total height. However calling any of these means all the hundreds
of constants it uses are all evaluated over and over again. So even on
a PC it starts to take significant time. It really shouldn't take that
long to evaluate a script but the constant evaluation explosion does
as soon as you separate a project into lots of files.

On Mon, 15 Jun 2020 at 01:16, Ronaldo Persiano <rcmpersiano@gmail.com
mailto:rcmpersiano@gmail.com> wrote:

     in that library all transformations are just functiontions
     producing matrices, and a sequence of transformations is
     easily accumulated into a single multmatrix by the library, so
     essentialy all your code below will break down into a single
     multmatrix operation in the CSG tree. all the calculation
     itself is not passed CSG, it is just matrix multiplications,
     so essentially every combination of input variabled becomes
     one matrix value and i think this will be chached right?


 As far as I know, they will not be cached. Only solids, models,
 objects are cached. Variables are not.
 _______________________________________________
 OpenSCAD mailing list
 Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org>
 http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

i think one possible approach would be to do big Part of the  caching yourself, that is use lookup tables. so if all transformation sequences are accumulated into single matrices, i would create a vector of matrices of all transformations you will need, and write it out as long string into lookup.scad file  this lookup.scad containing only single assignment of the lookup vector of matrices: lookup=[[1,2,2,2,...}[5,34,887,87,..], yadda yadda]; then just include the lookup.scad and use the multmatrix(lookup[indexofNeededVal]) in the main code creating lookup tables is never the most elegant approach,but still, flexible enough, and will probably save a lot of rendering time.  On 15.06.20 10:17, nop head wrote: > Yes that is the problem. If you have some complex code that generates > a solid it is all run on every update, the parameters it generates are > then compared with the cached solids to see if the geometry needs > updating. In my project that takes no time at all but running all the > code to generate thousands of parts starts to take a long time. I > think this is mainly because every constant that isn't in your top > level file gets evaluated over and over again.  > > For isolation I have individual files that I can load on their own, > for example the z axis assembly, which is quite complex. At the start > of the file it has a lot of constants to work out positions, etc. It > also includes definitions of all the vitamins it uses, which are > hundreds of lists.  It also needs to export a few functions and > modules to the rest of the machine, which just export constants, like > the total height. However calling any of these means all the hundreds > of constants it uses are all evaluated over and over again. So even on > a PC it starts to take significant time. It really shouldn't take that > long to evaluate a script but the constant evaluation explosion does > as soon as you separate a project into lots of files. > > On Mon, 15 Jun 2020 at 01:16, Ronaldo Persiano <rcmpersiano@gmail.com > <mailto:rcmpersiano@gmail.com>> wrote: > > in that library all transformations are just functiontions > producing matrices, and a sequence of transformations is > easily accumulated into a single multmatrix by the library, so > essentialy all your code below will break down into a single > multmatrix operation in the CSG tree. all the calculation > itself is not passed CSG, it is just matrix multiplications, > so essentially every combination of input variabled becomes > one matrix value and i think this will be chached right? > > > As far as I know, they will not be cached. Only solids, models, > objects are cached. Variables are not. > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
NH
nop head
Mon, Jun 15, 2020 11:57 AM

But it is then no longer parametric, the main reason for using OpenSCAD.

It isn't particularly slow to multiply matrices. It is only when it is done
over and over again. I sped it up considerably by caching functions calls
like this.

function shelf_screw_positions() = let(sw = spine_width(), sd =
spine_depth(), bc = box_intrusion(box_type) +
box_bezel_clearance(box_type)) [
translate([z_axis_x + sw / 2, box_depth / 2 - sd + spine_clearance +
shelf_boss_r + eps]) * rotate([-90, 0, 90]),
translate([z_axis_x + sw / 2, box_depth / 2 - shelf_boss_r - eps])
* rotate([-90, 0, 90]),

translate([-box_width / 4,               box_depth / 2])
               * rotate([-90, 0,  0]),

translate([box_width / 2,                box_depth / 2 - bc -

shelf_boss_r - eps])        * rotate([-90, 0, -90]),
translate([box_width / 2,              -box_depth / 2 + bc +
shelf_boss_r + eps])        * rotate([-90, 0, -90]),

translate([ 10, -box_depth / 2])
               * rotate([-90, 0, 180]),
translate([-10, -box_depth / 2])
               * rotate([-90, 0, 180]),

translate([-box_width / 2,               box_depth / 2 - bc -

shelf_boss_r - eps])        * rotate([-90, 0, 90]),
translate([-box_width / 2,              -box_depth / 2 + bc +
shelf_boss_r + eps])        * rotate([-90, 0, 90]),

translate([z_axis_x - sw / 2, box_depth / 2 - sd + spine_clearance +

shelf_boss_r + eps]) * rotate([-90, 0, -90]),
translate([z_axis_x - sw / 2, box_depth / 2 - shelf_boss_r - eps])
* rotate([-90, 0, -90]),
];

The three functions I calculate once in the let() and then reuse two or
three times are trivial functions but they are slow because they are in a
used file that has lots of constants defined in it. So each time they are
called lots of constants are evaluated again. Also this function should be
a constant, not a function, but then it gets evaluated whenever something
else is used from the file that defines it.

I got a  big speed up making it a function until I added more code that
called it, so I can't win. There is no way to calculate a constant once and
store it except to do it in the main file, but then it can't be accessed
from any other file unless they are all included. Then they can't be used
standalone and that breaks my build system because it locates stls and
assemblies in the file that defines them and calls them from the command
line. So each file has to be self contained and include or use all its
dependencies.

On Mon, 15 Jun 2020 at 12:37, pproj@posteo.de pproj@posteo.de wrote:

i think one possible approach would be to do big Part of the  caching
yourself, that is use lookup tables.
so if all transformation sequences are accumulated into single matrices,
i would create a vector of matrices of all transformations you will need,
and write it out as long string into lookup.scad file
this lookup.scad containing only single assignment of the lookup vector
of matrices: lookup=[[1,2,2,2,...}[5,34,887,87,..], yadda yadda];
then just include the lookup.scad and use the
multmatrix(lookup[indexofNeededVal])
in the main code
creating lookup tables is never the most elegant approach,but still,
flexible enough, and will probably save a lot of rendering time.

On 15.06.20 10:17, nop head wrote:

Yes that is the problem. If you have some complex code that generates a
solid it is all run on every update, the parameters it generates are then
compared with the cached solids to see if the geometry needs updating. In
my project that takes no time at all but running all the code to generate
thousands of parts starts to take a long time. I think this is mainly
because every constant that isn't in your top level file gets evaluated
over and over again.

For isolation I have individual files that I can load on their own, for
example the z axis assembly, which is quite complex. At the start of the
file it has a lot of constants to work out positions, etc. It also includes
definitions of all the vitamins it uses, which are hundreds of lists.  It
also needs to export a few functions and modules to the rest of the
machine, which just export constants, like the total height.
However calling any of these means all the hundreds of constants it uses
are all evaluated over and over again. So even on a PC it starts to take
significant time. It really shouldn't take that long to evaluate a script
but the constant evaluation explosion does as soon as you separate a
project into lots of files.

On Mon, 15 Jun 2020 at 01:16, Ronaldo Persiano rcmpersiano@gmail.com
wrote:

in that library all transformations are just functiontions producing

matrices, and a sequence of transformations is easily accumulated into a
single multmatrix by the library, so essentialy all your code below will
break down into a single multmatrix operation in the CSG tree. all the
calculation itself is not passed CSG, it is just matrix multiplications, so
essentially every combination of input variabled becomes one matrix value
and i think this will be chached right?

As far as I know, they will not be cached. Only solids, models, objects
are cached. Variables are not.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


OpenSCAD mailing listDiscuss@lists.openscad.orghttp://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

But it is then no longer parametric, the main reason for using OpenSCAD. It isn't particularly slow to multiply matrices. It is only when it is done over and over again. I sped it up considerably by caching functions calls like this. function shelf_screw_positions() = let(sw = spine_width(), sd = spine_depth(), bc = box_intrusion(box_type) + box_bezel_clearance(box_type)) [ translate([z_axis_x + sw / 2, box_depth / 2 - sd + spine_clearance + shelf_boss_r + eps]) * rotate([-90, 0, 90]), translate([z_axis_x + sw / 2, box_depth / 2 - shelf_boss_r - eps]) * rotate([-90, 0, 90]), translate([-box_width / 4, box_depth / 2]) * rotate([-90, 0, 0]), translate([box_width / 2, box_depth / 2 - bc - shelf_boss_r - eps]) * rotate([-90, 0, -90]), translate([box_width / 2, -box_depth / 2 + bc + shelf_boss_r + eps]) * rotate([-90, 0, -90]), translate([ 10, -box_depth / 2]) * rotate([-90, 0, 180]), translate([-10, -box_depth / 2]) * rotate([-90, 0, 180]), translate([-box_width / 2, box_depth / 2 - bc - shelf_boss_r - eps]) * rotate([-90, 0, 90]), translate([-box_width / 2, -box_depth / 2 + bc + shelf_boss_r + eps]) * rotate([-90, 0, 90]), translate([z_axis_x - sw / 2, box_depth / 2 - sd + spine_clearance + shelf_boss_r + eps]) * rotate([-90, 0, -90]), translate([z_axis_x - sw / 2, box_depth / 2 - shelf_boss_r - eps]) * rotate([-90, 0, -90]), ]; The three functions I calculate once in the let() and then reuse two or three times are trivial functions but they are slow because they are in a used file that has lots of constants defined in it. So each time they are called lots of constants are evaluated again. Also this function should be a constant, not a function, but then it gets evaluated whenever something else is used from the file that defines it. I got a big speed up making it a function until I added more code that called it, so I can't win. There is no way to calculate a constant once and store it except to do it in the main file, but then it can't be accessed from any other file unless they are all included. Then they can't be used standalone and that breaks my build system because it locates stls and assemblies in the file that defines them and calls them from the command line. So each file has to be self contained and include or use all its dependencies. On Mon, 15 Jun 2020 at 12:37, pproj@posteo.de <pproj@posteo.de> wrote: > i think one possible approach would be to do big Part of the caching > yourself, that is use lookup tables. > so if all transformation sequences are accumulated into single matrices, > i would create a vector of matrices of all transformations you will need, > and write it out as long string into lookup.scad file > this lookup.scad containing only single assignment of the lookup vector > of matrices: lookup=[[1,2,2,2,...}[5,34,887,87,..], yadda yadda]; > then just include the lookup.scad and use the > multmatrix(lookup[indexofNeededVal]) > in the main code > creating lookup tables is never the most elegant approach,but still, > flexible enough, and will probably save a lot of rendering time. > > On 15.06.20 10:17, nop head wrote: > > Yes that is the problem. If you have some complex code that generates a > solid it is all run on every update, the parameters it generates are then > compared with the cached solids to see if the geometry needs updating. In > my project that takes no time at all but running all the code to generate > thousands of parts starts to take a long time. I think this is mainly > because every constant that isn't in your top level file gets evaluated > over and over again. > > For isolation I have individual files that I can load on their own, for > example the z axis assembly, which is quite complex. At the start of the > file it has a lot of constants to work out positions, etc. It also includes > definitions of all the vitamins it uses, which are hundreds of lists. It > also needs to export a few functions and modules to the rest of the > machine, which just export constants, like the total height. > However calling any of these means all the hundreds of constants it uses > are all evaluated over and over again. So even on a PC it starts to take > significant time. It really shouldn't take that long to evaluate a script > but the constant evaluation explosion does as soon as you separate a > project into lots of files. > > On Mon, 15 Jun 2020 at 01:16, Ronaldo Persiano <rcmpersiano@gmail.com> > wrote: > >> in that library all transformations are just functiontions producing >>> matrices, and a sequence of transformations is easily accumulated into a >>> single multmatrix by the library, so essentialy all your code below will >>> break down into a single multmatrix operation in the CSG tree. all the >>> calculation itself is not passed CSG, it is just matrix multiplications, so >>> essentially every combination of input variabled becomes one matrix value >>> and i think this will be chached right? >>> >> >> As far as I know, they will not be cached. Only solids, models, objects >> are cached. Variables are not. >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > > _______________________________________________ > OpenSCAD mailing listDiscuss@lists.openscad.orghttp://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >