OpenJSCAD.org icon indicating copy to clipboard operation
OpenJSCAD.org copied to clipboard

Allow scripts to cache geometries when parameters change

Open hrgdavor opened this issue 3 years ago โ€ข 29 comments

Expected Behavior

call main function with new parameters without reloading the script

Actual Behavior

script is reloaded completely

Steps to Reproduce the Problem

  1. load https://openjscad.xyz/?uri=http://3d.hrg.hr/jscad/three/examples/parametric_butt_hinge_3.7.js
  2. change "throw angle"
  3. it should change instantly, but the whole script is reloaded so no caching is possible

Specifications

  • Version: V2
  • Platform: all
  • Environment: browser

hrgdavor avatar Apr 22 '21 13:04 hrgdavor

I tried to tackle this one as well, but this code style of streams all over the place is freaky difficult for me to follow.

I could not find where the events for rebuildSolids originate to be able to insert source:

  • model reloaded
  • parameter changed

so worker could be left alive and able to use cached reference to main method of the jscad script

and even if I do find a way to transmit tihs extra info to worker the issue is that workers are not reused, but are terminated and recreated.

packages/core/src/sideEffects/worker/index.js lines 18,19

        _worker.terminate()// FIXME: sub optimal ! worker recreation is SLOW and should not be systematic
        _worker = WebWorkify(workerPath)// new Worker(workerPath)

whoever implemented this also noticed it is sub-optimal, and left a TODO

side note: file called rebuildGeometry actually provides function rebuildSolids which is incosistent.

hrgdavor avatar May 02 '21 20:05 hrgdavor

If somebody could help inject info for the source of the rebuild: "model relaod" vs "parameters change"

I could play around with making the worker reusable. It will have issues to cover with multiple changes to paramters incomming while script re-evaluets the model if the re-eval is slow.

hrgdavor avatar May 02 '21 20:05 hrgdavor

@z3dev please help ๐Ÿ™ ๐Ÿ™

hrgdavor avatar May 06 '21 09:05 hrgdavor

The key is the VTREE package, as that has the start of the caching per shape / geometry. However, it's not well tested.

In addition, it's totally disabled in the WEB UI.

IF caching should come back then there's a BIG PILE of work to complete.

z3dev avatar May 06 '21 09:05 z3dev

I might be mistaken, but I think this is not about vtree or full blown caching of rendering of geometries, I am talking about the simple fact that whole jscad script is re-evaluated every time thus leaving zero chance to cache result of expensive operations like booleans.

This is one small step that could help right away, and will be useful in the future caching .

Could you please just help me so I can discern the difference:

  • model reloaded
  • parameter changed

I dont think it would have any negative sideffects for the app, but would enable me to experiment.

All these observables and sinks are unnatural to me, and seeing how this is done would also help me to understand the inner workings of the project a bit more.

I have recreated script execution and rendering portion using Three.js and this is my preferred env for creating jscad models. I am more productive in that setup, but I want to give back to jscad those things so others can benefit.

hrgdavor avatar May 06 '21 09:05 hrgdavor

I might be mistaken, but I think this is not about vtree or full blown caching of rendering of geometries,

Please review the VTREE package. I think that you will understand quickly. Basically, it duplicates the API of modeling (except for special cases), and caches every call as well as the results. And... reuses the โ€˜treeโ€™ for everything that hasnโ€™t changed.

Itโ€™s cool but needs a lot of work to make it โ€˜stableโ€™

z3dev avatar May 06 '21 10:05 z3dev

could you please help me with this so I can know when worker is called the reason is:

  • model reloaded
  • parameter changed ๐Ÿ™ ๐Ÿ™ pls pls help me ๐Ÿ‘ผ it is all in vain if I don't fix the worker, as there is no way any cache implementation will work with the context being destroyed on each param change.

I am not sure I would go in the direction vtree is going, especially since it looks like: "all or nothing" approach. I could be convinced to try to get it working as I am motivated to fix performace stuff.

in the end I prefer small improvements that can be made sooner. So please help meee

hrgdavor avatar May 06 '21 11:05 hrgdavor

could you please help me with this so I can know when worker is called the reason is...

Let's back up.

Designs export main() and getParameterDefinitions(). There are two exported functions but only one 'evaluation' of the main javascript module (file).

It's even more complicated than that as V2 duplicates the order of 'evaluation' that Node.js uses. Complex designs can be composed of several files, sub-directories, etc. The WHOLE FILE SYSTEM is passed to the rebuildGeometry() function (See the core package).

