Webgl Context Lost and not restored - javascript

I have a problem with webgl context lost/restored.
My application is very heavy with allot of information, graphs, lists, ... and map.
In the map i'm using webGL in order to get the best performances. My code is handling context lost and restored properly.
I'm starting a big operation that causes loading data from the server, parsing it,... This sometimes making the browser loose my webgl context. The problem is that the context is never restored. When I do again this big operation, then i got the restore event.
In my opinion it is related to memory and the garbage collector freeing time.
But I don't really know what to do, and how to solve this.

An approach to handling the lost could be to recreate the canvas and re-initialize your application for the GL parts. In the end, all resources are gone, so the added overhead for context re-creation should not be too troubling and you can take action immediately when the webglcontextlost event arrived.
(not sure if that's the best idea though...)
Commenting on the Answer by Raziza regarding WEBGL_lose_context:
Don't use this one like you proposed there. This extension is merely a debugging tool and should only be used to simulate this behavior.
See also here: https://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/

Found a way to call restore context manually. Don't know if it is good/smart to do, but it is working for me.
We do it by using the extension WEBGL_lose_context.
MDN reference
// Loading the extension
var ext = gl.getExtension("WEBGL_lose_context");
...
// This code in the context lost event, wait 3 secs for forcing
// restore context
var restoreTimeout = setTimeout(function() {
ext.restoreContext();
}, 3000);
...
// This code in restore context event
// incase we got restore not from my timeout, i'm canceling it
restoreTimeout && clearTimeout(restoreTimeout);

Related

JavaScript clean memory

I have a problem about memory management.
My simpliest code is here:
var url="/abrapo.php";
var ob={start_:100, token:null}
function post_token(){
$.post(url,{access:ob.token})
.done(function(data){
console.log(data);
ob=data;
});
}
I call function post_token every seconds. So after 2000 call user has problem of memory, ram goes up to 2GB. I don't need to save anything just want to log data after post and clear memory. I've already googled and find delete ob. But it does not clean the memory. What increase memory and how can I clean it without reloading the page
Use your browser's profiling tools to determine where you're accumulating memory. In Chrome these profiling tools are located under the Performance tab in the Chrome Developer Tools F12.
Click the Memory checkbox near the top to enable memory profiling
Click Start Profiling and Reload Page (Ctrl+Shift+E)
Let the profiling run for a while, most pages load in 2-3 seconds but it sounds like your page needs to run longer than that
Click the Stop button to halt the profiling
Among all the other performance graphs, you should see one for memory usage that looks something like this.
You can use this to see if, and when, the browser is performing garbage collections on the Javascript heap. You may need to manually clear certain objects by setting them to null. Also, try to avoid cyclical references and other complex referencing patterns that could cause the javascript engine to hold on to objects longer than it has to.
Click here, for more about the memory management and garbage collection in the browser.
I had similar problems while writing UI for a data acquisition device and managed to make it fly by setting every variable containing large data arrays to null whenever not used.
Your use case isn't easy to replicate with just your code, but I suggest you try setting
data = null;
and
ob = null;
whenever not in use.
You might have to tweak suggestion a bit, say by assigning only token:
ob.token = data.token;
in such case only token would have to be set to null
ob.token = null;
What this achieves essentially is that it gives garbage collector a chance to clear unused objects since variables using those were clearly set to null. Oh, yes, and memory profiling is your friend to find out what exactly should you null
According to your code example, the problem is with console.log(data)
it make your object accessible from Console. The Garbage collection will free memory only when the object is no more accessible.

debugging webgl in chrome

I have a webgl page running in chrome.
Every now and then chrome will report the following error.
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to render with no buffer attached to enabled attribute 1
I've tried to debug where the error is occurring but I cannot. I can reliably cause it to occur, but when I debug the error is reported on seemingly random lines. I suspect this is because of the asynchronous nature of gpu rendering.
Is there a good way to debug this?
You can use a debug wrapper to wrap the WebGL context and call gl.getError after every WebGL function.
There is an example of one available on the official WebGL Wiki.
Per default WebGL doesn't tell you much about it, you have to query all the information you need yourself. Once you know how to do that, those errors will tell you all you need to debug it. The getter for your case would be
var attribLocation = 1;
gl.getVertexAttrib ( attribLocation, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING );
Which, if you query it before your draw call, will probably return null, which means you're not calling vertexAttribPointer correctly when setting up or switching buffers.
So you go to the point in your code where you set the pointers and enable the arrays and confirm that the location you just enabled with enableVertexAttribArray returns also returns null if you query the buffer at this point. Now you know if you messed up with the pointer. You know you fixed it, when the query returns the correct WebGLBuffer Object.
There are getters for all the states (WebGL is mostly about managing state), they are a bit tricky to use, but using them will greatly help you understand everything going on all the time, when you need or don't need to make calls in order to update that state and where you made mistakes.
You can look the getters and the arguments they take up in the spec
SpectorJS is a tool aimed at WebGl developers wanting to know what happens in their context. It enables capturing of all the available information from a frame. You will be able to look at your entire commands list with their associated visual states and context information.
https://github.com/BabylonJS/Spector.js

How can I clone a <browser> element in Firefox using XUL?

I am developing a firefox extension where I need to save the state of an arbitrary web page in order to be able to restore that webpage later. The quirk is that I need to restore the entire state of the page, including the state of all javascript variables. The "saving" can be done in memory, it doesn't need to be serializable.
So, is there a way to exactly clone a browser element, so that it starts running from the same point of execution that the original is currently at?
If not, how much effort would it require to add this to firefox (using C++), and which files and documentation would I start looking at?
No, there isn't a way to do exactly what you want. Even the built-in session restore will only restore form fields (and some other selected things), but not the full JS and native object state.
Implementing something like this yourself not feasible (and would be also a massive task):
You could uneval() most js objects, but that will loose type information and you'll only get the source, but not any internal state (think "hidden" state via closures). Native objects like window or document need some special treatment, and getting the internal state isn't exactly always possible here without some C++-level "reflection".
You could potentially get a lot of the actual state using the debugger API in new ways, however I don't see any way to actually restore it later. And "a lot" is still not the same as "all".
About the closed-over "hidden" state:
There is no way I know of to reliably get the internal state of counter in the following example, let alone restore it later, without getting as low-level as a platform-dependent full memory dump.
var count = (function() {
var counter = 0;
return function() { return ++counter; };
})();
count();
count();
I guess that you could walk the properties of all objects and save them somewhere but preserving context of e.g. bound functions would be difficult. Maybe you could make some use of the session store?
See:
Session_store_API and nsISessionStore

Can variables in JS function closures be accessed in any way (including devtools)? How?

In my previous question:
Securing javascript game timing
... it became clear that client-side timing in a Javascript/Canvas game simply won't be secure. I know the mantra about not trusting the client - that is what is causing my struggle in the first place. :-)
So, if I do move all timing to the server and just deal with it, here is a follow-up question. The game obviously needs to be completed before submitting it. As the game puzzle is all Javascript, this introduces the problem of manipulating the client-side code to fake the completion of the game.
I've created the game JS code in a separate class file. If I instantiate the game as such:
var game;
$document.ready(function(){
game = new Game();
});
... then, I can access the 'game' object and all of its methods and variables via the console.
However, if I do:
$document.ready(function(){
var game = new Game();
});
... then I cannot access the 'game' object through the console. This seems to help, but is there something I don't know - can this object still be accessed in some way I don't know about or is making it a private var in that function a little more secure?
Thanks!
Note: there are many other security considerations and attack vectors in such a system. This answer just seeks to answer the specific question that was asked here.
It depends on the browser and what its devtools provide. Most browsers' devtools provide functionality to:
pause execution of JavaScript at any point in time and use a debugger interface.
variables that are in-scope at the current point of execution where the debugger is paused can usually be accessed via devtools in various ways. Inparticular, via console, where anything one can do with that variable in the console is fair game: query its fields, call its methods, etc. If the variable binding isn't const, one can even reassign the variable to a new user-created instance of the object.
navigate JS files and set breakpoints in them.
this is a vector to the above bullet point.
you can make this less attractive by using JS minification (ie. obfuscation), but that's not going to stop someone who's determined.
String literals don't get minified and can usually help a lot in navigating and understanding minified code.
inspect event listeners on HTML elements and set breakpoints on them.
If a variable has a reference bound to it in a function closure that is known to be an event listener of a certain HTML element, or reachable (execution-wise) by such an event listener, this can be another vector to the first bullet point. This can be very common in web games. Just a keyboard event listener usually is an entry-point to reach functions that reference important game objects.
There are even tools to record the JS heap memory. It's a lot of data to sift through, but it's basically everything on the JS heap (readonly).
Given those browser features (and the fact that a user can use any browser they wish), it's impossible to "safeguard" anything 100% on the client-side. It's a losing battle. If you want to play it like a game, you can do your best.
Look into Object.freeze and friends.
freeze or seal anything that can be frozen or sealed, including class prototypes
make variables which can be const const
use assertions to assert in critical parts of the logic that the program state is consistent and try to detect tampering.
Don't care too much about the console. Yes, if there are global objects whose method can easily be fired to "win" the game, it's a nice possibility to cheat, but it can easily prevented as you demonstrated.
So, the hacker would just listen (look at the network pane) which requests are made to your server and fire them manually. If they were just some simple urls like /action=start and /action=end, he could very easily fire them manually without any timing. So you will need to prevent that (although you never can really make it safe), e.g. by adding additional credential tokens. Or you could embed some "secret"(s) into the game code, which are revealed during the gameplay, and need to be sent to the server to prove the rightfulness. Of course they could be read out of your code, but you have to make it too complicated for the hacker. It's a bit like security by obscurity…

“Recursive” timeouts in AJAX callbacks fill up memory. How can I avoid this?

I am working on a dashboard project where multiple widgets (like a dozen) need to be updated via an AJAX source every 5 seconds or so. I am currently using setTimeout to queue a widget update, which is called everytime the widget is actually updated (not technically a recursion, but…). This is how the code looks
var update;
(update = function() {
$.get(source, function() {
// Do something
setTimeout(update, 5000);
});
})();
After a few hours of the page running (Chromium 21), it can easily OOM my 8GB RAM.
As the client uses IE6 on very small configurations (< 1GB RAM), the issue is even more important.
How could I avoid this quirk?
Ok, thanks freakish & Pointy, the leak was indeed caused by jqPlot. Thing is, you have to use the .destroy() method on said plot, and then remove (and not empty) its DOM container, before creating another one and redrawing a plot.
Use setInterval instead. That way you only generate one timer and don't need to start a new one every five seconds, which might consume some sort of handle in the browser.
I actually wouldn't have thought setTimeout to leak, but there is a clearTimeout function. Just for researching purposes you could try saving the returnvalue of setTimeout and clearing it, before starting the next one.

Categories

Resources