sparkline

JavaScript performance comparison

Revision 4 of this test case created by Pedro

Info

Testing sparkline charts plugins

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

Test runner

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

Java applet disabled.

Testing in unknown unknown
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. Here’s a list of current revisions for this page:

0 comments

Add a comment