Prev: FAQ Topic - Why does simple decimal arithmetic give strange results? (2010-03-31)
Next: Consolidate Credit Card Debt
From: Antony Scriven on 2 Apr 2010 15:58 On Apr 2, 7:02 pm, Thomas 'PointedEars' Lahn wrote: > Lasse Reichstein Nielsen wrote: > > Thomas 'PointedEars' Lahn <PointedE...(a)web.de> writes: > > > 2. Several function calls will be always more > > > expensive than just one and the creation of an > > > Array instance. > > > > That's not a given. > > > > It's possible that four function calls take longer than > > creating an Array and calling one function that loops > > over the array and extracts the elements again > > (possible, but not given), but the latter also > > allocates space for the array. If this happens often > > enough, the memory overhead will also cause earlier > > garbage collection. > > That argument is dubious and the tests have no meaning > because the function argument in chaining may be an Array > or Object reference anyway. Incidentally, that is what > can be observed in current general-purpose libraries that > use chaining. > > You are correct that cost is not merely measured in > runtime spent. However, you are ignoring here that for, > say, ten registrations I would need ten chained function > calls, or only one function call with an Array instance > of length 10. There can be no doubt that the chaining > grows more inefficient than the alternatives with each > registration. With 1000 registrations I would still need > only one Array instance or 1000 items to iterate over, > instead of 1000 calls to be made. And if, on average, the OP has only four registrations, what then? For the OP's specific case, theorising is pointless. I'm not saying you should entirely ignore performance considerations, and I do find Lasse's tests interesting, but optimisation should always be based on hard evidence, specific to the application. And remember The First Rule of Performance Optimisation: don't. --Antony
From: Lasse Reichstein Nielsen on 2 Apr 2010 17:32 Thomas 'PointedEars' Lahn <PointedEars(a)web.de> writes: > Lasse Reichstein Nielsen wrote: > >> Thomas 'PointedEars' Lahn <PointedEars(a)web.de> writes: >>> 2. Several function calls will be always more expensive than just one >>> and the creation of an Array instance. >> >> That's not a given. >> >> It's possible that four function calls take longer than creating an Array >> and calling one function that loops over the array and extracts the >> elements again (possible, but not given), but the latter also allocates >> space for the array. If this happens often enough, the memory overhead >> will also cause earlier garbage collection. > > That argument is dubious and the tests have no meaning because the function > argument in chaining may be an Array or Object reference anyway. That is irrelevant. If you create more objects, but do so in both cases, then it will just reduce the impact of the difference, but not eliminate it. > Incidentally, that is what can be observed in current general-purpose > libraries that use chaining. I won't argue against that without knowing the quality of code of those projects (but I'll wager a guess and assume that bad code could be blamed for most of their performance characteristics). > You are correct that cost is not merely measured in runtime spent. Any other cost, e.g., memory allocation, generally shows up in runtime as well. > However, you are ignoring here that for, say, ten registrations I would > need ten chained function calls, or only one function call with an Array > instance of length 10. This is not about chaining. Chaining may or may not cause an overhead compared to directly calling, but chaining wasn't mentioned in the point I'm arguing against. And as to the number of calls/length of the array, I'm not ignoring it. I show that for the case where the number is four, the point ("... will always be more expensive than ...") doesn't hold. I believe it will hold for larger numbers too, and I'm willing to test it. > There can be no doubt that the chaining grows more > inefficient than the alternatives with each registration. With 1000 > registrations I would still need only one Array instance or 1000 items to > iterate over, instead of 1000 calls to be made. The overhead of creating the array will be reduced compared to the case with fewer calls, but the cost of populating the array won't, nor will the cost of iterating over it and extracting the values again. Those are expensive memory accesses, compared to stack allocated function arguments. But again, I'm willing to test it: Is there number of calls where creating the array is faster. It's not obvious that there is, nor is it obvious that there isn't. > I find it particularly dubious that you have not noticed that the length of > the effective prototype chain can be an important factor regarding > efficiency. setChained() is an instance method with a short effective > prototype chain, setProp() and setProps() are prototype methods with longer > ones. That is a good point. While it's the natural implementation of each of these strategies, it does give a natural difference in the time of a single method call (a quick test shows the difference to be marginal in Opera and Chrome, and quite significant in Firefox). > I also don't see you considering that the chaining approach needs at > least one Function object more than the non-chaining one in your example. It needs one function per instance, which is significant. However, my main point was not about chaining (which I'm not convinced is a win compared to diret calls), but purely against the notion that passing an array of arguments in one call is always faster than doing multiple calls. > All in all, I don't think your argument or test holds water. Which test would? I tried making another one, ignoring chaining for now, since it's not part of the point I'm trying to make: http://www.infimum.dk/privat/testcallvsarray.html There does seem to be a point where using a single call with an array is faster than doing separate calls. For Opera it is around *2000* calls[1]. I'm wagering that counts as a very rare use case. So, the point is that: "Several function calls will be always more expensive than just one and the creation of an Array instance." is wrong. For such an absolute statement, it might not be surprising that there is a counter example. However, it seems that for *any* reasonable number of calls, calling is faster than building an array of arguments and passing them in one go - in most browsers [2]. After testing, it seems that it's only the case in very very rare cases. /L "Function calls aren't slow. 'nuff said" [1] Firefox is weird: An Array of length 2000 is *slower* than one of length 3000! [2] Just checked Safari. It's actually slightly faster with the array. -- Lasse Reichstein Holst Nielsen 'Javascript frameworks is a disruptive technology'
From: Richard Cornford on 6 Apr 2010 07:25
On Apr 1, 4:38 pm, Thomas Allen wrote: > On Apr 1, 6:56 am, Richard Cornford wrote: >> On Apr 1, 12:10 am, nick wrote: >>> To me something like >>> this is easily understandable, if a bit esoteric: > >>> Cufon('h1')('h2')('h3'); > >> Looking at this code itself we see a call to (what is assumed >> to be) a function, and then a call to whatever is returned >> from that first call, and then a call to whatever is returned >> from that. We might also observe a similarity in the arguments. > >> That is all the information available in the code. In order to >> determine that this actually represents three calls to the same >> function it will be necessary to find the code for a - Cufon - >> definition, or the code for whatever function is assigned to >> - Cufon - at any given time. Otherwise (even if 'Cfon' were >> instead an Identifier that described what the function did) >> the nature/process of the second and third function calls >> remains unknown. It is not even hinted at by the code above, >> and that is an objective fact. > > To be fair, I think that code intended for other developers' use > should be well-documented. Fair enough, you might not have to go to the code for - Cufon -, instead you could go to the documentation (assuming it actually was good enough). > So, in my opinion, your concern about the "nature/process of > the second and third function calls" is unwarranted, provided > that the function's return value (and usage too, given the > bizarre operation nick wants) is explained adequately. My concern here is only with how much understanding can be derived from the source code itself. For that it makes no real difference if understanding is only available through reference to documentation or only through reference to other source code, what is significant is that the code above is not saying what it is doing when it could be. If maintenance is where most software development resources are spent (as is frequently attested) strategies that ease maintenance can be disproportionately advantageous (over, say, strategies that easy initial code entry/typing). Writing directly understandable (even self- documenting) source code is one such strategy, particularly for the top level code that employs pre-built APIs (and the like). Richard. |