ども、Norimakiです。
今回は開発関係のお話です。
現在開発中のツールでサイトマネージャ的なものがあるんですが、
フィルタリングのスピードが遅いという問題点が発覚しました。
とにもかくにも、現実を見た方が早いということで、
遅いコードはこちら。
for s in FParent.FKVSData.Keys do begin if FFilteredList.IndexOf(s.Row)=-1 then FFilteredList.Add(s.Row); end;
FKVSDataはTDictionary、FFilteredListはTListです。
sはレコード型で、
TNYKVSIndex=Record Index:integer; Row :integer; end;
こんな感じで定義されています。
やっていることは簡単で、FKVSDataのキーTNYKVSIndex型のRowを抽出して、
同じものがないようにFFilteredListに追加していくということをやっています。
FKVSDataのキーはエクセルのセルと同様に考えてもらって構いません。
縦(Row)と横(Index)でキーを構成します。
目的は行数を知ることと、どのRowが存在するかをチェックすることです。
RowはRowと言いながら連続しているとは限らず抜けもあります。
という前提でデータの数はRowのMAXが1271、IndexのMAXが35とします。
なので、計44485個のデータをチェックすることになります。
この状況で先ほどのコードを実行すると、
ウチの環境では、およそ300ミリ秒かかります。
0.3秒です。
0.3秒と聞くとそこそこ早い気もするんですが意外にワンテンポ遅れて感じます。
で、これをTDictionaryを使って書き換えてみます。
var Rt:TNYKVSIndex; Dt:TDictionary<integer,integer>; begin Dt:=TDictionary<integer,integer>.Create; try FFilteredList.Clear; for Rt in FKVSData.Keys do begin if Dt.ContainsKey(Rt.Row) then continue; Dt.Add(Rt.Row,0); FFilteredList.Add(Rt.Row); end; finally FreeAndNil(Dt); end;
こんな感じ。
さっきと微妙に違いますが、そこはご愛嬌。
TDictionaryのValueが無意味と言われそうなんですが、とりあえず。
で、実際の速度を計測すると。
7ミリ秒。
はえーよ。43倍の速さって.....。
たった4万5000程度のデータチェックでこれだけの差が出てしまうわけですが、
実際のデータ運用に関しては、4万5000以上は必要になってくるはずで、
それを考えると、最初のコードを採用するわけにはいかないと。
そういうことになります。
まぁ、今回は速度以外のコストを度外視しているので、
これでいいのかどうかは分かりませんが、
速度を求めるのであればこんなやり方もアリなのかなと。
そう思った次第です。
ではでは。
Norimakiでした。