Is there a JavaScript console limit in WebKit? - javascript

I want to limit the memory or the number of entries in the JavaScript / Web Inspector console.
Is it already limited somehow (except by available and accessible memory)?
If not, is it possible to just clear out the oldest entries in the console log while retaining newer ones, i.e. something like console.clear(10000)?
Is there anything like a limit or a selective clear() in any JavaScript engine?
The issue is that I want to log debug information in a single-page app in an embedded web view but do not want to constantly leak memory this way.

While some JavaScript developer tools might implement an internal limit, WebKit's Web Inspector apparently does not, at least it does not expose any documented interface to it.
So basically there are two feasible solutions (besides patching WebKit or using a tool that supports a limit), as Cerbrus and Jan Dvorak have also mentioned.
Create a proxy to the various console methods to buffer any log output and dump on request only, and limit the internal buffer.
A simple ring buffer is not very fast, so an alternative would be to use two buffers where the older one is discarded and overwritten when the current becomes full.
The drawback of using a buffer is that you cannot immediately expand objects but only on first access, which may lose vital debug data if they get overwritten (Qt 5's console expands simple objects and arrays during logging).
Periodically clear the console to limit memory usage.
However, the console may be cleared at the wrong time.

Related

Why does Chrome retain an anonymous MediaRecorder object in memory?

After trying to understand why some of my Web application's objects were retained in memory by Chrome I think I may have narrowed it down to a case of a MediaRecorder object not being garbage collected even with the application having let go of all the references to it (whether explicit or "implicit").
A minimal example that reproduces the issue:
new MediaRecorder(new MediaStream())
After evaluating the above expression -- a MediaRecorder object being created with no references (variables or properties) to it being assigned, I profiled the heap usage using the Memory tab in both Chrome, Electron and Chromium -- the object remains on the heap for as long as I cared to find it there. It doesn't disappear.
Why is it retained? Testing with a trivial class like Object instead -- evaluating new Object(), for example, behaves as expected -- garbage collection eventually collects the anonymous object. But not so with MediaRecorder. This smells an awful lot like a bug to me.
Firefox, by comparison, releases the MediaRecorder object in due time (it's garbage collected), it is certainly no longer on the heap mere seconds after I execute new MediaRecorder(new MediaStream()).
The media recorder object is obviously not referenced by anything in the application and should thus have the shortest lifetime an object may ever have, yet it is there in memory afterwards in the snapshot I take after the console is cleared (the developers behind Developer Tools for Chrome recommend clearing the console before taking a heap snapshot because the former may hold on to objects that otherwise would be released).
I can't find any methods in the MediaRecorder class that would indicate to me one can "disassociate" it from a stream or otherwise "close" it. Short of making sure there are no obvious or not-so-obvious (e.g. through event listeners) references to it, I can only hope that an anonymous object isn't retained, and such objects usually aren't, but MediaRecorder objects seem to be with Chromium. There doesn't seem to be any lever for me to pull to dispose of one, so to speak.
You can see in the screenshot below that what objects retain the media recorder aren't exactly part of my scripts, they rather seem to be related to some internal browser state:
The window icon next to the object selected in the "Constructor" column has the tooltip "User object [is] reachable from window". The snippet above is the only code I run in the tab, why would the object be "reachable from window", and if it is, it surely cannot be any references I manage?
So why is the object retained? The larger problem here is that if my application initiates many recordings and creates a new media recorder object for each, these objects will just keep piling up in memory, a de-facto case of memory leaking.
Like I said, I ran the same statement in Firefox 62.0.2 and there the behaviour is as I would expect -- the single MediaRecorder object I created seems to go out of scope (as it should being how it should have no references to it) shortly after it is created.
(Chrome version 69.0.3497.100, x64 on Windows 10)
This was confirmed to be an issue with Chromium (and by implication Google Chrome and probably other Chromium derivatives, including Electron):
https://bugs.chromium.org/p/chromium/issues/detail?id=899722
At the time of writing this the issue is flagged as "available", which I presume communicates that it's acknowledged and effectively waiting for someone to step in and fix.
According to the specification:
A MediaStream object is said to be active when it has at least one MediaStreamTrack that has not ended. A MediaStream that does not have any tracks or only has tracks that are ended is inactive.
When you create a new MediaStream, unless you stop all its tracks, it remains in active state.
So, to unset this object, you need to explicitly get rid of its MediaStreamTrack objects, getting a reference to the stream e.g:
var myRecorder;
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function create_media_recorder(stream) {
myRecorder = new MediaRecorder(stream);
console.clear();
});
var myStream = myRecorder.stream;
myStream.getTracks().forEach(function(el) {
el.stop()
}
after that, you should see the recording icon going away - The media stream is now inactive.
Check these API's for further reference
https://developer.mozilla.org/en-US/docs/Web/API/MediaStream
https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack
Make sure you have "Preserve log upon navigation" unchecked in your browser's settings, otherwise console.clear() does nothing.
https://developer.mozilla.org/en-US/docs/Web/API/Console/clear
EDIT:
Also, I doubt this is a memory leak since unreachable objects are automatically removed. It's more likely MediaRecorder is saving objects to the global scope.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#Garbage_collection
"4.3.1 Life-cycle and Media Flow" should clear things up a bit.
https://www.w3.org/TR/mediacapture-streams/#stream-api

How to find out what's causing my Javascript to crash the browser tab?

I'm making a rather extensive game using Javascript. It is a kind of online game maker that allows players to upload media files and use them to create worlds. Unfortunately, it is rather prone to crashing the browser tab at unpredictable moments. So far, I have found no pattern to this - sometimes it happens within a few minutes, other times it can run for hours without a problem.
I have tried enabling logging in Chrome, but the crashes don't seem to generate an error report in the chrome_debug file.
I thought it might be that the program was using too much memory (given the game's open-ended nature, some worlds can involve downloading rather large data files - though this seems unrelated to when the crash actually happens - while large worlds do seem to be more crash-prone, they do not always crash when the world's data is loaded).
I tried using Electron to turn it into an executable app, but the app still crashes. That shouldn't happen if it's a memory issue, right?
Is there any way of finding out what is causing the code to crash?
Most unpredictable crashes in Javascript are caused by memory leaks - objects that are still stored in memory and not being picked up by the garbage collector. Every object in Javascript is stored in a variable somewhere within the global scope, or is associated with another object that is itself connected to the global scope. When a "branch" of the "tree" is removed and can no longer be accessed by the global scope, the garbage collector destroys it.
However, if an object is not being removed from the global scope when it should be, it remains in memory. This usually happens when objects are added to an array but are not removed from that array when they are no longer in use. Over time, these objects build up until the process crashes due to memory overload.
To find memory leaks in Chrome, press F12 and open the Performance tab. By recording the page over time, you can view the amount of memory being used. The green line (nodes) is the most important here - it refers to the number of objects in memory. If nodes are constantly increasing over time (there will always be increases and decreases, but if the overall level is constantly rising) this generally means there's a memory leak.
To find which specific objects are causing the problem, open the Memory tab to take snapshots or timeline profiles of the memory heap. This gives you a count of the specific objects that are in memory at any given time. If there are more of some kind of object than there should be, that's where the leak is.

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.

Count all objects and variables in use

Is it possible to count created objects and variables in javascript?
I am using Google Chrome to analyse my web app. But to debug and find the objects that causes "Memory Leak" is not so easy (at least for me). So I want to know all objects and variables that are created on the current page so I can know if they are removed.
No, you can't do that in Chrome (or any other major browser). You can use Chrome's "memory" page (chrome://memory/) to get some idea what's going on, but it's not down to the object level, and it's important to understand that garbage collection does not happen synchronously or immediately. The browser / JavaScript engine may well allocate memory, use it for some JavaScript objects, and then later correctly understand that those objects aren't used anymore, but keep the memory handy for future use.
Instead, what you can do is study how JavaScript works in detail, which tells you what will (usually) be kept in memory, and why. Understand how closures work (disclosure: that's a post on my anemic little blog), and understand how IE doesn't handle circular references between DOM elements and JavaScript objects well (specifically, it doesn't clean them up well when nothing refers to either of them anymore, which is otherwise not normally a problem). And in general, don't worry too much about it until/unless you have a specific issue to address. (Which absolutely happens, but not as much as people sometimes think.)

Tool to track down JavaScript memory leak

I have a web application which has a memory leak somewhere and I am unable to detect it. I already tried the Chrome developer tools which normally works great, but I am unable to track down the lines of code which are responsible. The Chrome tools just give me too much information and I can't relate the objects in memory to my code.
Are there any other tools that might be helpful?
update:
Lets use Record Heap Allocations profile type.
open devtools profiler
do a warm-up action
start profiler
repeat action a few times
if the action has a leak you will see the same number of groups of blue bars in the overview pane
stop the profiler
select one group of these blue bars in the overview
look into the list of objects
See screencast Javascript Memory Leak detection (Chrome DevTools)
was:
You can use the next scenario for fining memory leaks.
open devtools profiler
do an action that makes a leak
take a heap snapshot
repeat steps 2 and 3 tree times
select the latest heap snapshot
change filter "All Object" to "Objects between Snapshot 1 and 2"
After that you will see objects a set of leaked objects.
You can select an object and look at the list of retainers in Object's retaining tree
Use the innerHTML and outerHTML values of the element in the Detached DOM tree view of the Heap Profiler to map objects in memory to your code and track down memory leaks.
jQuery ajax requests were the biggest culprit in my app. Locate all your ajax jQuery functions: .ajax(), .get(), .post() and content setters: .html(), .text().
Go to the network tab in dev tools, refresh the current page 10 to 20 times. If you see things stacking up too frequently, or calls not being completed, you have a memory leak.
Here is a recent memory leak I was able to solve with jQuery.load()...
if(!jQuery.terms_html)
$('#tc_container').load(STATIC_DOMAIN + '/terms.html', function() { jQuery.terms_html = $('#tc_container').html() })
else
$('#tc_container').html(jQuery.terms_html)
Also, the latest version of jQuery at time of writing this is 3.3.1. Having the latest version installed is the best way to get started, if possible.
https://github.com/jquery/jquery/releases

Categories

Resources