-1

JSON データ (200Mega) で操作を実行する JavaScript プログラムがあります。このプログラムは、regxp によってデータ内のオカレンスを検索します。

var myDatas = [
 { "id" : "0000000001",
   "title" :"Data1",
   "info": {
             "info1": "data data data",
             "info2": "infoinfoiinfoinfo",
             "info3": "info333333333",
             "miscellaneous": "",
             "other": [
                 {"title": "qwe", "ref": "other"},
                 {"title": "sdsd", "ref": "other"},
                 {"title": "ddd", "ref": "123"} 
             ]
           },
    "text": "xxxx text sldjdjskldj text text" },
 . . . ];

実際の実行は遅すぎます。

私は html 5 の Worker を使用しますが、IE9 ではサポートされていません。

私のプログラム:

    iterObject : function(obj){

        var text = $('#search-input').val() //text to search

        var self = this
        $.each(obj, function(key, value) {
            if((typeof value) == 'object'){
                self.iterObject(value)
            }
            else{
                 self.Search(text, value)
              }
          }
      }

Search : function(item, text){

        var regexThisFragment =
                          new RegExp("[^a-zA-Z0-9]+.{0,40}[^a-zA-Z]+" + 
                          item + 
                          "[^a-zA-Z]+.{0,40}[^a-zA-Z0-9]+", "i")

        while(text.match(regexThisFragment) != null)
        {
            var fragment = text.match(regexThisFragment).toString()
            console.log(fragment );
            }
        }
},

プログラムを改善するにはどうすればよいですか?

4

2 に答える 2

1

処理中に UI がフリーズすることが問題の場合は、処理を非同期で処理されるチャンクに分割できます。これにより、UI がユーザーに応答できるようになります。

var i = 0,
    chunkSize = 10, // This is how many to process at a time
    duration = 30;  // This is the duration used for the setTimeout

(function process() {
    // process this chunk
    var chunk = myDatas.slice(i, i += chunkSize);

    // do the next chunk
    if (i < myDatas.length)
        setTimeout(process, duration);
})();

chunkSizeとは必要に応じて微調整できdurationます。

問題が実際のコードのパフォーマンスを向上させることである場合は、いくつかのコードを表示する必要があります。

于 2012-11-15T15:03:08.787 に答える
1

user1689607 が投稿した回答は興味深いものですが、使用setTimoutするとコードが非同期に実行されません。メイン アプリケーションと同じスレッドで実行されます。タイマーを使用する上でさらに興味深いのは、アプリケーションの他の部分では、タイマーの実行中にいくらかの処理時間を利用できることです。

アプリケーションを低速/高速デバイスで正常に動作させる最善の方法は、処理時間と「リリース」時間を選択することです。また、データの処理には時間がかかる場合があるため、キャンセルできるようにする必要があります。そして、コールバックを使用してプロセスの終了を処理します。

コードは次のようになります。

var DataProcessor = {
     dataProcessDuration : 30,
     releaseDuration : 5,
     dataProcessedCallback : function() { 
                //... somehow notify the application the result is available
                                       },
     _currentIndex : 0,
     _processing : false,
     _shouldCancel : false,
     processData : function() 
                              {   this.cancelProcessing();
                                  this._currentIndex =0;
                                  this._processing = true;
                                  // launch data process now, or give it time to cancel
                                  if (!this._shouldCancel)  this._processData();
                                  else setTimeout(this._processData.bind(this), 
                                            this.releaseDuration+this.dataProcessDuration+1);
                               },
     cancelProcessing : function() 
                               { 
                                     if (!this._processing) return;
                                     this._shouldCancel=true;
                               },
     _processData : function() {
          if (this._shouldCancel) { this._shouldCancel = false ;  
                                    this._processing = false; 
                                    return; }
           var startTime = Date.now();
           // while there's data and processing time  left.
           while  ( ( this._currentIndex < length of data)
                       && (Date.now()-startTime < this.dataProcessDuration) )
                {    var thisBatchCount=10;
                     while (thisBatchCount--)
                           {  
                              // ... process the this._currentIndex part of the data
                             this._currentIndex++;
                             if ( this._currentIndex == length of data) break;
                            }
                }
           if (this._currentIndex == (length of data) ) // the end ?
                {     this._processing = false; 
                      this.dataProcessedCallback()
                 }
           else // keep on processing after a release time
                setTimeout(this._processData.bind(this), this.releaseDuration);
                           }
}

Rq : メイン プロセス ループでは、thisBatchCount を変更して粒度を微調整することができます。小さすぎると Date.now() を過剰にチェックして時間を無駄にし、大きすぎると内部処理に時間がかかりすぎて、選択したプロセス/リリース比率が得られなくなります。

于 2012-11-15T17:27:52.423 に答える