FYI, I would like to bring back VTREE (caching) but there's too many other pressing changes.

And you are correct. There are plenty of performance improvements as well. I've been trying to raise those as issues now, and appreciate the help to improve everything.

z3dev avatar May 07 '21 00:05 z3dev

Last time i tested the whole script is re-evaluated on parameter change. Just add some console log in script body outside of main, and test the script by changing params. Console log is called every time.

hrgdavor avatar May 07 '21 05:05 hrgdavor

open these 2 examples and change params after you F12 open dev console https://openjscad.xyz/?uri=http://3d.hrg.hr/jscad/three/examples/sphere.js http://3d.hrg.hr/jscad/three/threejscad.html?uri=examples/sphere.js

console.log('Script evaluated ', new Date())
function main({ radius= 10}){
  console.log('main called ', new Date())
  return sphere({radius})
}

hrgdavor avatar May 07 '21 06:05 hrgdavor

Last time i tested the whole script is re-evaluated on parameter change. Just add some console log in script body outside of main, and test the script by changing params. Console log is called every time.

Correct. Think about this... it's a complex design... maybe with a parameter that says 'USE B-STATISTICS'... which resides in a JSON file. The whole procedural stack has changed.

So, now what do you do?

z3dev avatar May 07 '21 06:05 z3dev

The code did not change, so there is no need for re-eval the script. if the code loads something else based on the parameter, still code did not change, an no need to re-eval the script.

If you produce an example example I would gladly investigate.

hrgdavor avatar May 07 '21 06:05 hrgdavor

if the code loads something else based on the parameter, still code did not change, an no need to re-eval the script.

The worker thread does not cache the 'evaluated' code. The exchange is like this...

  1. Drag-n-drop file/folder to WEB UI
  2. main thread read file contents and creates 'fake' file system
  3. main thread sends file system to worker thread for evaluation
  4. worker thread evaluates code, starting from 'index'
  5. worker thread calls getParameterDefinitions()
  6. worker thread sends parameter definitions / defaults to main thread
  7. worker thread calls main()
  8. worker thread sends results of main() to main thread
  9. main thread renders results

z3dev avatar May 07 '21 06:05 z3dev

yeah, but the whole process is also repeated for every parameter change:

1 change parameters 2 main thread sends file system to worker thread for evaluation 3 worker thread evaluates code, starting from 'index' 4 worker thread calls getParameterDefinitions() 5 worker thread sends parameter definitions / defaults to main thread 6 worker thread calls main() 7 worker thread sends results of main() to main thread 8 main thread renders results

thus disabling any type of caching optimization for between parameter changes

all I am asking here is a little help form you to discern the two scenarios where worker is called by script loading versus param change... why won't you help me ?

hrgdavor avatar May 07 '21 06:05 hrgdavor

thus disabling any type of caching optimization for between parameter changes

So you think that 'evaluation' of the code is taking the major time? I doubt that. It's the total number of small allocations for points, polygons, etc. The creation of the geometry is taking the major time.

For example, create a design that adjusts the 'segments' on a sphere, and perform some boolean operations. The performance gets worse as the number of 'segments' grows.

This is where VTREE can assist as it does caching of those geometries.

z3dev avatar May 07 '21 06:05 z3dev

all I am asking here is a little help form you to discern the two scenarios where worker is called by script loading versus param change... why won't you help me ?

Just see web/src/ui/flows/design.js as this is the main 'controller' for the solid generation.

z3dev avatar May 07 '21 07:05 z3dev

yes, but there is zero chance to optimize by reusing some operations results if code is revaluated every time.

The way I see it, there are multiple levels to optimize the final user experience and you are only focusing on a singular part and that is internal optimization of the operations.

level1 - internal speed for operations level2 - reuse of some generated solids when parameters change ... this can help immensely for slow booleans that are now re-executed on every parameter change level3 - opengl reuse of geometries that are the same basic shape but transformed and with different color

You are right about level1 and you are expert there and I cant help you there, but you seem to miss my point that I am looking to improve level2 and leve3 and not interfere with you.

I am not saying leve2 and level3 are more important, just saying they are important too.

Actually I have made significant improvements on level2 and level3 in my evaluator and renderer based on three.js

I have mentioned those performance and user experience improvements in this article: https://openjscad.nodebb.com/topic/247/three-js-integration-part2-threejscad

