sparkline

JavaScript performance comparison

Revision 4 of this test case created by Pedro

Preparation code

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
	<style>
		.sparkline{
			position: relative;
			margin: 30px;
		}
		.sparkline div{
			width: 0px; 
		    border-style: solid;
		    background-color: transparent;
		    position: absolute;
		    bottom: 0px;
		}
	
		.sparkline a{
			cursor: pointer;
			position: absolute;
			width: 8px;
			height: 8px;
			background: url('bullet.png') transparent 0 0 no-repeat;
			margin-left: -4px;
			margin-bottom: -4px;
		}

		</style>

<script type="text/javascript" src="http://documentcloud.github.io/underscore/underscore-min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script>


<script  type="text/javascript" src="http://omnipotent.net/jquery.sparkline/2.1.2/jquery.sparkline.min.js"></script>



<div id="teste1"></div>
<div class="sparkline" id="teste2"></div>
<div id="teste3" style="width:100px; height:20px;"></div>
<div id="teste4" style="width:100px; height:20px;"></div>
      
<script>
Benchmark.prototype.setup = function() {
  Raphael.fromJquery = function($obj) {
    var obj = $obj.get(0),
      width = obj.scrollWidth,
      height = obj.scrollHeight;
    return Raphael($obj.attr('id'), width, height);
  };
  
  Raphael.fn.sparkline = function(data) {
    var paper = this,
      min = Math.min.apply(Math, data),
      max = Math.max.apply(Math, data),
      graph_opts = {
        padding: {
          top: 5,
          left: 5,
          bottom: 5,
          right: 5
        },
      },
      graph_width = paper.width - graph_opts.padding.left - graph_opts.padding.right,
      graph_height = paper.height - graph_opts.padding.top - graph_opts.padding.bottom,
      padding = graph_opts.padding.left;
  
    var to_coords = function(value, idx) {
      var step = (graph_width / (data.length - 1));
      return {
        y: max - min !== 0 ? -((value - min) / (max - min) * graph_height) + graph_height + graph_opts.padding.top : graph_height / 2 + graph_opts.padding.top,
        x: padding + idx * step
      };
    };
  
    var prev_pt;
  
    _.each(data, function(item, idx) {
      var pt = to_coords(item, idx);
  
      if (item === max || item === min) {
        paper.circle(pt.x, pt.y, 1).attr({
          stroke: '#F00'
        }).toFront();
      }
      if (idx === 0 || idx === data.length - 1) {
        paper.circle(pt.x, pt.y, 1).attr({
          stroke: '#00F'
        }).toFront();
      }
  
      if (prev_pt) {
        var path = Raphael.format("M{0},{1}L{2},{3}z", prev_pt.x, prev_pt.y, pt.x, pt.y);
        paper.path(path).attr({
          stroke: '#666',
          'stroke-width': 0.5
        });
      }
      prev_pt = pt;
    });
  };
  var data = [Math.floor((Math.random()*1000) - (Math.random()*1000)), Math.floor((Math.random()*1000) - (Math.random()*1000)), Math.floor((Math.random()*1000) - (Math.random()*1000)), Math.floor((Math.random()*1000) - (Math.random()*1000)), Math.floor((Math.random()*1000) - (Math.random()*1000))];
  var spark={
  				rzCC:function(s){
  				  for(var exp=/-([a-z])/; 
  				      exp.test(s); 
  				      s=s.replace(exp,RegExp.$1.toUpperCase()));
  				  return s;
  				},
  				_setStyle:function(element, declaration) {
  
  				  if (declaration.charAt(declaration.length-1)==';')
  				    declaration = declaration.slice(0, -1);
  				  var k, v;
  				  var splitted = declaration.split(';');
  				  for (var i=0, len=splitted.length; i<len; i++) {
  				     k = spark.rzCC(splitted[i].split(':')[0]);
  				     v = splitted[i].split(':')[1];
  				     eval("element.style."+k+"='"+v+"'");
  				  }
  				  return element;
  				},
  				toCords:function(maxh,h,val,min){
  					return (val*h/maxh)-(min*h/maxh);
  				},
  				styleTriangle:function(left, h, w, a, pos){
  
  				    if(left){
  
  				        var c=0, b=w, ca="transparent blue transparent transparent", cb="transparent white transparent transparent";
  				    } else {
  						var c=w, b=0, ca="transparent transparent transparent blue", cb="transparent transparent transparent white";
  				    }
  	  
  					return { 
  						up:"height: "+h+"px; border-width: "+a+"px " + b + "px 0px " + c +"px; border-color:" + ca + "; left:"+pos+"px;",
  						down: "height: "+h+"px; border-width: "+a+"px " + b + "px 0px " + c +"px; border-color:" + cb +"; left:"+pos+"px; bottom:-1px;"
  					};
  
  				},
  				Sparkline:function(el, w, h, values, callbackTitle){
  					var val_filter=_.filter(values, function(num){ return num != null; }),
  					min = _.min(val_filter),
  	      			max = _.max(val_filter), 
  	      			totalH=max-min, 
  	      			lastH=null, 
  	      			w=Math.ceil(w/values.length),
  	      			elems=[],
  	      			elemsPoint=[];
  	      			
  	      		
  	      			_.each(values, function(item, idx){
  	      				var tri = null, left=true, a=0;
  
  	      				if(item==null){
  
  	      					if(idx==values.length-1){
  	      						tri = spark.styleTriangle(left, (lastH.H_ITEM<1?1:lastH.H_ITEM) , (idx-lastH.idx)*w, 0, (lastH.idx)*w);
  	      					}
  
  	      				}else{
  
  							var H_ITEM=spark.toCords(totalH,h,item,min);
  							if(_.isNaN(H_ITEM)) H_ITEM=0;
  							var elem_a=document.createElement("a");
  							elem_a.title=callbackTitle(idx);
  							
  							elemsPoint.push(spark._setStyle(elem_a, "bottom:"+ H_ITEM +"px; left:"+((idx)*w)+"px;"));
  	      					if(lastH==null && idx>0){
  								tri = spark.styleTriangle(left, (H_ITEM<1? 1 : H_ITEM), w*idx, a, 0);
  
  	      					}else if(idx>0){
  	 
  	      						if(H_ITEM<(lastH.H_ITEM)) {
  	      							left=false;
  	      						}
  	      						a=Math.abs(lastH.H_ITEM-H_ITEM);
  	      						
  								tri = spark.styleTriangle(left, _.min([H_ITEM,lastH.H_ITEM]), (idx-lastH.idx)*w, a,((lastH.idx)*w));
  
  	      					}
  	      					lastH={idx:idx,a:a,H_ITEM:H_ITEM};
  	      					
  	      				}
  
  						
  	      				if(tri!=null){
  	      					elems.push(spark._setStyle(document.createElement("div"), tri.up));
  	      					elems.push(spark._setStyle(document.createElement("div"), tri.down));
  	      				}
  	      			})
  	      			var fragment = document.createDocumentFragment();
  					for (var e = 0; e < elems.length; e++) {
  		                fragment.appendChild(elems[e]);
  		            }
  		            for (e = 0; e < elemsPoint.length; e++) {
  		                fragment.appendChild(elemsPoint[e]);
  		            }
  		        	spark. _setStyle(el, "height:"+h+"px; width:"+w+"px");
  		            el.appendChild(fragment.cloneNode(true));
  				}
  
  			}

};
</script>

Preparation code output

<style> .sparkline{ position: relative; margin: 30px; } .sparkline div{ width: 0px; border-style: solid; background-color: transparent; position: absolute; bottom: 0px; } .sparkline a{ cursor: pointer; position: absolute; width: 8px; height: 8px; background: url('bullet.png') transparent 0 0 no-repeat; margin-left: -4px; margin-bottom: -4px; } </style> <script type="text/javascript" src="http://documentcloud.github.io/underscore/underscore-min.js"></script> <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script> <script type="text/javascript" src="http://omnipotent.net/jquery.sparkline/2.1.2/jquery.sparkline.min.js"></script> <div id="teste1"></div> <div class="sparkline" id="teste2"></div> <div id="teste3" style="width:100px; height:20px;"></div> <div id="teste4" style="width:100px; height:20px;"></div>

Test runner

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

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
raphael
var r = Raphael(document.getElementById("teste1"), 100, 20);
r.sparkline(data);
pending…
jquery
$('#teste3').sparkline(data);
pending…
dom test
new spark.Sparkline(document.getElementById("teste2"), 80, 15, data, function(idx){
					return data[idx];
				});
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.

0 Comments