I have a timer function that creates a large amount of data, declared with var. Why does the object not get garbage-collected? The number shown by usedJSHeapSize keeps growing. Task Manager in Chrome also shows memory increasing.
I'm testing this in Windows 10, Chrome, using VS 2017.
If I copy and paste the code into a separate file called test.html and open that in Chrome, it also shows the leak.
I've tested this code in Edge and IE (using Developer Tools instead of usedJSHeapSize) and I see no memory leak.
Is this an issue with Chrome?
<script type="text/javascript">
function refreshTimer() {
try {
var longStr = new Array(1000000).join('*');
document.getElementById('div1').textContent = 'usedJSHeapSize: ' + window.performance.memory.usedJSHeapSize;
}
catch (err) {
document.getElementById('div1').textContent = 'refreshTimer: ' + err;
}
}
window.setInterval("refreshTimer()", 3*1000);
</script>
<div id="div1" style="font-family:Calibri"></div>
I expect that there would be no memory leak because the large data object is declared with var and should be garbage-collected when it leaves scope.
Edit to my my original post:
I have run Chrome with and without "--enable-precise-memory-info" and it makes no difference. I have observed memory growing in Chrome->More Tools->Task Manager and in Windows Task manager with just one instance of Chrome running with my test.html file.
The only links I can find that mention this as a possible bug in Chrome are these:
Javascript garbage collection of typed arrays in Chrome
https://bugs.chromium.org/p/chromium/issues/detail?id=232415
These are old posts though and I can't believe the bug would live this long.
So - I'm still perplexed.
1/2/2019 - adding a comment to move this question to the top of SO. If anyone knows, please add your thoughts.
You've run into a security issue with Chrome. Chrome does not expose true memory usage via "window.performance.memory". Attackers could use this information to attack the web browser.
Related
This morning, suddenly found that our users are saying app crashes after we had breakpoints found iOS 10 of the iphone, JavaScript & UIWebview interface problem occurs in the injected JSContext object, the proxy method can not be performed, and direct crash to the stack area, cause I can not modify on the line.
EDIT: The following original comment is not helpful. My use of window.webkit.messagehandlers in UIWebView is an unsupported hack (to match the API of WKWebView), so no surprise that broke, and the overflow crash when attaching Safari is reportedly not happening to other devs who are on Safari 10 (I haven't updated yet)
-- Original Comment --
Seeing the same bug on iOS 10, filing to Apple now. Problem #1, adding callbacks to window.webkit.messagehandlers: this object now only allows for a single callback function added, it used to allow multiple, i.e. messagehandlers.doOneThing, messagehandlers.doAnother.
Problem #2, seeing crashes: first an EXC_BREAKPOINT on WTF::CrashOnOverflow::overflowed() then a crash
* thread #10: tid = 0x81c29d, 0x0dfb3d1d JavaScriptCore`JSC::DFG::SpeculativeJIT::speculate(JSC::DFG::Node*, JSC::DFG::Edge) + 1197, name = 'WebThread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
* frame #0: 0x0dfb3d1d JavaScriptCore`JSC::DFG::SpeculativeJIT::speculate(JSC::DFG::Node*, JSC::DFG::Edge) + 1197
All of a sudden, my breakpoints in Chrome stopped working entirely. The weird thing is if I hit an error in the code and break that way, or if I add debugger; anywhere in my code, it does stop, but it opens a different file with a prefix like VM[number].
The file that shows naturally in the development console that breakpoints don't work in is entitled main.js, but when I encounter an error or stop through the debugger command, it opens a new file called "VM113 main.js". The even weirder thing is if I follow the code into a different file, like jquery.js, it also doesn't go into the jquery.js file but into a file called "VM97 jquery.js" or "VM98 jquery-ui.js".
What's going on and how do I get Chrome to look at the actual files rather than VM files?
In my personal research, this is caused by having an accented character in the file path of the file in which I'm attempting to place a breakpoint.
Suppose you have two files, HäagenDazs/main.js and HaagenDazs/main.js (named for the sake of example) and they both contain (roughly) the same thing:
var x = function () {}; and var y = function () {};
If you place a breakpoint in HäagenDazs/main.js, Chrome will delete it and set it in VM-### main.js at the same location. If you place a breakpoint in HaagenDazs/main.js, Chrome keeps it there in the original file.
It seems to be the combination of an accented character anywhere in the path and having the keyword function present in that file. I tested this in OS X 10.10 using Chrome Version 38.0.2125.122.
I completely uninstalled Chrome and reinstalled it and that seemed to fix the issue. I do not know what caused it to start this behavior, but a reinstall solved it.
I've just experienced the same issue and got a solution, so I'll leave it here just for the record.
In my case, it was because that particular website used service workers, and they provided an additional level of JS caching 'ahead' of the local overrides where I had placed my breakpoints.
So the execution always stopped in a [VM] tab that did not contain any of the changes that I had in those overrides.
The solution was to go into the Application menu. There, in the Service Workers section, I checked the 'Offline' and 'Bypass for network' options, then clicked on 'Unregister' on the far right side.
I want to read a file with FileSystemObject. My code is as following:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Read json</title>
</head>
<body>
<script type="text/javascript">
function readFile(filename){
var fso = new ActiveXObject("Scripting.FileSystemObject");
var ForReading = 1;
var f1 = fso.OpenTextFile(filename, ForReading);
var text = f1.ReadAll();
f1.close();
return text;
}
myJSONText = "text.txt";
var myObject = readFile(myJSONText);//eval('(' + myJSONText + ')');
document.write(myObject.name);
</script>
</body>
</html>
First, let me repeat some comments above. I've never seen using ActiveXObject client side extolled as a thing that should be done.
Now, let me say I'm trying to learn how to do this myself. Here are some thoughts (and helpful links, see the bottom) on this question.
The general layout, according to "Much ADO about Text Files" on MSDN's scripting clinic column, is:
Create the object.
Create another object, using the first, that uses
a method of the first object (such as getting a file).
Do things to
the file.
Close the file.
How do you start? According to IE Dev Center (linked here), use an ActiveXObject in Javascript as follows:
newObj = new ActiveXObject(servername.typename[, location])
You've got that when you declare fso in your code. What about this "servername" thing, isn't the file accessed locally? Instead of "servername etc" you've put in Scripting.FileSystemObject. This is actually fine, if the HKEY_CLASSES_ROOT registry key on the host PC supports it (see ref above).
Once the ActiveXObject is successfully declared, and if the browser allows it (IE only), and if the end user agrees to any warnings that pop up ("An ActiveX control on this page might be unsafe to interact with other parts of the page..." etc), then the object allows you to use any of the methods associated with that object. That's where the power of the Windows Scripting FileSystemObject comes into play.
Any FileSystemObject (fso) method is now available to use, which as its name suggests, means file (and directory) interaction on the local machine. Not just reading, as your question is focused on, but writing and deleting as well. A complete list of methods and properties is available at MSDN here. After being used, close out the file using the .close() method.
So, this is dangerous for obvious reasons. But what wasn't obvious to me at first was that these interactions with the filesystem may happen invisibly. There is a good chance that whatever you do, from reading a file to deleting a directory tree, no warnings or command prompts will come up to let you know what's happening because of your few lines of code.
Let me finish by commenting on the last bits of code above. Using JSON in conjunction with data pulled from the FileSystemObject provides a great way to allow JavaScript interaction (JSON .parse and .stringify come immediately to mind). With this, data could be stored locally, perhaps as an alternative to HTML5 local storage (ref this SO thread, which goes more in-depth with this concept, and another SO question I raised about this here).
Here are some links for further reading:
IE Dev Center, JavaScript Objects, ActiveXObject
MSDN JScript Windows Scripting (including FileSystemObject methods, etc)
MSDN Scripting Clinic (older articles, many broken links, but stil a lot of good info on this stuff)
I have recently started to tinker with Project Euler problems and I try to solve them in Javascript. Doing this I tend to produce many endless loops, and now I'm wondering if there is any better way to terminate the script than killing the tab in Firefox or Chrome?
Also, is firebug still considered the "best" debugger (myself I can't see much difference between firebug and web dev tool in safari/chrome ).
Any how have a nice Sunday!
Firebug is still my personal tool of choice.
As for a way of killing your endless loops. Some browsers will prevent this from happening altogether. However, I still prefer just going ctrl + w, but this still closes the tab.
Some of the other alternatives you can look into:
Opera : Dragonfly
Safari / Chrome : Web Inspector
Although, Opera has a nice set of developer tools which I have found pretty useful. (Tools->Advanced->Developer Tools)
If you don't want to put in code to explicitly exit, try using a conditional breakpoint. If you open Firebug's script console and right-click in the gutter next to the code, it will insert a breakpoint and offer you an option to trigger the breakpoint meets some condition. For example, if your code were this:
var intMaxIterations = 10000;
var go = function() {
while(intMaxInterations > 0) {
/*DO SOMETHING*/
intMaxIterations--;
}
};
... you could either wait for all 10,000 iterations of the loop to finish, or you could put a conditional breakpoint somewhere inside the loop and specify the condition intMaxIterations < 9000. This will allow the code inside the loop to run 1000 times (well, actually 1001 times). At that point, if you wish, you can refresh the page.
But once the script goes into an endless loop (either by mistake or design), there's not a lot you can do that I know of to stop it from continuing if you haven't prepared for this. That's usually why when I'm doing anything heavily recursive, I'll place a limit to the number of times a specific block of code can be run. There are lots of ways to do this. If you consider the behaviour to be an actual error, consider throwing it. E.g.
var intMaxIterations = 10000;
var go = function() {
while(true) {
/*DO SOMETHING*/
intMaxIterations--;
if (intMaxIterations < 0) {
throw "Too many iterations. Halting";
}
}
};
Edit:
It just occurred to me that because you are the only person using this script, web workers are the ideal solution.
The basic problem you're seeing is that when JS goes into an endless loop, it blocks the browser, leaving it unresponsive to any events that you would normally use to stop the execution. Web workers are still just as fast, but they leave your browser unburdened and events fire normally. The idea is that you pass off your high-demand tasks (in this case, your Euler problem algorithm) to a web worker JS file, which executes in its own thread and consumes CPU resources only when they are not needed by the main browser. The net result is that your CPU still spikes like it does now, but your browser stays fast and responsive.
It is a bit of a pest setting up a web worker the first time, but in this case you only have to do it once. If your algorithm never returns, just hit a button and kill the worker thread. See Using Web Workers on MDC for more info.
While having Firebug or the webkit debuggers is nice, a browser otherwise seems like overhead for Project Euler stuff. Why not use a runtime like Rhino or V8?
I have almost the same problem as this unanswered question. The only difference is I'm using VS2008, but I'm in an MVC project calling this javascript function:
function CompanyChange(compCtrl) {
alert(compCtrl.value);
debugger;
var test;
for (var i = 0; i < document.all.length; i++) {
test = document.all[i];
}
}
I hit the alert, then I get the message "there is no source code available for the current location." At which point the page becomes unresponsive and I have to manually stop the debugger just to shut it down.
I've logged into another machine and ran this exact code and it works fine, I hit the debugger and can step through. I've checked to make sure all settings in VS>Tools>Options>Debugging are identical as well as IE>Options>Advanced and they are. Both machines are Windows 7 Enterprise edition 32-bit, VS2008, IE8.
I've also tried attaching a process manually in VS, and using the 'Developer Tools' in IE which didn't work (said there already was a process attached).
I was hoping someone may have had this problem and found a work-around because I've already done a lot of searching and tried all the options I've read. Anyone else run into this?
Thank you,
Jeff
I recently answered the original question, so thought I'd post my answer here too:
The debugger cannot debug both Silverlight code and Script code at the same time, if the Silverlight debugger is selected JavaScript debugging is switched off.
To resolve this go to the Project's Properties and select "Start Options". Next check that the Silverlight checkbox is NOT ticked if you want to be able to debug JavaScript. (It is unfortunate that the UI here is not clear about this side effect.)
Even I had the same "Source code not available" msg for ie8. Actually I was having 2 different methods with same names having different parameters in 2 different pages and one of the method which I was invoking was not getting called due to the overloaded method which Ie8 doesn't detect. So I just renamed the function and it resolved the issue