OpenJSCAD.org
OpenJSCAD.org copied to clipboard
Allow scripts to cache geometries when parameters change
Expected Behavior
call main function with new parameters without reloading the script
Actual Behavior
script is reloaded completely
Steps to Reproduce the Problem
- load https://openjscad.xyz/?uri=http://3d.hrg.hr/jscad/three/examples/parametric_butt_hinge_3.7.js
- change "throw angle"
- it should change instantly, but the whole script is reloaded so no caching is possible
Specifications
- Version: V2
- Platform: all
- Environment: browser
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.
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.
@z3dev please help ๐ ๐
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.
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.
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โ
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
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.
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.
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})
}
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?
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.
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...
- Drag-n-drop file/folder to WEB UI
- main thread read file contents and creates 'fake' file system
- main thread sends file system to worker thread for evaluation
- worker thread evaluates code, starting from 'index'
- worker thread calls getParameterDefinitions()
- worker thread sends parameter definitions / defaults to main thread
- worker thread calls main()
- worker thread sends results of main() to main thread
- main thread renders results
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 ?
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.
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.
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 ๐ญ ...
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.
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.
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.
so, the dev that chose 'most' framework is no longer here ? or someone else that understands how it works ?
so, the dev that chose 'most' framework is no longer here ? or someone else that understands how it works ?
BINGO! Now you understand!
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.
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.
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.
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.
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 ?
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.
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.