IE+JScript Performance Recommendations Part 3: JavaScript Code Inefficiencies
Hello again, this is Peter Gurevich, Performance PM for IE. We have gotten a lot of good feedback from our first posts on IE + JavaScript Performance Recommendations Part 1 and Part 2, so I am eager to hear what you think of our third installment.
JScript Code Inefficiencies – Chapter 2
Here we’ll be concentrating on specific inefficiencies related to closures and object oriented programming.
Avoid Closures if Possible
Closures (functions that refer to free variables in their lexical context) are both extremely powerful and extremely dangerous. There are certain programming techniques that demand their use and once you learn how to use them they can quickly become one of the most overused features of the JScript language. Currently the misuse of closures in connection with the IE DOM and various COM components are the number one cause of heightened memory usage within IE. Also, while they are useful, this is a performance article and there are not really any scenarios where a closure is going to provide more performance throughput than a bare function or inline code.
Closures are most often used when attaching event handlers. The purpose in this case is to encapsulate some of the scope for the currently running function into a brand new function that can later be used when the event handler is invoked. The trouble with this approach is that circular references between the scoped variables and the closure are nearly invisible to the eye. The extra memory pressure of leaving these objects around means extra garbage collection pressure, possibly extra work for IE, or more bookkeeping for other hosts. APIs for handling the retrieval of remote data are useful as an example.
function startDownload(url)
{
var source = new ActiveXObject(“Ficitious.UrlFetcher”);
source.ondataready = new function() { source.ondataready = null; }
source.startRequest(url);
}
The above example is pretty basic. The script doesn't do any real work, but sets up a mock scenario of a closure. What happens when the ondataready event never fires? We expect it to, but it might not. If it doesn't fire, the closure in this case has a reference to the source object and the source object back to the closure. This is an implicit circular reference, hard to spot, and IE leaks memory. This is never good for performance. Furthermore, every time the startDownload function is called, it means allocating a new object to store all of this state. Rewriting the sample to not use closures is very specific to your application. If you only allow a single instance of the object to exist, then you could take advantage of a global singleton. If you allow multiple requests, then a pooling mechanism is probably more appropriate along with a method for dispatching and handling all incoming requests even if a particular request is signaling it is ready. For additional information on closures, please see the Closures section in Understanding and Solving Internet Explorer Leak Patterns.
Don’t use Property Accessor Functions
A common technique in object oriented programming is to use property accessor functions. An example would be in the form of [get/set]_PropertyName (or many others depending on the style). The basic premise is a local member variable for some class followed by two methods for either retrieving or setting the property. These methods are often used for controlling member visibility, but in JScript everything is visible. Further, most object oriented languages optimize the property methods away to direct variable access during compilation, not so with interpreted JScript. A quick attempt at coding a simple Car object might produce code with property accessors:
function Car()
{
this.m_tireSize = 17;
this.m_maxSpeed = 250; // One can always dream!
this.GetTireSize = Car_get_tireSize;
this.SetTireSize = Car_put_tireSize;
}
function Car_get_tireSize()
{
return this.m_tireSize;
}
function Car_put_tireSize(value)
{
this.m_tireSize = value;
}
var ooCar = new Car();
var iTireSize = ooCar.GetTireSize();
ooCar.SetTireSize(iTireSize + 1); // An upgrade
The above is pretty good object oriented but terrible JScript. The extra indirection in accessing our local members is really hurting the performance of the application. Unless we need to do validation of the incoming values, the code should never add extra indirection and should be as precise as possible. Rewriting the above is an exercise in removing as much extra code as possible.
function Car()
{
this.m_tireSize = 17;
this.m_maxSpeed = 250; // One can always dream!
}
var perfCar = new Car();
var iTireSize = perfCar.m_tireSize;
perfCar.m_tireSize = iTireSize + 1; // An upgrade
We’ve removed two extra expando properties on the object, a couple of functions, some extra work while retrieving and setting our properties, and a few name binds. In short, try to stay away from any extra indirection.
For a more complete sample, we can also add prototypes. Note that prototypes will actually be slower, since the instance will be searched first, then the prototype, and so functional look-ups occur more slowly. This will make our naïve sample slower for sure. If you are creating thousands of instances of the class, the prototypes start to become more efficient. They start by reducing the size of each object since extra properties are not added per instance that point to the same global functions. Further, object instantiation can be much faster since the extra property assignments are not needed to set up all of the functions. For completeness, here is a full sample. As an extra challenge, try to find scenarios where the prototype car wins over the slow car.
<script>
// Slow Car definition
function SlowCar()
{
this.m_tireSize = 17;
this.m_maxSpeed = 250; // One can always dream!
this.GetTireSize = SlowCar_get_tireSize;
this.SetTireSize = SlowCar_put_tireSize;
}
function SlowCar_get_tireSize()
{
return this.m_tireSize;
}
function SlowCar_put_tireSize(value)
{
this.m_tireSize = value;
}
</script>
<script>
// Faster Car, no more property accessors
function FasterCar()
{
this.m_tireSize = 17;
this.m_maxSpeed = 250; // One can always dream!
}
</script>
<script>
// Prototype Car, use the language features!
function PrototypeCar()
{
this.m_tireSize = 17;
this.m_maxSpeed = 250; // One can always dream!
}
PrototypeCar.prototype.GetTireSize = function() { return this.m_tireSize; };
PrototypeCar.prototype.SetTireSize = function(value) { this.m_tireSize = value; };
</script>
<script>
function TestDrive()
{
var slowCar = new SlowCar(); // Safe and reliable, probably not fast
var fasterCar = new FasterCar(); // Lacks air-bags, probably faster
var protoCar = new PrototypeCar(); // Can technology win the day?
var start = (new Date()).getTime();
for(var i = 0; i < 100000; i++) { slowCar.SetTireSize(slowCar.GetTireSize() + 1); }
var end = (new Date()).getTime();
output.innerHTML += "Slow Car " + (end - start) + "<br>";
start = (new Date()).getTime();
for(var i = 0; i < 100000; i++) { fasterCar.m_tireSize += 1; }
end = (new Date()).getTime();
output.innerHTML += "Faster Car " + (end - start) + "<br>";
start = (new Date()).getTime();
for(var i = 0; i < 100000; i++) { protoCar.SetTireSize(protoCar.GetTireSize() + 1); }
end = (new Date()).getTime();
output.innerHTML += "Prototype Car " + (end - start) + "<br>";
}
</script>
<button onclick="TestDrive();">Test Drive Cars!</button>
<div id="output"></div>
That’s all for Part 3.
Thanks,
Peter Gurevich
Program Manager
Justin Rogers
Software Development Engineer
Comments
Anonymous
January 04, 2007
Is this really helping? I mean, most of the recommendations require drastic changes of code which makes it less readable. Sure, it may be faster, but the gains come at a steep price. Instead, I'd love to see tips on how to make IE render faster [1], or how to prevent it from slowing down if there's a big application running for a longer time. These issues are causing the problems for developers, not function lookup. [1]: Actually, one way to do this is by giving elements with a lot of descendants layout.Anonymous
January 04, 2007
@Mark: Without data from a profiler to back you up, it's not clear why you think these tips aren't the best place to start optimizing. As for making the code unreadable, that's a matter of opinion, but it's hard to believe that the suggested code is any less readable. As for how "drastic" the changes are, it entirely depends. As with any perf optimization exercise, you should look for the bottlenecks (e.g. tight loops) and optimize those first.Anonymous
January 04, 2007
Hungarian variable notation is sooooo 1990! ugh!Anonymous
January 04, 2007
Woah!... is the final example supposed to be the "good" one? If so, it bombed horribly... performance in IE7 is 4x worse that Firefox... Ouch!Anonymous
January 04, 2007
The benchmark given shows a significant difference indeed (even in Opera!) However if all 300000 loops take 1-2 seconds, is there any practical use in this? Does anyone write scripts that are this heavy (and where bottleneck is not in network, DOM or rendering speed?)Anonymous
January 04, 2007
I'm not agree with Mark, it's just an habit. I use this syntax since many month and it's great. For property I use getter and setter only if I need to make another action or if the property is public, if the property is internal I'll use the direct access because there is no function call thus it's a lot faster.Anonymous
January 04, 2007
The comment has been removedAnonymous
January 04, 2007
The comment has been removedAnonymous
January 04, 2007
function startDownload(url) { var source = new ActiveXObject("Ficitious.UrlFetcher"); source.ondataready = function() { this.ondataready = null }; source.startRequest(url); }Anonymous
January 04, 2007
The comment has been removedAnonymous
January 04, 2007
function PrototypeCar(){}; PrototypeCar.prototype = { mTireSize: 17, mMaxSpeed: 250, // One can always dream! getTireSize: function() { return this.mTireSize; }, setTireSize: function(value) { return this.mTireSize = value; } }Anonymous
January 04, 2007
Dao: "source.ondataready = function() { this.ondataready = null };" 'this' here will most likely be a reference to the global namespace and not to your object instance As for your last post with the PrototypeCar object; that's merely a different notation for creating the same kind of object so it doesn't matter in performance at all...Anonymous
January 04, 2007
The comment has been removedAnonymous
January 04, 2007
> "source.ondataready = function() { this.ondataready = null };" > 'this' here will most likely be a reference to the global namespace and not to your object instance Not if you have a decent implementation of ECMAScript. But then again we're talking about JScript + badly integrated ActiveX objects, so you could be right ... > As for your last post with the PrototypeCar object; that's merely a different notation for creating the same kind of object so it doesn't matter in performance at all... I know, but it's actually readable code. It doesn't have to be ugly just because performance is our topic.Anonymous
January 04, 2007
Washington Post shows some scary stats for IE6 in 2006. http://blog.washingtonpost.com/securityfix/2007/01/internet_explorer_unsafe_for_2.html Does Microsoft expect that IE7 in 2007 will show a much better report card?Anonymous
January 04, 2007
"Not if you have a decent implementation of ECMAScript. But then again we're talking about JScript + badly integrated ActiveX objects, so you could be right ..." That totally depends on the implementation of those event-handlers within (in this case) the ActiveX object. In case of f.i. the onreadystatechange handler of an XMLHttpRequest object 'this' will refer to the function instance of the handler itself and not to the XMLHttpRequest instance object. Those things are simply beyond the ECMAScript scope... And to what is 'readable' or 'ugly' is basically a matter of taste. Mind that when you want to dynamically extend an object's prototyped methods you'd still need to use "object.prototype.method = "Anonymous
January 04, 2007
The comment has been removedAnonymous
January 04, 2007
The comment has been removedAnonymous
January 04, 2007
> That totally depends on the implementation of those event-handlers within (in this case) the ActiveX object. In the first place it's a property called "ondataready" of the type "function". That's well defined by ECMAScript. > In case of f.i. the onreadystatechange handler of an XMLHttpRequest object 'this' will refer to the function instance of the handler itself and not to the XMLHttpRequest instance object. I guess you mean IE7's XMLHttpRequest, which of course is a wrapper for the ActiveX object. For every other browser, that behaviour would be considered a bug (or "compatibility with IE", but I doubt they do that).Anonymous
January 04, 2007
> And to what is 'readable' or 'ugly' is basically a matter of taste. Mind that when you want to dynamically extend an object's prototyped methods you'd still need to use "object.prototype.method = " Well, find me someone who prefers the structure of the initial code to mine. Mind that it wasn't an extending scenario.Anonymous
January 04, 2007
Oops, my question was addressed to Peter, not 'Dave' (long day). Also, it would be helpful if MS wrote more about their plans to address fundamental technical problems in IE (e.g. layout engine and Javascript implementation).Anonymous
January 04, 2007
goose, ehere are you? This entry really need your comment!Anonymous
January 04, 2007
" If IE's implementation of things like XMLHTTP was truly native, it would be garbage-collected properly" It depends what you mean by "native". When discussing Windows (of which IE is part), "native" refers to C++/COM code, as opposed to scripting or managed code. I assume you mean native JScript/JavaScript/ECMAScript. But why should this be the native language of the browser? Should XMLHTTPRequest also have all language properties for VBScript, Perl, or any other pluggable scripting engine?Anonymous
January 04, 2007
Justin and Peter, Can you give us more info on changes in IE7 memory management? It appears that IE7 has made a big improvement in collecting circular references. We certainly appreciate that. I was wondering if IE7 still uses the terrible 100 slot/10,100 array slot addition criteria for triggering garbage collection that leads to O(n^2) GC over progressive object growth, or if the GC triggering algorithm has been improved. I am pretty sure it is possible to acheive O(n) by simply making the threshold proportional to the current number of objects or memory or something... Maybe that has been done in IE7?Anonymous
January 04, 2007
> I assume you mean native JScript/JavaScript/ECMAScript. But why should this be the native language of the browser? Nobody says so. It's just that C++ (or whatever) code needs to be glued properly with the scripting layer. All other browsers get this without being written in JavaScript. E.g. Firefox with XPConnect: >>> XMLHttpRequest.prototype.setRequestHeader function setRequestHeader() { [native code] } > Should XMLHTTPRequest also have all language properties for VBScript, Perl, or any other pluggable scripting engine? Yes.Anonymous
January 04, 2007
Dao: "In the first place it's a property called "ondataready" of the type "function". That's well defined by ECMAScript." sure, but the code that actually uses this property (fires is as an event for instance) that can determine in which scope it is executed. e.g. in javascript you can use call() or apply() to determine in which scope it is executed. "I guess you mean IE7's XMLHttpRequest, which of course is a wrapper for the ActiveX object. For every other browser, that behaviour would be considered a bug (or "compatibility with IE", but I doubt they do that)." Well, I actually checked this in Firefox :P My point being: ECMAScript doesn't define the scope some function is executed in, the application itself does. Although it seems logical that 'this' within some object method would refer to the object instance this is not necessarily true. "Well, find me someone who prefers the structure of the initial code to mine. Mind that it wasn't an extending scenario." I do prefer the object-notation actually, but I don't think the alternative is 'ugly', only 'less nice' ;)Anonymous
January 04, 2007
> but the code that actually uses this property (fires is as an event for instance) ... It would actually work as expected if it was an event :) (as defined by the W3C XMLHttpRequest spec, btw.) As far as I remember, it isn't, i.e. you can't do xhr.attachEvent('onreadystatechange'...). > ... that can determine in which scope it is executed. e.g. in javascript you can use call() or apply() to determine in which scope it is executed. Absolutely. It's up to the implementation to do the right thing (which in this case isn't defined by ECMAScript, yes). You can break any method with "var x = this.method; x()" or "(this.method)()". But I think it's obvious that only applying it to the object itself makes sense. That's also why I didn't expect Firefox to follow the IE nonsense: I guess nobody uses "this" in onreadystatechange, because it's really worthless -- hence there's no script that Firefox could have broken, if it called the method differently.Anonymous
January 05, 2007
Peter Gurevich and Justin Rogers wrote an excellent on JScript performance in IE. This is the simplest,...Anonymous
January 05, 2007
Great article. You've really concentrated on the bottle necks like the time it takes to invoke a function and the time it takes to walk the prototype chain. Articles like this leads to more misunderstanding and bad coding practices.Anonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
Closures don't cause memory leaks. Browsers that have garbage collection bugs (IE6) and continue to retain those bugs in new versions (IE7) cause memory leaks. Closures are an extremely powerful and useful programming technique. It's unfortunate that you would recommend against their use simply because your browser has a bug that causes a memory leak. A huge amount of time has been spent by the js community to detect, resolve, and work around these IE memory leaks. It's too bad this was required, and will continue to be required as long as MS refuses to fix the problem. Hopefully IE's market share will continue to drop and we can begin to ignore these memory leaks because every other browser out there handles closures just fine.Anonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
Peter, While I can't argue with some of what you wrote, it suffers from one major problem. Its absolutely wrong and lacks any value what so ever. I agree totally with Matt Kruse. But let's look at what is being asserted in this article. First, the use of closures is not, as many have already suggested, a the sources of the problem. In fact, closures are one of the most useful techniques that are a available to a JavaScript programmer. Closures are exceedingly powerful. If you were to read Doug Crockford (cf. http://javascript.crockford.com/private.html and http://video.yahoo.com/?t=t&p=douglascrockford) you would quickly see that closures are indispensible. The problem is not with closures, but with using closures poorly and without considering the consequences of your code. So if you want to improve your JavaScript code efficiency, then learn to use the language properly. In the second case, you suggest that the ues of setters and getters is a bad thing, and that we should refer to the bare members directly. But this is not necessarily true, or at least the second part isn't necessarily true. Regardless of the language, having setters and getters that do nothing but set and get private variables should be a huge code stench. Generally we should be exposing behaviour NOT hiding data. So don't write code that does myCar.setTireSize(myCar.getTireSize() + 1 ) or even myCare.tireSize ++ or which ever variation. Assuming its meaningful, you want something like myCar.incrementTireSize( 1 ). In reality, writing good code is more efficient than trying to work around browser problems. The root of all evils is optimizing too soon.Anonymous
January 05, 2007
For gods sake ppl, please fix your garbage collectors! It is a BIG trouble coding in IE!Anonymous
January 05, 2007
>The problem is not with closures, but with >using closures poorly and without >considering the consequences of your code. There's no such thing as "using closures poorly" with regards to this suggestion. Regardless of how they are used, they should not result in a memory leak. The only reason a person needs to "consider the consequences" of using closures is because IE's garbage collection can't break the circular reference between COM objects and javascript. It's a fundamental flaw that has nothing to do with closures and everything to do with a broken garbage collector. In fact, the scenario can easily be created without closures. It just happens that closures are convenient and extremely useful and they often end up exposing this flaw in IE. So of course, the easiest solution is to tell people not to expose the flaw! The really depressing thing is that MS acknowledged the bug years ago and actually actively decided not to fix it. Instead, we get "tips" like "avoid closures" that are really just thinly-disguised attempts by MS to CYA. Saying "avoid closures" is like saying "avoid using typeof". It's a core feature of the language, and the only reason someone would recommend avoiding it is because their implementation of the feature is flawed. IMO.Anonymous
January 05, 2007
Just how difficult is it to write the <script> Element right? It must have a type-attribute including text/javascript. <script type="text/javascript">[...]</script> I'm sorry, but this is such a fundamental thing to know. I though you are good programmers. Why are you so far away from simple basics?Anonymous
January 05, 2007
> It must have a type-attribute including text/javascript. application/javascript actually :) Of course IE doesn't recognize that.Anonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
The comment has been removedAnonymous
January 05, 2007
> If you write text/javascript it's ok. The server is to send the right Type. And that way IE recognises app/js or any of the newser ones. Doesn't it just ignore the header then?Anonymous
January 05, 2007
Anne, Very well said, I was wondering if anyone would point out the obvious incompatibility between GC and reference counting. To expect Microsoft to re-write XMLHttpRequest as a native JS object just to appease a few die hard standards dudes (who will never be appeased anyway) is asking a bit much, particularly when they invented the thing in the first place. At a basic level ActiveX and COM are one and the same. I'd just thought I'd drop that in because ActiveX has become such a dirty word and people often seem to confuse the two. It's a pity the comments to the often excellent entries in this blog can't be more constructive, instead of attempting to find fault in everything that is said. We might all learn a lot more. The MS IE engineers deserve more respect than this.Anonymous
January 05, 2007
> To expect Microsoft to re-write XMLHttpRequest as a native JS object just to appease a few die hard standards dudes (who will never be appeased anyway) is asking a bit much Funny enough, it was this blog entry that pointed to the flaw in source.ondataready = new function() { source.ondataready = null; }: "This is an implicit circular reference, hard to spot, and IE leaks memory." Wouldn't be a problem if you could use "this" inside of the method. And no, I don't want MS to rewrite just XMLHttpRequest. I want MS to fix the underlying architectural flaws.Anonymous
January 05, 2007
Anne I think you need to get a sense of humor, the internet is community based if people want to bash microsoft now and again so what. Most people see through the sarcasm and ironies commonly posted. Usually when someone posts an inaccurate comment it is quickly corrected by other users. At the same time serious issues are raised which can only lead to a better internet explorer. Keep up the good work everyone.Anonymous
January 05, 2007
i still cannot open outlook express and pls send me detailed instructions, thanks.Anonymous
January 06, 2007
Anne, I think that much of the frustration in the comments is not really directed at Peter but rather at the feeling that the IE team is addressing the symptoms (closures are problematic in IE) rather than the root causes of the problems (IE has serious technical issues w/ memory management). There's a lot of bad will towards Microsoft because of the hiatus they took from major enhancements to the browser in the years between IE 6 and IE 7. I think what would really help community feelings towards Microsoft would be for posts like this to:
- acknowledge immediately offers advice geared towards IE problems, and not programming language problems (i.e. closures aren't bad, but closures are dangerous in IE)
- point to a detailed technical roadmap where the IE team lays out (IN DETAIL) how they'll be addressing the underlying technical problems in the next IE release We can assume that the IE team takes these underlying problems seriously, but until we see detailed plans published on the web, it's a very bad feeling to see articles on how to workaround problems that have existed for over five years.
Anonymous
January 06, 2007
@Aedrin Actually, yes, they are facts, they are backed up by public stats, none of it is heresay, and yes, you can most certainly compare browser A to browser B. Cold hard facts: 1.) IE6 was vulnerable to open exploits for X days 2.) Firefox was vulnerable to open exploits for Y days X vs. Y (You don't even need to look at the website, to guess the correct answer!) What is scary, is the fact that the numbers are 10 times different. We're not talking about IE6 being exposed for 2 to 3 more days, we're talking about being exposed for over 75% of 2006. Cut that cake anyway you like it.. 25% secure, is NOT secure!Anonymous
January 06, 2007
> Doesn't it just ignore the header then? Yeah. However, as said: JS isn't as strict about the MIME-Type as CSS is. So it is ok, and needed as IE doesn't understand die others. The attribute and the <meta> information are still required. > Anne I think you need to get a sense of humor, the internet is community based if people want to bash microsoft now and again so what. No one want's to bash MS. However, they've done questionable things in the past, other companies did that as well. Last time they were bashing Netscape, now it's IE, next is unknown, but it'll come. I'd like to love MS, however, the past has to be accepted first.Anonymous
January 06, 2007
The comment has been removedAnonymous
January 06, 2007
Dao: you may be interested to know that your remarks about the scope of eventhandlers for javascript extension objects made me to write an article about it: http://therealcrisp.xs4all.nl/blog/2007/01/06/xmlhttprequest-and-the-scope-of-events/ ;)Anonymous
January 08, 2007
@lex "Actually, yes, they are facts, they are backed up by public stats, none of it is heresay, and yes, you can most certainly compare browser A to browser B." Patch Available != Secure Users Like I've pointed out before, FireFox updates are sent out randomly at 1.5-2 month periods. IE updates are sent out at 1 month periods. Conclusion? The only real way to measure how safe each browser was, is to look at the releases of the full updates, not the patch itself. Then again, the whole discussion is silly anyway. As most security issues are in the user, not the browser.Anonymous
January 09, 2007
i still cannot open outlook express and pls send me detailed instructionsAnonymous
January 12, 2007
Well. Probably the article should have been named "Microsoft code inefficiencies"? For more than 5 years of programming JS, I formed an opinion that this "browser" ("MSIE") lacks just the following letters in its name: u,t,d. (Insert them where appropriate.) I don't favor any browser since each has its own bugs, but bugs becoming standards is too much one can take. I hate the case when a programmer has to correct or avoid the bugs of the programming language he uses. It's pretty much the same as driving a car without relying on its brake system. While microsoft will leave its bugs for a programmer to correct, I will continue to blame microsoft.Anonymous
January 12, 2007
If you read this heated page, but only found the blog's post useful ... try watching Douglas Crawford's seminars: "Theory of the DOM", and "Advanced Javascript". [ Douglas Crawford is the Javascript Architect for Yahoo, and quite enjoyable to watch ] http://video.yahoo.com/video/search?p=crockford&x=0&y=0 Asside from the absurd notion to avoid closures... and I do mean absurd. He suggests to use a mature Javascript Library and let them resolve these issues (which cover leaks and performance). Additionally, he mentions that Javascript is a flexible, brilliant language. You can mold it to look and feel like whatever you want, but there's a performance hit in doing so. Do it only if your code truely becomes more readable.Anonymous
January 12, 2007
The comment has been removedAnonymous
January 12, 2007
Maybe rewriting the GC algorithm would prove to be a better solution than trying to convert every JavaScript programmer to the Microsoft way of coding. Just a thought...Anonymous
January 12, 2007
the js engine of IE is slow, and your team never think about rewrite the engine and tell us for these kind of optimizations (e.g. getter/setter) huh? does it make any sense?Anonymous
January 16, 2007
Sorry for the delay in response. First of all let me thank you all for the great back and forth discussion. It is great to see all that passion for Jscript and Jscript performance. I want to answer some of the questions you posed about our future plans and the exact nature of the changes we mad to our garbage collector. First of all, performance (and specifically Jscript performance) is a top priority for our next release and we will be spending a lot of time and effort to provide competitive or superior performance. I cannot provide additional details beyond that but improving performance is solidly on our radar. Now as to the nature of the improvements we made to the garbage collection routine, here are the technical details. The garbage collector is the same general type as before – mark and sweep. Improvements have been made on the algorithm for determining when a garbage collection (GC) is triggered. The allocator keeps track of three classes of items: variables, array slots, and bytes of string space allocated through OLE Automation’s SysAlloc*String APIs. We call these triggers. In the old allocator: we do a GC on the next statement after any one of the following limits are passed since the previous GC: 0x100 variables/temps/etc allocated 0x1000 array slots allocated 0x10000 bytes of strings allocated For applications that allocate large numbers of variables/objects/arrays to start up, a huge amount of time was spent performing a GC when only a very few objects were available for reclamation. For significant applications, there is a curve of memory usage during the apps lifetime. There is typically a lot of growth during startup and data loading, then the app reaches a steady state where the usage is fairly constant. Then at some point, the app is closed, and memory is released. For some apps this pattern repeats. In the new allocator, we apply a heuristic to guess when an application is growing and shrinking, and adapt the thresholds to the size of the application. We track the same items as before and bump the initial var and slot triggers: 0x200 variables 0x2000 slots 0x10000 string bytes (same as before) We make the thresholds for vars and slots adaptive. Only the variable and slot triggers adapt (change thresholds). When a GC is triggered by passing one of these thresholds, we examine the total number of items and how many were actually reclaimed. When fewer than 15% of items are reclaimed, we guess that the application is growing, and we double the trigger (up to a maximum of 0x00010000). When more than 85% of items are reclaimed, we guess that the application is shrinking, and we reset the thresholds to the starting values. To keep an application’s memory usage in trim when running at steady state, every 10 seconds we trigger a GC if the starting threshold of item have been allocated since the last collection. The timer-based collections do not cause the thresholds to change. For comparison, the CLR does a GC every 1 second. It can get away with this frequency because it is a generational GC, which reduces the cost of a collection pass. Because the jscript GC isn’t as efficient, we allow a longer time before triggering. I hope this helps and please let us know if you have any other questions. Thanks Peter GurevichAnonymous
January 16, 2007
I've flagged a few links to noteworthy JavaScript posts over the last month. Yahoo! Video: Advanced...Anonymous
January 16, 2007
I've flagged a few links to noteworthy JavaScript posts over the last month. Yahoo! Video: Advanced JavaScriptAnonymous
January 24, 2007
This is the first ever blog written by me in my entire life time. Let me take some time to introduceAnonymous
February 11, 2007
Peter Gurevich, Performance Programm Manager des IE7 Teams, hat seine dreiteilige Serie zu o.g. ThemaAnonymous
February 12, 2007
IE + JavaScript Performance Recommendations von Peter Gurevich, Programm Manager IE7 IE + JavaScriptAnonymous
September 02, 2007
ncaa 2005 college football rankingsAnonymous
September 02, 2007
The comment has been removedAnonymous
December 16, 2007
JavaScript est un langage " late binded " c'est à dire que chaque appel d'une propriété aura un coupAnonymous
December 16, 2007
JavaScript est un langage " late binded " c'est à dire que chaque appel d'une propriété aura un coûtAnonymous
November 21, 2008
Recently someone asked me about the best practices for AJAX performance. Though this information is scattered