Example of my level2 optimization (reuse solids) ... I only changed like 5 lines of code in original script https://openjscad.xyz/?uri=http://3d.hrg.hr/jscad/three/examples/parametric_butt_hinge_3.7.js change throw angle and wait and wait to see result

http://3d.hrg.hr/jscad/three/threejscad.html?uri=examples/parametric_butt_hinge_3.7.js change throw angle slider and see it change instantly like animation

Example of my level3 optimization (opengl reuse ) https://openjscad.xyz/?uri=https://openjscad.xyz/examples/core/colors/colorCube.js change colorize method and wait and wait

http://3d.hrg.hr/jscad/three/threejscad.html?uri=examples/core/colors/colorCube.js change colorize method and it is instant

I have already made these for my self and use them with joy, now I would like to make that also for openjscad and I get the feeling you do not want me to ๐Ÿ˜ญ ...

hrgdavor avatar May 07 '21 07:05 hrgdavor

Just see web/src/ui/flows/design.js as this is the main 'controller' for the solid generation.

I have found it before and seen it, I have seen it again.....

it is just so very confusing for me this style of code, and I can't understand it enough to inject the info I need in the worker... my mindset is object oriented and I use observables and streams and functional style only when I cant avoid it and in small quantities

that is the reason I am asking for your help so you do it... that small change would not break existing code, but would help me continue to explore the worker.

hrgdavor avatar May 07 '21 07:05 hrgdavor

I have already made these for my self and use them with joy, now I would like to make that also for openjscad and I get the feeling you do not want me to

Not at all.

There's no way that I can walk you through that maze of the WEB UI. The 'most' framework makes tracing and tracking almost impossible. There is no one function that handle a specific event. There is no one function that updates 'state'. Everything goes into 'most' streams, gets processed, and posts new events.

If you want to make a new WEB UI then please feel free to start. I'm sure you can produce something far more understandable, but there's a lot of functionality to support.

z3dev avatar May 07 '21 07:05 z3dev

And hopefully, those 'core' functions can be reused to 'evaluate' code and create geometry as well.

By the way, others are using V2 to create different interfaces using different frameworks. So, I think you are working on some thing great.

z3dev avatar May 07 '21 07:05 z3dev

so, the dev that chose 'most' framework is no longer here ? or someone else that understands how it works ?

hrgdavor avatar May 07 '21 07:05 hrgdavor

so, the dev that chose 'most' framework is no longer here ? or someone else that understands how it works ?

BINGO! Now you understand!

z3dev avatar May 07 '21 07:05 z3dev

Actually, IF you are interested then please work with the OpenJSCAD.org packages. Your version of the WEB UI can live side-by-side until ready. And if there are changes required to the 'core', 'io', etc then those can be integrated as well.

z3dev avatar May 07 '21 07:05 z3dev

is the dev that made regl-renderer still here or sbdy that understands it ? I found it easier to navigate three.js even tho it is huge... I think it would be at least for now easier for me to make compatible renderer in threejs and if you prefer regl-renderer we could make them both as option.

hrgdavor avatar May 07 '21 07:05 hrgdavor

I think it would be at least for now easier for me to make compatible renderer in threejs and if you prefer regl-renderer we could make them both as option.

Sounds like a reasonable first step... creating a new renderer.

z3dev avatar May 07 '21 08:05 z3dev

is the dev that made regl-renderer still here or sbdy that understands it ?

I'm starting to understand but nothing in WEB GL is easy. And I always find little bugs that need patching.

z3dev avatar May 07 '21 08:05 z3dev

ok, it is ok then that I play around with threejs for the new web ui in a separate repo? is threejs possible as a future direction or future alternative paralel with regl-renderer ?

hrgdavor avatar May 07 '21 08:05 hrgdavor

ok, it is ok then that I play around with threejs for the new web ui in a separate repo? is threejs possible as a future direction or future alternative paralel with regl-renderer ?

Absolutely! Iโ€™m more interested in having a group of enthusiastic developers. So, anything is possible.

z3dev avatar May 07 '21 12:05 z3dev

I was actually concerned such approach would be discouraged, and looks like I was too paranoid.

Ok then. I will continue to explore and brag about what I make ๐Ÿ˜„ .

When I make tolls for myself I do it with scrappy/nasty-ass code that somehow works. Then we can look into how to do it nicely within opanjscad. ๐Ÿ˜ƒ

I will leave this issue open, as it will be nice to have it regardless if it is current web-ui or some new one.

hrgdavor avatar May 07 '21 12:05 hrgdavor