Disposing objects and restoring them - javascript

I am working on a three.js project that allows the user to switch through scenes that hold different mesh objects. They're all loaded into the project at the same time when the page has loaded, and all of these objects have textures which weigh heavily on the performance.
So to fix this, I want to temporarily remove all the objects in all of the scenes that the user has not selected. So, with 10 scenes, should the user for example select to see what's in scene 4 (which would be the currentScene), then scene 1 through 3 and 5 through 10 should have no objects that put an unnecessary strain on the performance. This should account as well for when the page has loaded. Only when the user selects one of those aforementioned scenes again, then it restores the scenes' objects.
This FIDDLE is an example of my project that encompasses the essential code. I am using the remove() and dispose() methods to achieve it.
//scene that's to be removed and disposed of
var destroyScenes = scenes[1];
//removes and disposes all objects in above scene
for (i = destroyScenes.children.length - 1; i >= 0; i--) {
obj = destroyScenes.children[i];
destroyScenes.remove(obj);
obj.geometry.dispose();
obj.material.dispose();
obj.texture.
}
My concrete question(s) is this:
How do I restore the objects if I remove and dispose of them? Is that a good approach to it, is it even possible, and/or is there a better way of achieving this?
Also, if that is a way to do it, how do I select all of the scenes except for the currentScene?
PS: I'm well aware that it'll put a loading time switching between scenes, but I'd still much more prefer that.

How do I restore the objects if I remove and dispose of them?
- If you dispose object right, you must load it again, which is ugly
Is that a good approach to it, is it even possible, and/or is there a better way of achieving this?
- If you plan to show object again, it is better to set obj.visible = false; Loading and disposing again is the worst performance method. Some things (as is fog etc..) cannot be applied correctly after loading object later.
Also, if that is a way to do it, how do I select all of the scenes except for the currentScene?
- Not sure about question, make a new question for that. (by controlling mouse move i guess)
I'm well aware that it'll put a loading time switching between scenes, but I'd still much more prefer that.
- It's not a way how it works. Scenes are running at the same time, you can stop animation frame for inactive scenes. But scenes will load on initialisation, not during switching them.
Ask always only one question pls.

Related

Speed difference between inserting html and changing display style property

