later schedule def

JavaScript performance comparison

Test case created by BunKat

Info

Performance tests for generating Later.js schedules using Recur, Cron, English expression, and manual methods. The moral of the story is to cache the parsed schedule instead of re-parsing it each time if performance is an issue.

Preparation code

<script type="text/javascript">
((function(){"use strict";var a=function(){var a={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12,SUN:1,MON:2,TUE:3,WED:4,THU:5,FRI:6,SAT:7},b={s:[0,0,59],m:[1,0,59],h:[2,0,23],D:[3,1,31],M:[4,1,12],Y:[6,1970,2099],d:[5,1,7,1]},c=function(b,c){return isNaN(b)?a[b]:+b+(c||0)},d=function(a){var b={},c;for(c in a)c!=="dc"&&c!=="d"&&(b[c]=a[c].slice(0));return b},e=function(a,b,c,d,e){var f=c;a[b]||(a[b]=[]);while(f<=d)a[b].indexOf(f)<0&&a[b].push(f),f+=e||1},f=function(a,b,c,f){if(b.d&&!b.dc||b.dc&&b.dc.indexOf(f)<0)a.push(d(b)),b=a[a.length-1];e(b,"d",c,c),e(b,"dc",f,f)},g=function(b,c,d){var f={},g={};d===1?(e(c,"D",1,3),e(c,"d",a.MON,a.FRI),e(f,"D",2,2),e(f,"d",a.TUE,a.FRI),e(g,"D",3,3),e(g,"d",a.TUE,a.FRI)):(e(c,"D",d-1,d+1),e(c,"d",a.MON,a.FRI),e(f,"D",d-1,d-1),e(f,"d",a.MON,a.THU),e(g,"D",d+1,d+1),e(g,"d",a.TUE,a.FRI)),b.exceptions.push(f),b.exceptions.push(g)},h=function(a,b,d,f,g,h){var i=a.split("/"),j=+i[1],k=i[0];if(k!=="*"&&k!=="0"){var l=k.split("-");f=c(l[0],h),g=c(l[1],h)}e(b,d,f,g,j)},i=function(a,b,d,i,j,k){var l,m,n=b.schedules,o=n[n.length-1];a==="L"&&(a=i-1),(l=c(a,k))!=null?e(o,d,l,l):(l=c(a.replace("W",""),k))!=null?g(b,o,l):(l=c(a.replace("L",""),k))!=null?f(n,o,l,i-1):(m=a.split("#")).length===2?(l=c(m[0],k),f(n,o,l,c(m[1]))):h(a,o,d,i,j,k)},j=function(a){return a.indexOf("#")>-1||a.indexOf("L")>0},k=function(a,b){return j(a)&&!j(b)?1:0},l=function(a){var c={schedules:[{}],exceptions:[]},d=a.split(" "),e,f,g,h;for(e in b){f=b[e],g=d[f[0]];if(g&&g!=="*"&&g!=="?"){h=g.split(",").sort(k);var j,l=h.length;for(j=0;j<l;j++)i(h[j],c,e,f[1],f[2],f[3])}}return c};return{parse:function(a,b){var c=a.toUpperCase();return l(b?c:"0 "+c)}}},b=typeof exports!="undefined"&&exports!==null?exports:window;b.cronParser=a})).call(this);var root=typeof exports!="undefined"&&exports!==null?exports:window,recur=root.recur;!recur&&typeof require!="undefined"&&(recur=require("./recur").recur),function(){"use strict";var a=function(){var a=0,b="",c,d={eof:/^$/,rank:/^((\d\d\d\d)|([2-5]?1(st)?|[2-5]?2(nd)?|[2-5]?3(rd)?|(0|[1-5]?[4-9]|[1-5]0|1[1-3])(th)?))\b/,time:/^((([0]?[1-9]|1[0-2]):[0-5]\d(\s)?(am|pm))|(([0]?\d|1\d|2[0-3]):[0-5]\d))\b/,dayName:/^((sun|mon|tue(s)?|wed(nes)?|thu(r(s)?)?|fri|sat(ur)?)(day)?)\b/,monthName:/^(jan(uary)?|feb(ruary)?|ma((r(ch)?)?|y)|apr(il)?|ju(ly|ne)|aug(ust)?|oct(ober)?|(sept|nov|dec)(ember)?)\b/,yearIndex:/^(\d\d\d\d)\b/,every:/^every\b/,second:/^(s|sec(ond)?(s)?)\b/,minute:/^(m|min(ute)?(s)?)\b/,hour:/^(h|hour(s)?)\b/,day:/^(day(s)? of the month)\b/,dayInstance:/^day instance\b/,dayOfWeek:/^day(s)? of the week\b/,dayOfYear:/^day(s)? of the year\b/,weekOfYear:/^week(s)? of year\b/,weekOfMonth:/^week(s)? of month\b/,weekday:/^weekday\b/,weekend:/^weekend\b/,month:/^month(s)?\b/,year:/^year\b/,between:/^between (the)?\b/,start:/^(start(ing)? (at|on( the)?)?)\b/,at:/^(at|@)\b/,and:/^(,|and\b)/,except:/^(except\b)/,also:/(also)\b/,first:/^(first)\b/,last:/^last\b/,"in":/^in\b/,of:/^of\b/,onthe:/^on the\b/,on:/^on\b/,through:/(-|^(to|through)\b)/},e={jan:1,feb:2,mar:3,apr:4,may:5,jun:6,jul:7,aug:8,sep:9,oct:10,nov:11,dec:12,sun:1,mon:2,tue:3,wed:4,thu:5,fri:6,sat:7,"1st":1,fir:1,"2nd":2,sec:2,"3rd":3,thi:3,"4th":4,"for":4},f=function(a,b,c,d){return{startPos:a,endPos:b,text:c,type:d}},g=function(c){var d=c instanceof Array?c:[c],e=/\s+/,g,h,i,j,k,l;d.push(e),k=a;while(!g||g.type===e){l=-1,h=b.substring(k),g=f(k,k,b.split(e)[0]);var m,n=d.length;for(m=0;m<n;m++)j=d[m],i=j.exec(h),i&&i.index===0&&i[0].length>l&&(l=i[0].length,g=f(k,k+l,h.substring(0,l),j));g.type===e&&(k=g.endPos)}return g},h=function(b){var c=g(b);return a=c.endPos,c},i=function(a){var b=+q(a),c=o(d.through)?+q(a):b,e=[];for(var f=b;f<=c;f++)e.push(f);return e},j=function(a){var b=i(a);while(o(d.and))b=b.concat(i(a));return b},k=function(a){var b,c,f,g;o(d.weekend)?a.on(e.sun,e.sat).dayOfWeek():o(d.weekday)?a.on(e.mon,e.tue,e.wed,e.thu,e.fri).dayOfWeek():(b=q(d.rank),a.every(b),c=n(a),o(d.start)?(b=q(d.rank),a.startingOn(b),p(c.type)):o(d.between)&&(f=q(d.rank),o(d.and)&&(g=q(d.rank),a.between(f,g))))},l=function(a){o(d.first)?a.first():o(d.last)?a.last():a.on(j(d.rank)),n(a)},m=function(e){a=0,b=e;var f=recur();while(a<b.length&&!c){var g=p([d.every,d.onthe,d.on,d.of,d.in,d.at,d.and,d.except,d.also]);switch(g.type){case d.every:k(f);break;case d.onthe:l(f);break;case d.on:f.on(j(d.dayName)).dayOfWeek();break;case d.of:f.on(j(d.monthName)).month();break;case d.in:f.on(j(d.yearIndex)).year();break;case d.at:f.at(q(d.time));while(o(d.and))f.at(q(d.time));break;case d.also:f.and();break;case d.except:f.except();break;default:c=a}}return{schedules:f.schedules,exceptions:f.exceptions,error:c}},n=function(b){var e=p([d.second,d.minute,d.hour,d.dayOfYear,d.dayOfWeek,d.dayInstance,d.day,d.month,d.year,d.weekOfMonth,d.weekOfYear]);switch(e.type){case d.second:b.second();break;case d.minute:b.minute();break;case d.hour:b.hour();break;case d.dayOfYear:b.dayOfYear();break;case d.dayOfWeek:b.dayOfWeek();break;case d.dayInstance:b.dayOfWeekCount();break;case d.day:b.dayOfMonth();break;case d.weekOfMonth:b.weekOfMonth();break;case d.weekOfYear:b.weekOfYear();break;case d.month:b.month();break;case d.year:b.year();break;default:c=a}return e},o=function(a){var b=g(a).type===a;return b&&h(a),b},p=function(b){var d=h(b);return d.type?d.text=r(d.text,b):c=a,d},q=function(a){return p(a).text},r=function(a,b){var c=a;switch(b){case d.time:var f=a.split(/(:|am|pm)/),g=f[3]==="pm"?parseInt(f[0],10)+12:f[0],h=f[2].trim();c=(g.length===1?"0":"")+g+":"+h;break;case d.rank:c=parseInt(/^\d+/.exec(a)[0],10);break;case d.monthName:case d.dayName:c=e[a.substring(0,3)]}return c};return{parse:function(a){return m(a.toLowerCase())}}};root.enParser=a}.call(this),function(){"use strict";var a=function(a,b){var c=b||!1,d="get"+(c?"":"UTC"),e=!0,f=a||1,g=864e5,h=Math.ceil,i=Math.floor,j=Date.prototype,k=j[d+"FullYear"],l=j[d+"Month"],m=j[d+"Date"],n=j[d+"Day"],o=j[d+"Hours"],p=j[d+"Minutes"],q=j[d+"Seconds"],r=function(a,b,c){var d,e,f=b[0],g=b.length;while(g--){d=b[g];if(d===a)return a;f=d<f?d:f,e=d>a&&(!e||d<e)?d:e}return e||f+c},s=function(a,b,d,e,f,g){return c?new Date(a,b,d,e||0,f||0,g||0):new Date(Date.UTC(a,b,d,e||0,f||0,g||0))},t=function(a){return(a<10?"0":"")+a},u=function(a,b,c){var d=b,e,f,j,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S=1e3;while(d&&S--){if(c&&d.getTime()>c.getTime())return null;u=k.call(d);if(a.Y&&(e=r(u,a.Y,0))!==u){d=e>u?s(e,0,1):null;continue}B=s(u,0,1),G=s(u+1,0,0);if(a.dy){I=h((d.getTime()-B.getTime()+1)/g),M=h((G.getTime()-B.getTime()+1)/g);if((e=r(I,a.dy,M))!==I){d=s(u,0,e);continue}}v=l.call(d);if(a.M&&(e=r(v+1,a.M,12))!==v+1){d=s(u,e-1,1);continue}w=m.call(d),x=n.call(d);if(a.wy){D=s(u,v,w+4-(x||7)),E=s(k.call(D),0,1),Q=n.call(B)===4||n.call(G)===4?53:52,J=h(((D.getTime()-E.getTime())/g+1)/7);if((e=r(J,a.wy,Q))!==J){d=s(k.call(D),l.call(D),m.call(D)-3+(e-J)*7);continue}}F=s(u,v+1,0),N=m.call(F);if(a.D&&(e=r(w,a.D,N))!==w){d=s(u,v,e);continue}if(a.wm){O=n.call(s(u,v,1)),K=i((w+O-1)/7+1),R=i((N+O-1)/7+1);if((e=r(K,a.wm,R))!==K){d=s(u,v,(e-1)*7-(O-1)-(e>R&&n.call(F)<6?7:0)+(e===R+1?n.call(F)+1:0));continue}}if(a.d&&(e=r(x+1,a.d,7))!==x+1){d=s(u,v,w+(e-1)-x);continue}if(a.dc){L=i((w-1)/7)+1;if((e=r(L,a.dc,0))!==L){if(e>0){d=s(u,v+(e<L?1:0),1+7*(e-1));continue}if(e<1&&w<N-6){d=s(u,v,N-6);continue}}}y=o.call(d);if(a.h&&(e=r(y,a.h,24))!==y){d=s(u,v,w,e);continue}z=p.call(d);if(a.m&&(e=r(z,a.m,60))!==z){d=s(u,v,w,y,e);continue}A=q.call(d);if(a.s&&(e=r(A,a.s,60))!==A){d.setSeconds(e),d=s(u,v,w,y,z,e);continue}if(a.t){H=t(y)+":"+t(z)+":"+t(A);if((e=r(H,a.t,""))!==H){f=e.split(":"),d=s(u,v,w+(H>e?1:0),f[0],f[1],f[2]);continue}}break}return S>0?d:null},v=function(a){return new Date(a.getTime()+f*1e3)};return{isValid:function(a,b){return b.getTime()===this.getNext(a,b).getTime()},get:function(a,b,c,d){var e=[],f;while(b-->0&&(f=this.getNext(a,f||c,d)))e.push(f),f=v(f);return e},getNext:function(a,b,c){var d=a.schedules||[],e={schedules:a.exceptions||[]},f=b||new Date,g,h,i=d.length;if(c&&b.getTime()>c.getTime())return null;while(i--){h=u(d[i],f,c);if(!g||h<g)g=h}return g&&e.schedules.length>0&&this.isValid(e,g)&&(g=this.getNext(a,v(g))),g},exec:function(a,b,c,d){var f=this.getNext(a,v(b));if(f)return f=f.getTime()-(new Date).getTime(),e=setTimeout(this.handleExec,f,this,a,c,d),!0},stopExec:function(){e&&(clearTimeout(e),e=!1)},handleExec:function(a,b,c,d){c(d),e&&a.exec(b,new Date,c,d)}}},b=typeof exports!="undefined"&&exports!==null?exports:window;b.later=a}.call(this),function(){"use strict";var a=function(){var a=[{}],b=[],c=a[0],d=a,e,f,g,h,i,j,k,l=function(a,b,d){c[a]||(c[a]=[]),e=c[a];if(g){f=[];for(j=b;j<=d;j+=g)f.push(j);k={n:a,x:g,c:e.length,m:d}}f=h?[b]:i?[d]:f;var l=f.length;for(j=0;j<l;j+=1)e.indexOf(f[j])<0&&e.push(f[j]);f=g=h=i=0};return{schedules:a,exceptions:b,on:function(){return f=arguments[0]instanceof Array?arguments[0]:arguments,this},every:function(a){return g=a,this},first:function(){return h=1,this},last:function(){return i=1,this},at:function(){f=arguments;var a,b=f.length;for(var a=0;a<b;a++){var c=f[a].split(":");c.length<3&&(f[a]+=":00")}return l("t"),this},second:function(){return l("s",0,59),this},minute:function(){return l("m",0,59),this},hour:function(){return l("h",0,23),this},dayOfMonth:function(){return l("D",1,i?0:31),this},dayOfWeek:function(){return l("d",1,7),this},onWeekend:function(){return f=[1,7],this.dayOfWeek()},onWeekday:function(){return f=[2,3,4,5,6],this.dayOfWeek()},dayOfWeekCount:function(){return l("dc",1,i?0:5),this},dayOfYear:function(){return l("dy",1,i?0:366),this},weekOfMonth:function(){return l("wm",1,i?0:5),this},weekOfYear:function(){return l("wy",1,i?0:53),this},month:function(){return l("M",1,12),this},year:function(){return l("Y",1970,2450),this},startingOn:function(a){return this.between(a,k.m)},between:function(a,b){return c[k.n]=c[k.n].splice(0,k.c),g=k.x,l(k.n,a,b),this},and:function(){return c=d[d.push({})-1],this},except:function(){return b.push({}),d=b,c=b[0],this}}},b=typeof exports!="undefined"&&exports!==null?exports:window;b.recur=a}.call(this);
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Simple Recur
var schedule = recur().every(5).minute();
pending…
Simple Cron
var schedule = cronParser().parse('* */5 * * * *', true);
pending…
Simple English Expr
var schedule = enParser().parse('every 5 minutes');
pending…
Simple Manual
var schedule = {
  schedules: [{
    m: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]
  }]
};
pending…
Complex Recur
var schedule = recur().at('05:00:00').on(15).dayOfMonth().onWeekday();
schedule.and().at('05:00:00').on(14).dayOfMonth().on(6).dayOfWeek();
schedule.and().at('05:00:00').on(16).dayOfMonth().on(2).dayOfWeek();
pending…
Complex Cron
var schedule = cronParser().parse('0 5 15W * ?');
pending…
Complex English Expr
var str = 'every weekday on the 14-16th day of the month at 5:00 am ';
str += 'except on the 14th day of the month on mon-thu ';
str += 'also on the 16th day of the month on tue-fri';

var schedule = enParser().parse(str);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment