Ruby's Louvre

每天学习一点点算法

导航

queryspeed

QuerySpeed.js

(function(){
    if(!String.prototype.trim){
        String.prototype.trim = function(){
            return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
        }
    }
    var mix = function(target, source ,override) {
        var i, ride = (override === void 0) || override;
        for (i in source) {
            if (ride || !(i in target)) {
                target[i] = source[i];
            }
        }
        return target;
    }
    var dom = {};
    var metaObject = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '\\': '\\\\'
    },
    _startOfHTML = "\t__views.push(",
    _endOfHTML = ");\n",
    _rAt = /(^|[^\w\u00c0-\uFFFF_])(@)(?=\w)/g;
    (function(w,s){
        //http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
        s = ["XMLHttpRequest",
        "ActiveXObject('Msxml2.XMLHTTP.6.0')",
        "ActiveXObject('Msxml2.XMLHTTP.3.0')",
        "ActiveXObject('Msxml2.XMLHTTP')",
        "ActiveXObject('Microsoft.XMLHTTP')"];
        if( !-[1,] && w.ScriptEngineMinorVersion() === 7 && location.protocol === "file:"){
            s.shift();
        }
        for(var i = 0 ,el;el=s[i++];){
            try{
                if(eval("new "+el)){
                    dom.xhr = new Function( "return new "+el)
                    break;
                }
            }catch(e){}
        }
    })(this);

    mix(dom,{
        queryId : function (id, context) {
            var el = (context || document).getElementById(id);
            return el && [el] || []
        },
        queryTag : function(tag,context){
            var flag_skip = tag !== "*",result = [],els = (context || document).getElementsByTagName(tag);
            if(-[1,]){
                return  Array.prototype.slice.call(els)
            }else{
                for(var i = 0,ri = 0,el;el = els[i++];)
                    if(flag_skip || el.nodeType === 1){
                        result[ri++] = el
                    }
            }
            return result;
        },
        each: function(array,fn,bind){
            for (var i = 0, n = array.length; i < n; i++){
                if(i in array){
                    if(fn.call(bind, array[i], i, array) === false){
                        break;
                    }
                }
            }
        },
        numberOfWindow : 0,
        numberOfIframe : 0,
        hasReady : function(){
            if(dom.numberOfWindow === dom.numberOfIframe ){
                var el = dom.queryId("hasReady")[0]
                el.innerHTML = "已经准备就绪!";
                el.style.color = "#a9ea00";
            }
        },
        addEvent: document.addEventListener ?  function(el,type,fn){
            el.addEventListener(type,fn,false);
        } :  function(el,type,fn){
            el.attachEvent("on"+type,function(){
                return fn.call(el,window.event)
            })
        },
        quote: String.quote || function (str) {
            return   '"' + str.replace(/[\\\"\x00-\x1f]/g, function (a) {
                var c = metaObject[a];
                return typeof c === 'string' ? c :
                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"'
        },
        ejs_partial: function(url){
            var xhr = dom.xhr();
            xhr.open("GET",url,false);
            xhr.setRequestHeader("If-Modified-Since","0");
            xhr.send(null);
            return xhr.responseText|| ""
        },

        ejs: function(obj,usePart){
            if(!usePart){//如果普通模板,则要整理配置文件
                obj.left = obj.left || "<&";
                obj.right = obj.right || "&>";
                obj.rLeft =  obj.rLeft  || new RegExp("\\s*"+ obj.left+"\\s*");
                obj.rRight = obj.rRight  || new RegExp("\\s*"+ obj.right+"\\s*");
            }
            //取得缓存索引
            var key = obj.selector || obj.url,
            rAt = _rAt,
            startOfHTML = _startOfHTML,
            endOfHTML = _endOfHTML,
            self = arguments.callee,
            buff = ["var __views = [];\n"],str;
            if(obj.selector){
                var el = dom.queryId(key);
                if (!el.length) throw "can not find the target element";
                str = el[0].text;
            }else {
                str = dom.ejs_partial(obj.url);
                if (!str) throw "the target file does not exist";
            }
            if(!self[key]){
                var arr = str.trim().split(obj.rLeft),temp = [],url,selector,i=0,n=arr.length,els,segment,logic;
                while(i<n){
                    segment = arr[i++];
                    els = segment.split(obj.rRight);
                    if(segment.indexOf(obj.right) !== -1){//这里不使用el.length === 2是为了避开IE的split bug
                        switch (els[0].charAt(0)) {
                            case "~"://include 局部模板 以URL方式引入
                                delete obj.selector;
                                obj.url = els[0].substring(1).trim();
                                self[url] = self[url] || self(obj,true);
                                temp = temp.concat(self[url] );
                                break;
                            case ":"://include 局部模板 以元素选择符方式引入
                                delete obj.url;
                                selector = obj.selector = els[0].substring(1).trim();
                                self[selector] = self[selector] || self(obj,true);
                                alert(temp)
                                temp = temp.concat(self[selector] );
                                break;
                            case "="://处理后台返回的变量(输出到页面的);
                                logic = els[0].substring(1);
                                if(logic.indexOf("@") !== -1){
                                    temp.push(startOfHTML, logic.replace(rAt,"$1data."), endOfHTML);
                                }else{
                                    temp.push(startOfHTML, logic, endOfHTML);
                                }

                                break;
                            case "#"://处理注释
                                break;
                            default:
                                logic = els[0];
                                if(logic.indexOf("@") !== -1){
                                    temp.push(logic.replace(rAt,"$1data."), "\n");
                                }else{
                                    temp.push(logic, "\n");
                                }
                        }
                        els[1] &&  temp.push(startOfHTML, dom.quote.call(null,els[1]), endOfHTML)
                    }else{
                        temp.push(startOfHTML, dom.quote.call(null,els[0]), endOfHTML)
                    }
                }
                if(usePart){//局部模板
                    return  (self[key] = temp);
                }else{
                    //缓存模板函数
                    self[key] = new Function("data", buff.concat(temp).join("") + ';return __views.join("");');
                }
            }
            return  self[key](obj.data || {});
        }
    });
    window.dom = dom;

    //要测试的框架
    var frameworks = {
        "Peppy 0.1":{
            disable:1,
            file:"peppy.js",
            fun:"$"
        },
        "uuQuery v1.01":{
            
            file:"uuQuery.js",
            fun:"uuQuery"
        },

        "DOMAssistant2.8":{
            disable:1,
            file:"DOMAssistantComplete-2.8.js",
            fun:"$"
        },
        "query v3.9":{

            file:"queryv39.js",
            fun:"dom.query"
        },

        "Fox":{
            disable:1,
            file:"Fox.js",
            fun:"Fox.query"
        },

        "jQuery1.4.4":{
             disable:1,
            file:"jquery1.4.4.js",
            fun:"jQuery"
        },
        "Sizzle":{
            file:"sizzle.js",
            fun:"Sizzle"
        },
        "Sly v1.0rc2":{
            disable:1,
            file:"Sly.js",
            fun:"Sly.search"
        },
        "inQuery":{
            disable:1,
            file:"inCore.js,inQuery.js",
            fun:"$"
        },

        "EXT 2.2":{
            disable:1,
            file:"ext-2.2.js",
            fun:"Ext.query"
        },


        "JQuery 1.2.6":{
            disable:1,
            file:"jquery-1.2.6.js",
            fun:"jQuery"
        },

        "MooTools 1.3":{
            disable:1,
            file:"mootools.js",
            fun:"$$"
        },


        "YUI 2.6.0":{
            disable:1,
            file:"YUI-2.6.0.selector-beta.js",
            fun:"YAHOO.util.Selector.query"
        },
        "myframework":{
            disable:1,
            file:"myFramework.js",
            fun:"getElements"
        },
        "Dojo 1.2.0":{
            disable:1,
            file:"dojo-1.2.0.js",
            fun:"dojo.query"
        }
    }
    //要测试的选择器
    var selectors = [
    "div :only-of-type",
    "th:first-of-type",
    "th:last-of-type",
    "td:nth-of-type(even)",
    "td:nth-last-of-type(odd)",
    "body :empty",
    "div:not(.example)",
    "p:contains(selectors)",
    "div p a",
    // "div, p, a",
    "div p",
    "body div",
    ".note",
    "ul.toc li.tocline2",
    "ul.toc > li.tocline2",
    "tr .pattern",
    "p",
    "div",
    "div ~ p",
    "div > div",
    "div ~ div",
    "div > p",
    "body",
    "div + p",
    "div ~ p",
    "div[class^=exa][class$=mple]",
    "div.example",
    "ul .tocline2",
    "div.example, div.note",
    "#title",
    "h1#title",
    "div #title",
    "h1#title + div > p",
    "a[href][lang][class]",
    "div[class]",
    "div[class=example]",
    "div[class^=exa]",
    "div[class$=mple]",
    "div[class*=e]",
    "div[class|=dialog]",
    "div[class!=made_up]",
    "div[class~=example]",
    "p:nth-child(even)",
    "p:nth-child(2n)",
    "p:nth-child(odd)",
    "p:nth-child(2n+1)",
    "p:nth-child(n)",
    "p:only-child",
    "p:last-child",
    "p:first-child",
    "div :only-child",
    "td:odd",
    "p:even"
    ]
    window.onload = function(){


        dom.queryId("iframes_tc")[0].innerHTML = dom.ejs({
            selector:"iframes_tmpl",
            data:{
                frameworks:frameworks
            }
        });

        dom.queryId("table_tc")[0].innerHTML = dom.ejs({
            selector:"table_tmpl",
            data:{
                frameworks:frameworks,
                selectors:selectors
            }
        });


        var tbody = dom.queryTag('tbody')[0];
        var tfoot = dom.queryTag('tfoot')[0];
        var lastrow = dom.queryTag('tr',tfoot)[0];
        var startTest = dom.queryId("startTest")[0];
        var stopTest = dom.queryId("stopTest")[0];
        var scoreNum= {}; //用于放置积分
        var scoreTds = {};//用于放置存在积分的TD元素
        var cellIndex = 1;
        var framework;
      
        for(var name in frameworks){
            framework = frameworks[name];
            if (!framework.disable){
                framework.window =  window.frames[name];
                framework.selectors = selectors.concat();
                scoreTds[name] = lastrow.cells[cellIndex++]
                dom.numberOfWindow++;
                scoreNum[name] = 0;
            }
        }

        var tests = [] ,rows = tbody.rows
     
        dom.each(selectors, function(selector, i){//构建测试单元数组,个数为tbody的TD数
            var cellIndex = 1,row = rows[i],framework;
            for (var name in frameworks){
                framework = frameworks[name];
                if (!framework.disable){
                    tests.push({
                        'window': framework.window,//执行环境
                        'selector': framework.selectors[i],
                        'name': name,
                        'row': row,
                        'cell' : row.cells[cellIndex++]
                    });
                }
            }
        });

        var timeoutId;
        var testRunner = function(){       
            var test = tests.shift();//取得测试单元
            if (!test || !test.window.test) return;//如果不存在选择器函数返回
            var results = test.window.test(test.selector);
            test.cell.className = 'test';
            test.cell.innerHTML = results.time + ' ms | ' + results.found + ' found';//花了多少时间与发现了多少个节点
            test.cell.speed = results.time;
            if (results.error){
                test.cell.innerHTML = results.time + ' ms | <span class="exception" title="' + results.error + '">error returned</a>';
                test.cell.className += ' exception';
                test.cell.found = 0;
                test.cell.error = true;
            } else {
                test.cell.found = results.found;
                test.cell.error = false;
            }

            scoreNum[test.name] += test.cell.speed;
            scoreTds[test.name].innerHTML =  ' ' + scoreNum[test.name] + ' ';

            if (test.cell == test.row.lastChild) colourRow(test.row);
            timeoutId = setTimeout(testRunner, 300);
        };
        //为Tbody的行着色
        var colourRow = function(row){
            var cells = row.cells

            var speeds = [];//用于存在速度
            dom.each(cells,function(cell,i){
                speeds[i] = cell.error ?  9999999999 : ~~cell.speed;
            });

            var min = Math.min.apply({}, speeds);
            var max = Math.max.apply({}, speeds);     
            var consistency = true;
            var found = [];
            dom.each(cells, function(cell, i){
                if (!cell.error && "found" in cell ){
                    found.push(cell.found);
                    var length = found.length;
                    if(length > 2 &&  found[length-2] !==  found[1-1] ){
                        return  (consistency = false);
                    }
                }
                if (cell.speed == min) cell.className += ' good';
                else if (cell.speed == max) cell.className += ' bad';
                else cell.className += ' normal';
            });

            if (!consistency){//如果各个框架取得的结果不一致,则全部
                dom.each(cells, function(cell){
                    if (cell.found != undefined) cell.className += ' mismatch';
                });
            }
        };
        dom.addEvent(startTest,"click",testRunner);
        dom.addEvent(stopTest,"click",function(){
            clearTimeout(timeoutId);
            timeoutId = null;
        });
       
        
    }
}).call(this);

index.html



    
        
        QuerySpeed~选择器测试速工具
        
        
    
    
        

QuerySpeed

正在准备中………………

QuerySpeed为著名的选择器测速工具SlickSpeed的javascript版本。

测试页面为 此页面的拷贝。

注释

发生异常 结果不一致

template.html的javascript部分

                  
            var params = document.location.search.slice(1).split('&'), i = 0,pair, queryFnStr
            while((pair = params[i++])){
                if(pair.indexOf("include")!==-1){
                    document.write('<script type="text/javascript" src="frameworks/'+pair.replace("include=","")+'"></sc'+'ript>')
                }
                if(pair.indexOf("function")!==-1){
                    queryFnStr = pair.replace("function=","")
                }

            }
            window.test = function(selector){
                try {
                    var start = new Date() - 0
                    var queryFn = arguments.callee.queryFn;
                    var nodes = queryFn(selector);
                    var time = new Date - start;
                    return {'time': time, 'found': nodes.length};
                } catch(err){
                    return {'time': time||1, 'found': -1, 'error': err};
                }
            };
            (function(){
                try{
                    var queryFn = eval("window."+queryFnStr);
                    //   window.console.log(queryFnStr+"准备好了")
                    queryFn("body")
                    test.queryFn = queryFn;
                }catch(e){
                    setTimeout(arguments.callee,64)
                }
            })();

            window.onload = function(){
                window.parent.dom.numberOfIframe++;
                window.parent.dom.hasReady();
            }
          

posted on 2011-01-04 23:10  司徒正美  阅读(987)  评论(1编辑  收藏  举报