2011-06-24 9 views
3

私は状況がある、私はユーザーがキーを押すたびに20kのレジスタのギザギザの配列を処理する必要があります。私はグリッドを持っていて、ユーザーが入力している間に、システムはグリッド内でフィルタリングされた結果を表示します。そう。だから私はすべての20kのレジスタでいっぱいにギザギザの配列を持っている。私はリスト(コントロールのグローバル)を持っていて、ユーザーがキーを押してフィルタリングされたレジスタだけを埋めるたびにグリッドに表示されるたびにクリーンアップされます。ここでメモリパフォーマンスとスピードアップ

はコード

the model 
public struct PlayerLookUpAdapter 
    { 
     [Browsable(false)] 
     public decimal Id { get; set; } 
     [DisplayName("Número")] 
     public String Number { get; set; } 
     [DisplayName("Nombre")] 
     public String Name { get; set; } 
     [DisplayName("Apellido")] 
     public String Surname { get; set; } 
     [DisplayName("DNI")] 
     public String Document { get; set; } 
     [DisplayName("Estado")] 
     public String Status { get; set; } 
    } 

private PlayerLookUpAdapter[] _source; // here are the 20k registers 

List<PlayerLookUpAdapter> filteredOut = new List<PlayerLookUpAdapter>(); // here the filtered ones 

// this code is executed every time the user press a key 
private void tb_nro_KeyUp(object sender, KeyEventArgs e) 
     { 
      if (!(e.KeyCode.Equals(Keys.Enter) || e.KeyCode.Equals(Keys.Down)) && _source!=null) 
      { 
       String text = tb_nro.Text.ToUpper(); 
       if (String.IsNullOrEmpty(text)) 
       { 
        fg.DataSource = _source; 
        fg.Refresh(); 
        return; 
       } 
       fg.DataSource = null; 
       filteredOut.Clear(); 
       int length = _source.Length; 
       for (int i = 0; i < length; i++) 
       { 
        PlayerLookUpAdapter cur = _source[i]; 
        if (cur.Number.ToUpper().StartsWith(text) || cur.Surname.ToUpper().StartsWith(text) || cur.Name.ToUpper().StartsWith(text)) 
         filteredOut.Add(cur); 
       } 
       fg.DataSource = filteredOut; 
       SetGridColumnsProperties(); 
       fg.Refresh(); 

      } 
      else 
      { 
       fg.Focus(); 
      } 
     } 

それはメモリ使用量とパフォーマンスの面で良い解決策はありますか?助言がありますか?どのようにしてより多くのスピードを得ることができますそれは本当にうまくいくが、20kの代わりに100kのレジスタがあればどうなるのだろうか?

ありがとうございます。

+1

'しかし、私が代わりに20Kの100Kのレジスタを得た場合について' - あなたは私たちよりも、それを試してみるためにはるかに良い位置にありますあります。 – sehe

+0

20kではなく100kのレジスタはどれくらいありますか? –

+0

ユーザーは100,000の選択肢のリストを掘り起こすのが好きではありません。結果セット*をフィルタリングする前に*フィルタリングしてください。一度に10件しか表示されません。 –

答えて

3

私は、これは木を使用するための典型的な例であるべきだと思います。

ツリーにデータを配置すると(実際にはC#/ .Netがツリーデータ構造をサポートしているかどうかわからないか、自分で手を汚してしまいます)。あなたがツリー内で検索

速度は、アレイ内の検索用の比較で増加します(O(N)= N *ログ(N)のようなsomehtingのツリーGOTSため、検索スピード)

論簡単です:ユーザがリテラル内でタイプすると、ツリーはこのリテラルで始まるノードに行きます。このノード上では他のすべてのノードなどが可能です。例えば:ユーザは "t"ノードに "t"ノードを、 "t"ノードに行くと "e"をタイプし、 "test"のような他のサブノードがあり、システムはこれらのサブノードをユーザに提案する。

+0

バックグラウンドスレッドのデータをフィルタリングするコードをいくつか追加して、キー入力がすぐに戻り、ユーザーが入力を続けるようにします。また、100ms後にフィルタリングを開始するだけで、ユーザーがいくつかの文字を入力できるようになります。 – CodingBarfield

0

ToUpper()コールを事前に計算してください。毎回行う必要はありません。すべての文字列が大文字で格納されている2番目のリストを保持することができます。

さらに、検索文字列にが追加された場合は、フィルタリングされたリスト(リスト全体ではなく)を検索する必要があります。新しい(より長い)文字列はフィルタリングされた結果の外に出ることはありません。

1

あなたのコードを少し改善することができます:StartWithメソッドには、文字列比較も同様に行うオーバーロードがあります。あなたは "OrdinalIgnoreCase"としてすべての文字列を上にすることを避けるためにそれを設定することができますが、私はあなたが多くを得るとは思わない。 検索を高速化する唯一の方法は、Lucene.netという検索エンジンになります。

http://www.codeproject.com/KB/library/IntroducingLucene.aspx

0

文字列の比較にStringComparison.OrdinalIgnoreCaseオプションを使用して、すべての文字列に20,000回までToUpperを呼び出さなくてもかまいません。

理想的には、まず、プログラムの一般的な使用状況に関する最善の見積もりに基づいて、どの程度遅いかを判断する必要があります。すべての後にpremature optimisation is the root of all evil

関連する問題