Assuming you have a relatively small piece of HTML (let's say under 100 tags and <4KB in size) and you want to occasionally display and hide it from your user (think menu, modal... etc).
Is the fastest approach to hide and show it using css, such as:
//Hide:
document.getElementById('my_element').style.display = 'none';
//Show:
document.getElementById('my_element').style.display = 'block';
Or to insert and remove it:
//Hide
document.getElementById('my_element_container').innerHTML = '';
//Show:
const my_element_html = {contents of the element};
document.getElementById('my_element_container').innerHTML = my_element_html;
// Note: insertAdjacentHTML is obviously faster when the container has other elements, but I'm showcasing this using innerHTML to get my point across, not necessarily because it's always the most efficient of the two.
Obviously, this can be benchmarked on a case by case basis, but, with some many browser versions and devices out there, any benchmarks that I'd be able to run in a reasonable amount of time aren't that meaningful.
I've been unable to find any benchmarks related to this subject.
Are there any up to date benchmarks comparing the two approaches? Is there any consensus from browsers developers as to which should, generally speaking, be preferred when it comes to speed.
In principle, DOM manipulation is slower than toggling display property of existing nodes. And I could stop my answer here, as this is technically correct.
However, repaint and reflow of the page is typically way slower and both your methods trigger it so you could be looking at:
display toggle: 1 unit
DOM nodes toggle: 2 units
repaint + reflow of page: 100 units
Which leaves you comparing 101 units with 102 units, instead of comparing 3 with 4 (or 6 with 7). I'm not saying that's the order of magnitude, it really depends on the actual DOM tree of your real page, but chances are it's close to the figures above.
If you use methods like: visibility:hidden or opacity:0, it will be way faster, not to mention opacity is animatable, which, in modern UIs, is preferred.
A few resources:
Taming huge collections of DOMs
Render-tree Construction, Layout, and Paint
How Browsers Work: Behind the scenes of modern web browsers
An introduction to Web Performance and the Critical Rendering Path
Understanding the critical rendering path, rendering pages in 1 second
Web performance, much like web development, is not a "press this button" process. You need to try, fail, learn, try again, fail again...
If your elements are always the same, you might find out (upon testing) caching them inside a variable is much faster than recreating them when your show method is called.
Testing is quite simple:
place each of the methods inside a separate function;
log the starting time (using performance.now());
use each method n times, where n is: 100, 1e3, 1e4,... 1e7
log finishing time for each test (or difference from its starting time)
Compare. You will notice conclusions drawn from 100 test are quite different than the ones from 1e7 test.
To go even deeper, you can test differences for different methods when showing and for different methods when hiding. You could test rendering elements hidden and toggle their display afterwards. Get creative. Try anything you can think of, even if it seems silly or doesn't make much sense.
That's how you learn.

How games delete an object in the database but animate it out at the same time

I am wondering about how async actions like animations work when you do actions like delete an item, and so came up with this sort of thought process and would like feedback to see if it makes sense from an industry best practice perspective.
There are two layers:
The reactive layer.
The rendering layer.
The reactive layer occurs instantly and can be done with traditional event dispatching.
This is where you create and delete data and it all happens instantaneously.
The state machine gets notified of these instant reactive changes.
Then the state machine "transitions". This process occurs over a period of time, assuming there are some async things that occur (animations, network requests, etc.). This is what people mean when they say "action queue".
Then the rendering layer pics up stuff off the action queue and renders it. This way there is sort of a delayed reaction to the underlying instant reactive layer.
My question is if the reactive layer needs to handle async as well. For example, deleting something.
Say an item is deleted, and you want to animate it out. There are a few ways to do this:
Queue up a delete action, then animate it out first. When animation is complete, then do the actual delete. If animation is interrupted (cancel the delete), then the delete is never performed.
Delete the item instantly (reactive layer). The animation layer keeps a reference to the item around, so can still do its animation even though from the global place it is deleted. If the animation is cancelled, then you would have to do an "undo" sort of thing which is more complex.
If (1) is the way to go, then there is no reactive layer, and everything is implemented with a sort of action queue in mind. This makes it harder to make reusable code because everything is tied to the action-queue idea.
If (2) is the way to go, then there are two copies of the data, the global copy, and the local copy, which is kept in sync asynchronously. This makes it easier to have reusable code but makes it more complicated to reason about.
Wondering if any of this makes sense, and if any of these approaches is better practice in the industry (or if there is an alternative I didn't address that makes more sense).
Put another way, there are two main ways to do it:
Eager: Delete it now, okay everyone we've deleted it, time to come back inside. And wait for everything to trinkle back in to call it "done".
Cautious: Announce "we are going to delete it", then wait til everything is done and comes back inside to actually do the delete.
Wondering how games and apps and such handle this sort of thing.
Update
After thinking about it a different way, maybe it would be more like the swaying of kelp in the ocean:
https://www.youtube.com/watch?v=gIeLCzR8EgA
By that I mean, there is a base layer that is immediate (does the create/delete), then there are some intermediate layers with copies of all the transactions that occurred (create/delete), that the rendering layer uses to animate create/delete. So the original data is always in sync, but the rendering layer uses a sort of older version of the data with a chain of all the changes taking place.
reactive layer -> transaction layer -> rendering layer.
Another option is flagging as delete, then only after animations are complete actually do the delete, but that seems hacky.
Update
Another version:
Reactive version
Always has the latest data. (a)
Rendering version
Has the last data (b), plus a chain of changes leading to (a).
As rendering completes, it applies the changes to (b), so eventually it is like (a).
from my experiece as Unity Game Developer the right decision is in the middle, as for the physics in game engine are approximated because the sensation of a things semi-perfect is pretty like a perfect one.
The explanation is because the more realistic and real-life like is your goal the more you need resources, not only CPU and GPU but cash too.
after this strange preamble I quote for the flag options, the method applicated is not much different than a normal Garbade Collector, you mark a no more usefull item and when the Garbage collector come he free the ram space used by this object, so this new space can be reused.
The same process is done by a lot of engine, and the destroy operation appens before the rendering calculations.
The final goal is always to reach a good in-between solution.
There is the possibility to force the instant destruction in every moment of the engine computation process, but this solution is always deprecated.
With the animation the way u typically use is to Destroy (setting flag to be destructed) at the end of the animation or in the last few frames.
At least you can use some tricks to make the fade more enjoyable (like particles).
The real problem is when you have to destroy object over the net (multiplayer games), in this case you have to establish what is the more attendible machine and pick that to calculate physics and interaction, this machine is always the server or the at least the host(depending on the game type).
I know that the question was marked as javascript question, but i couldn't resist to answer.
I enclose also a page from the unity documentation about the Destruct function were explain how they menage to remove item from a game enviroment:
https://docs.unity3d.com/ScriptReference/Object.Destroy.html
Have a nice day! and good coding.

lots of backbone views - performance issues?

tl;dr: I wonder if having lots (100+ for the moment, potentially up to 1000/2000 or more) of backbone views (as a cell of a table) is too heavy or not
The project I'm working on revolves around a planning view. There one row per user that covers 6 hours of a day, each hour splitted in 4 slots of 15mn. This planning is used to add "reservations" when clicking on a slot, and should handle hovering of the correct slots, and also handle when it is NOT possible to make a reservation - ie. prevent user click on an "unavailable" slot.
There is many reasons why a slot can't be clicked on: the user is not available at this time, or the user is in a reservation; or the app needs to "force" a delay slot between two reservations. Reservations (a div) are rendered in a slot (a cell of a table), and by toying with dimensions, hovers the right number of slots.
All this screen is handled with backbone. So For each slot I'm hovering on, I need to check wether I can do a reservation here or not. As of this moment, I use this by toying with the data attributes on the slots : when a reservation object is added, the slots covered are "enhanced with (among others) the reservation object (the backbone view object).
But in some cases I don't quite have a grasp on now, it mixes up, and when the reservation view is removed, the slots are not "cleaned up" : the previous class is not reset correctly. It is probably something I've done wrong or badly, but this is only going to get heavier; I think I should use another class of Backbone views here, but I'm afraid the number of slots and thereof of views objects will be high and cause performance issue. I don't know mush about js perf so I'd like to have some feedback before jumping on that train. Any other advice on how to do this would be quite welcomed too.
Thanks for your time. If this is not clear enough, tell me, I'll try and rephrase it.
We have a pretty complex backbone.js app with potentially thousands of views at a given time. Our bottlenecks are mostly in memory leaks from views that have not been properly removed or eventdriven rendering that re-renders views needlessly. That said, the actual number of views doesn't seem to affect much. Backbone views are pretty lightweight, so as long as you don't have too much events bound to them, it's not that big of a problem.
You might run into performance issues, but the views probably isn't the problem.
What you might want to do though, if you do use thousands of views is to stash up the initial rendering into one big ´.html()´-call. You can do this by giving each view-element an id based on the view's cid and then you concatenate the view's html strings and afterwards you use setElement on each view to find its element again.
Maybe this helps a litte bit :
https://stackoverflow.com/a/7150279/1067061
btw.: i like your avatar ;)
backbone handles everything is the least performant way for the browser. If it's not fast enough you need to stop creating and destroying templates. Caching a template is almost no help at all.
Instead of calling the render function against, save out a variable to the jquery selector and when the model changes use the cached selector to update the DOM. This will give you the largest jump in performance off the bat.
$title = null,
init = function(){ $title = this.$el.find('h1'); },
onTitleChange = function(event){ $title.html(event.value) }
I'm working on a backbone view that is performant. It can render a collection with 1,000,000 models at over 120FPS. The code is up on Github. https://github.com/puppybits/BackboneJS-PerfView There are a lot of other optimizations that can be done. If you check out the PrefView it has comments on most of the optimizations.

Executing JavaScript "in the background"

do you have any experiences with the following problem: JavaScript has to run hundreds of performance intensive function calls which cannot be skipped and causing the browser to feel crashed for a few seconds (e.g. no scrolling and clicking)? Example: Imagine 500 calls for getting an elements height and then doing hundreds of DOM modifications, e.g. setting classes etc.
Unfortunately there is no way to avoid the performance intensive tasks. Web workers might be an approach, but they are not very well supported (IE...). I'm thinking of a timeout or callback based step by step rendering giving the browser time to do something in between. Do you have any experiences you can share on this?
Best regards
Take a look at this topic this is some thing related to your question.
How to improve the performance of your java script in your page?
If your doing that much DOM manipulation, you should probably clone the elements in question or the DOM itself, and do the changes on a cached version, and then replace the whole ting in one go or in larger sections, and not one element at the time.
What takes time is'nt so much the calculations and functions etc. but the DOM manipulation itself, and doing that only once, or a couple of times in sections, will greatly improve the speed of what you're doing.
As far as I know web workers aren't really for DOM manipulation, and I don't think there will be much of an advantage in using them, as the problem probably is the fact that you are changing a shitload of elements one by one instead of replacing them all in the DOM in one batch instead.
Here is what I can recommend in this case:
Checking the code again. Try to apply some standard optimisations as suggested, e.g. reducing lookups, making DOM modifications offline (e.g. with document.createDocumentFragment()...). Working with DOM fragments only works in a limited way. Retrieving element height and doing complex formating won't work sufficient.
If 1. does not solve the problem create a rendering solution running on demand, e.g. triggered by a scroll event. Or: Render step by step with timeouts to give the browser time to do something in between, e.g. clicking a button or scrolling.
Short example for step by step rendering in 2.:
var elt = $(...);
function timeConsumingRendering() {
// some rendering here related to the element "elt"
elt = elt.next();
window.setTimeout((function(elt){
return timeConsumingRendering;
})(elt));
}
// start
timeConsumingRendering();

Site navigation catching events and triggering the right actions

I have dabbled with jQuery and javascript (I'm afraid in that order) before but allways very simple stuff, like sliding elements up, adding/removing classes etc.
I've not worked with events and objects before.
Now I have an allready working intranet "app" that is programmed exactly how I would do it. Namely lots of (if not all) global functions and variables to show / hide & generally control the page elements. all this is controlled without a mouse, only by keys.
Seeing this (and getting slightly scared in the process) I got myself a copy of "Object-Oriented JavaScript" By Stoyan Stefanov ...
My problem now is that I understand I'm going to need to work with objects, prototypes and events...
I -think I- understand the concepts by themselves but am totally at a loss at how to start.
Another problem I have is that the same keys should trigger different actions, depending on the visible or active elements. up/right/down/left should control the menus but when a content is loaded(end of menu is reached) the same keys have to trigger completely different things. I think I need to work with event-namespaces here, right?
Since it is not the mouse that is triggering the events I have to catch them at a very high level and determine what actions have to be made depending on the active and visible elements. Since I dont really get to know with event.target which element triggered the event
for example: if menu1 is visible and "right" was pressed
either open sub-menu or load content.
I have made a few attempts but was not able to get away from letting everything stay globally:
jQuery('body').on('ok.menu.rc right.menu.rc',function(e){
var cur = jQuery('nav.active a.active').removeClass('active').addClass('selected');
jQuery('nav.active a:not(.selected)').addClass('disabled').parent().removeClass('active');
//cur.parent().removeClass('active');
get_entry(cur.attr('data-name')+'-');
//jQuery('body').off('.menu'); // testing namespaces
jQuery('#menu1wrap nav').removeAttr('class').addClass('active');
});
And still nowhere near any kind of reuse-ability. It probably does not seem like it, but I have made several (and at least 2 different) attempts but grew frustrated pretty quickly.
Especially when trying out to put everything into objects. I wouldn't know how to link the html-elements with the instances of the javascript objects.
How would you take this beast on?

Categories

Resources