2010年8月31日 星期二

Javascript Unzip Testing

前陣子一直在調校 Javascript & Unzip 的事情,找到一個滿貼切工作的 -- Booktorious ,並且開始修改它。只是再怎樣地修改,在 Mobile Device 都不太適用,也被提醒會不會挑到的程式沒有實做很好,這部份我有留意它 unzip 的部份,的確存在不少可以精進的地方,當我準備要改得時候,我又看到了 rePublish 裡頭用的 zip 其實就已經接近我要改善的方式,因此筆記一下比較的過程,之後有空再慢慢增加其他對應的 library。


整個過程,看起來有點線性的成長,隨著檔案大小的增加,解壓縮的時間也會接近倍數成長。而 Booktorious 之 js-unzip 裡頭,有用到大量的資料複製,所以時間上花費會更多,相對於 rePublish 之 zip 的使用,對於 raw data 採用紀錄 offset 的方式,因此比 Booktorious 更加接近線性關係。


函式庫:



測資(純粹看 size 關係而非內容或檔案數目):



@ AMD X4 955, Ubuntu 10.04 i386, DDR3-1333 4GB, Google Chrome 6.0.495.0 dev


91KB


0.034s @ [js-zip & js-inflate]
0.026s @ [zip & inflate]


929KB


0.302s @ [js-zip & js-inflate]
0.139s @ [zip & inflate]


9.2MB


14.945s @ [js-zip & js-inflate]
1.654s @ [zip & inflate]


@ iPad, iOS 3.2.2


91KB


2.182s @ [js-zip & js-inflate]

1.214s @ [zip & inflate]


929KB


JavaScript execution exceeded timeout @ [js-zip & js-inflate]

7.177s @ [zip & inflate]


9.2MB


JavaScript execution exceeded timeout @ [js-zip & js-inflate]
JavaScript execution exceeded timeout @ [zip & inflate]


@ iPhone 3G, iOS 4.0.2


91KB


8.438s @ [js-zip & js-inflate]
5.397s @ [zip & inflate]


929KB


JavaScript execution exceeded timeout @ [js-zip & js-inflate]
JavaScript execution exceeded timeout @ [zip & inflate]


9.2MB


JavaScript execution exceeded timeout @ [js-zip & js-inflate]
JavaScript execution exceeded timeout @ [zip & inflate]


以下是實驗的 Source Code,而測試中如果瀏覽器已經等很久甚至產生 timeout 的訊息時,試著一次只測試一個 library 吧,並且在 iPad 或 iPhone 也有機會碰到直接跳出 Safari 的情況


@index.html


<!DOCTYPE html>
<html xml:lang="utf-8" lang="utf-8" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <script type="text/javascript" src="js-unzip.js"></script>
        <script type="text/javascript" src="js-inflate.js"></script>
        <script type="text/javascript" src="zip.js"></script>
        <script type="text/javascript" src="inflate.js"></script>
    </head>
    <body>
<script language="Javascript">
    function report( s, clear )
    {
        var report = document.getElementById( 'report' );
        if( clear )
            while ( report.hasChildNodes() && report.childNodes.length >= 1 )
                report.removeChild( report.firstChild );
        if( s )
        {
            report.appendChild( document.createTextNode( s ) );
            report.appendChild( document.createElement( 'br' ) );
        }
    }
    function doZip( epub , choose )
    {
        var path = epub || "epub/91kb.epub";
        var ajReq = new XMLHttpRequest();
 
        try{
            ajReq.open( 'GET' , path , false );
            ajReq.overrideMimeType( 'text/plain; charset=x-user-defined' );
            ajReq.send(null);
            ajReq.overrideMimeType( 'text/plain; charset=UTF-8' );
 
            var out = ajReq.responseText || '' ;
            var out_array = [];
            for( var i=0, len=out.length, scc=String.fromCharCode ; i<len ; ++i )
                out_array[i] = scc( out.charCodeAt(i) & 0xff );
            var out_binary = out_array.join( '' );
 
            if( out_binary !== '' )
            {
                var cost ;
                var unzipper;
 
                report( null, true );
 
                //
                // js-unzip & js-inflate
                //
                if( !choose || choose === 1 )
                {
                    unzipper = null;
                    cost = new Date();
                    unzipper = new JSUnzip( out_binary );
                    if( unzipper.isZipFile() )
                    {
                        unzipper.readEntries();
                        for (var i = 0 , len = unzipper.entries.length; i < len ; i++)
                        {
                            if ( unzipper.entries[i].compressionMethod === 0)
                                ; // unzipper.entries[i].data
                            else if ( unzipper.entries[i].compressionMethod === 8)
                                JSInflate.inflate( unzipper.entries[i].data );
                        }
                    }
                    cost = new Date() - cost ;
                    report( (cost / 1000.0) + 's' + ' @ [js-zip & js-inflate]' );
                }
 
                //
                // zip & inflate
                //
                if( !choose || choose === 2 )
                {
                    unzipper = null;
                    cost = new Date();
                    unzipper = Zip;
                    unzipper.Archive( out_binary );
                    for (var i = 0 , len = unzipper.entries.length; i < len ; i++)
                        unzipper.entries[i].content();
                    cost = new Date() - cost ;
                    report( (cost / 1000.0) + 's' + ' @ [zip & inflate]' );
                }
            }            
 
        }catch( err ){
 
            alert( 'Error:' + err );
 
        }
    }
</script>
        <dl>
            <dt>Do all</dt>
            <dd><button onclick="doZip( 'epub/91kb.epub' );">Unzip 91KB</button></dd>
            <dd><button onclick="doZip( 'epub/929kb.epub' );">Unzip 929kB</button></dd>
            <dd><button onclick="doZip( 'epub/9.2mb.epub' );">Unzip 9.2MB</button></dd>
        </dl>
        <dl>
            <dt>Use Booktorious</dt>
            <dd><button onclick="doZip( 'epub/91kb.epub' , 1 );">Unzip 91KB</button></dd>
            <dd><button onclick="doZip( 'epub/929kb.epub' , 1 );">Unzip 929kB</button></dd>
            <dd><button onclick="doZip( 'epub/9.2mb.epub' , 1 );">Unzip 9.2MB</button></dd>
        </dl>
                    
        <dl>
            <dt>Use rePublish</dt>
            <dd><button onclick="doZip( 'epub/91kb.epub' , 2 );">Unzip 91KB</button></dd>
            <dd><button onclick="doZip( 'epub/929kb.epub' , 2 );">Unzip 929kB</button></dd>
            <dd><button onclick="doZip( 'epub/9.2mb.epub' , 2 );">Unzip 9.2MB</button></dd>
        </dl>
        <p id="report"></p>
    </body>
</html>


沒有留言:

張貼留言