I am playing around with the date object, i made a function that generates a bunch of dates, and applies some function on each date.
For a month's worth, it is fine about 2.5ms on my pc, ff and chrome, but for a year's worth it is horribly slow, 17-50ms, not predictable at all.
This ofc got me thinking, what am I doing wrong, why the unpredictability?
What would you do different, in dynamically creating a years worth of timestamps?
function MakeDateRange( begin, end, __func )
{
begin = new Date(begin);
end = new Date(end);
var len =((end.getTime()-begin.getTime())/86400000)|0,
i = 0,
t = performance.now(),
dates = [];
__func = __func || function( date )
{
return new Date(date);
}
for(i; i <= len; i++)
{
dates.push(__func(begin));
begin.setDate(begin.getDate()+1);
}
document.body.innerHTML += (performance.now()-t )+"<br />";
return dates;
}
var dates = MakeDateRange( "2015 2 1 0:0:0 GMT+0100", "2016 2 1 0:0:0 GMT+0100" , function(date){
var no = document.body.appendChild(document.createElement("div"));
no.innerHTML = date;
return no
});
-
2You can profile it, right?djechlin– djechlin2015年12月06日 08:18:36 +00:00Commented Dec 6, 2015 at 8:18
-
1Not to the degree that it helps me, do you have any suggestions ?MeganFoxObama– MeganFoxObama2015年12月06日 09:05:37 +00:00Commented Dec 6, 2015 at 9:05
-
1What is your performance requirement?Robert Harvey– Robert Harvey2015年12月07日 08:00:28 +00:00Commented Dec 7, 2015 at 8:00
-
3Have you tried having a number and adding one days worth of milliseconds instead of getDate/setDate?Alpha– Alpha2015年12月12日 14:29:55 +00:00Commented Dec 12, 2015 at 14:29
-
3I'm not sure about the inconsistency, but I think this would be better if there was no DOM manipulation within the MakeDates function. If required, build up the elements unattached to the DOM, then make one insert of all the data once completed.Matt Klinker– Matt Klinker2015年12月29日 19:45:27 +00:00Commented Dec 29, 2015 at 19:45
1 Answer 1
Performance Tests
Visit jackgiffin.com for performance tests
The Code
Well, for one thing I would write all of the HTML at once. Another thing is that I would use insertAdjacentHTML so that current event listeners and other virtual parts of the body's current content don't get taken off. So, using this and several other micro-optimizations, I tripled the performance of your code (in chrome, at least). The following optimized function preserve most of your functions original functionality.
let currentRound = -1;
MakeDateRange = function( beginText, endText, __func ){
'use-strict';
const t = performance.now();
let begin = new Date(beginText), end = new Date(endText),
curRound = 'z' + ++currentRound,
len = ((end.getTime()-begin.getTime())/86400000)|0,
i = -1,
bodyHTML = '',
dates;
if (__func instanceof Function){
while (i++ !== len)
begin.setDate(begin.getDate()+1), bodyHTML += __func(begin, curRound);
document.body.insertAdjacentHTML('beforeend',bodyHTML);
perfs[1] = (performance.now()-t );
return document.getElementsByName(curRound);
}
dates = new Array(len);
while (i++ !== len)
begin.setDate(begin.getDate()+1), dates[len] = new Date(begin);
perfs[1] = (performance.now()-t );
return dates;
};
dates = MakeDateRange(
"2015 2 1 0:0:0 GMT+0100",
"2016 2 1 0:0:0 GMT+0100" ,
function(date, curRound){ return '<div name='+curRound+'>'+date+'</div>' }
);
console.log(dates);
However, if you inline __func
then it will be even faster:
let currentRound = -1;
MakeDateRange = function( beginText, endText ){
'use-strict';
const t = performance.now();
let begin = new Date(beginText), end = new Date(endText),
curRound = 'z' + ++currentRound,
template = '<div name="' + curRound + '">',
len = ((end.getTime()-begin.getTime())/86400000)|0,
i = -1,
bodyHTML = '',
dates;
while (++i !== len)
begin.setDate(begin.getDate()+1), bodyHTML += template + begin + '</div>';
document.body.insertAdjacentHTML('beforeend',bodyHTML);
perfs[2] = (performance.now()-t );
return document.getElementsByName(curRound);
};
dates = MakeDateRange(
"2015 2 1 0:0:0 GMT+0100",
"2016 2 1 0:0:0 GMT+0100"
);
console.log(dates);
And also, I would highly recommend using let
and const
instead of var
because performance.now
has been available since IE10, and let
and const
are available since IE11. IE10 is only obtainable through having specific windows 7 updates. And, most windows users have either no updates installed which would mean IE9, or, much more commonly, all windows updates installed which would mean IE11. It is unlikely any windows 7 user with just the right updates for IE10 will visit your site, so you might as well shoot for IE11.
-
1Something seems to be missing from the last sentence?Glorfindel– Glorfindel2017年07月10日 06:49:28 +00:00Commented Jul 10, 2017 at 6:49