[リストへもどる]
一括表示

投稿時間:2004/03/04(Thu) 13:02
投稿者名:Eclipse
Eメール:
URL :
タイトル:
リストボックスへの高速追加
リストボックスに大量のデータを追加する場合、どうしても動作が鈍くなります。

List1.Visible = False や SendMessage(API)を使って画面に表示しないようにはしていますが、
どうしてもやはり追加処理が遅いです。(GetTickCountで計測すると3秒くらいかかっている)

1.  List1.AddItem アイテム

2.  List1.List(i) = アイテム
   i = i + 1

を比べてみたりしても、一部の端末では何故か効果がありましたが(CPUのせい?)
やはり根本的な解決にはなりませんでした。

やはりプログラムの高速化は大切なことなので、解決策をご存知の方ご教授くださいませ。

投稿時間:2004/03/04(Thu) 13:10
投稿者名:non-a-Me
Eメール:
URL :
タイトル:
Re: リストボックスへの高速追加
#丸付き数字はネットでは控えましょう!

> リストボックスに大量のデータを追加する場合、どうしても動作が鈍くなります。

List1へ追加する大元のデータはどこから集めているのでしょうか?
そこは遅くなく、ListBoxにAddItemで追加するところが遅い、
ということは調査してはっきりさせているのでしょうか?

> List1.Visible = False や SendMessage(API)を使って画面に表示しないようにはしていますが、

SendMessageを使って何のメッセージを送っているのですか?

> どうしてもやはり追加処理が遅いです。(GetTickCountで計測すると3秒くらいかかっている)

純粋にListBoxにAddItemしているだけなんでしょうか?
何件のデータでどういうスペックのマシンで3秒なんでしょうか?
#3秒とだけ言われても、その値がしょうがないものなのか、コード上の問題なのかも判断できません。

> やはりプログラムの高速化は大切なことなので、解決策をご存知の方ご教授くださいませ。

現在のコードはどんなコードを書かれているのですか?

純粋にAddItemしているだけであれば、それ以上はどうしようもないような・・・
一度に追加する項目数を制限しましょう。

投稿時間:2004/03/04(Thu) 14:13
投稿者名:Eclipse
Eメール:
URL :
タイトル:
Re^2: リストボックスへの高速追加
> List1へ追加する大元のデータはどこから集めているのでしょうか?
ただのテキストファイルです。

> そこは遅くなく、ListBoxにAddItemで追加するところが遅い、
> ということは調査してはっきりさせているのでしょうか?
はっきりしているので質問しているのですが...
  
> SendMessageを使って何のメッセージを送っているのですか?
SendMessage(List1.hWnd, WM_SETREDRAW, 0, ByVal &H0) '画面の更新を停止
SendMessage(List1.hWnd, WM_SETREDRAW, 0, ByVal &H0) '画面の更新を再開
結局、List1.Visible = False にしているので意味はないのですが。

> 純粋にListBoxにAddItemしているだけなんでしょうか?
そうですね、あまり余計なことをするのは処理が遅くなる原因となるので。

> 何件のデータでどういうスペックのマシンで3秒なんでしょうか?
スペック:CPU=Pen4 1.8GHz, MEMORY=512MB, HDD=空き容量十分
まあ、スペックのせいで遅いわけではないですね。
件数は23,000件くらいですね。
ちなみに、投稿する前に色々調べてみましたが、
追加速度は、件数というより1件あたりの文字数の方に左右されるようです。
文字数は、ばらつきがありますが、全角25文字くらいでしょうか。

> 現在のコードはどんなコードを書かれているのですか?
> 純粋にAddItemしているだけであれば、それ以上はどうしようもないような・・・
> 一度に追加する項目数を制限しましょう。
私の職業はプログラマで、C出身者なのですが。VBは始めたばかりなのです。
投稿する以上、最低限やるべきこと(自分なりの調査)は、やっています。(最低限の礼儀ですが)
そのため、自分の中で考えがまとまりすぎていて、ここへ書き込む内容も要約されすぎていたようです。
ご迷惑をおかけしました。

どんな方法で今やっているかと言うと、

「C++でテキストファイルを読み込むDLLを作って、高速に絞込み検索してその結果をVBへ返す」

その前にVBだけで色々やったのですが、これが1番早かったです。

このDLLは0.2秒くらいでVBへ結果を返してくれています。
やはり、VBの「AddItemメソッドが遅すぎ」としか思えません。
ですから、ListBoxに高速にデータを追加する方法についてだけお聞きしたのです。
説明不足で申し訳ありませんでした。

やはりしょうがなさそうですね。
件数を絞り込むわけにはいかないので、このまま導入します。(まあ3秒が限界だと結論)
ありがとうございました。

> #丸付き数字はネットでは控えましょう!
最近は「文字化け」とは無縁なので、普通に使ってしまいました。
こういう場所では控えるようにします。申し訳ありませんでした。

> 題名も変えないほうがいいでしょう
では、修正しておきます。

投稿時間:2004/03/04(Thu) 15:18
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: リストボックスへの高速追加
遅い、早いは気分的なものや見た目でも左右されますので、
私は、プログラム起動時にリストボックスに読み込んでおくとか
最初の数件は表示させて、後は非表示で読み込む等の方法をとって
おります。
又、場合によっては MSHFlexGrid 等を使ってみるとか。

投稿時間:2004/03/04(Thu) 17:33
投稿者名:Eclipse
Eメール:
URL :
タイトル:
Re^2: リストボックスへの高速追加
> 遅い、早いは気分的なものや見た目でも左右されますので、
確かに、時間が消費するとわかりきっている場合は、
プログレスバーで誤魔化したりするもんですが。
今回は、2,3秒の話ですから、逆に割り切れないことがあります。

> 私は、プログラム起動時にリストボックスに読み込んでおくとか
> 最初の数件は表示させて、後は非表示で読み込む等の方法をとっております。
MSDNで検索したところ同じ様なテクニックが書いてありました。
そこに辿り着く前にバックグラウンドで、少し作業をしておくのは今回はムリです。
その画面で[検索]ボタンを押下することで集計するので。

> 又、場合によっては MSHFlexGrid 等を使ってみるとか。
これは大変興味深いです。
私は、MSFLEXGRIDしか使用したことがありません。
ですので、MSHFLEXGRIDがMSFLEXGRIDとどう違うのかわかりません。
何故、MSHFLEXGRIDを使うと改善する可能性があるのか教えていただけませんでしょうか?

投稿時間:2004/03/04(Thu) 18:51
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: リストボックスへの高速追加
> 私は、MSFLEXGRIDしか使用したことがありません。
> ですので、MSHFLEXGRIDがMSFLEXGRIDとどう違うのかわかりません。
> 何故、MSHFLEXGRIDを使うと改善する可能性があるのか教えていただけませんでしょうか?

基本的にはMSFlexGrid と変りはないと思うのですが35万セルの制限もないし、ADOが使用
できますので読み込み処理から表示までの一貫した処理が早くできます。
以前2つのファイルの違いを調べて結果を表示するといった処理で掲示板に投稿がありテスト
した結果ではMSHFlexGrid + ADO が一番早かったです。
ただ、今回の場合も早くなるかは試して見ないと判りませんが。

http://www.bcap.co.jp/hanafusa/logbbs/wforum.cgi?mode=allread&no=3487
http://www.bcap.co.jp/hanafusa/logbbs/wforum.cgi?mode=allread&no=3623

投稿時間:2004/03/04(Thu) 20:15
投稿者名:Eclipse
Eメール:
URL :
タイトル:
Re^4: リストボックスへの高速追加
> 基本的にはMSFlexGrid と変りはないと思うのですが35万セルの制限もないし、ADOが使用
> できますので読み込み処理から表示までの一貫した処理が早くできます。
> 以前2つのファイルの違いを調べて結果を表示するといった処理で掲示板に投稿がありテスト
> した結果ではMSHFlexGrid + ADO が一番早かったです。
> ただ、今回の場合も早くなるかは試して見ないと判りませんが。

実際試してみましたが、やはり余計遅くなってしまいました。
参考までに、MSHFLEXGRIDのADOの他、DAOなども試してみましたが、
VBからのシーケンシャルモードでファイルオープンするより遅くなりました。
やはり、C++の自作DLLが1番早そうです。(やはり限界だと思われます)
ソースも単純明解なので、改良の余地もないです。(AddItemだけだし、List(Index)でやっても遅い)
C++からAddする方法でも探してみます。
VBは手軽で簡単かもしれませんが、処理速度とかを考慮したりすると正直つらいですね。
(まあ、言語にはそれぞれの特性があるのでしょうがないのですが)

参考までに:
端末によっては、コンボボックスでやったほうが早い場合と、
リストボックスでやった方が早い場合がありました。
さらに、List(i) = アイテムで i をインクリメントしながら追加した場合と、
純粋にList.AddItem = アイテムでやった場合の方が早い場合とありました。
CPUのせい?のような気もしますが(Pen4、Pen3、Celeronと結果が違っていたので)

ともかく、色々アドバイスして頂きありがとうございました。>花ちゃん様

投稿時間:2004/03/05(Fri) 12:36
投稿者名:Eclipse
Eメール:
URL :
タイトル:
【解決】リストボックスへの高速追加
> そちらのC++の自作DLLで抽出したデータをMsFlexGlidにTextMatrixプロパティを
> 使用して表示しても駄目でしょうか?
花ちゃん様から、指摘を頂いた際にやってみましたが、効果がありませんでした。
ただ、他の端末からだと、これも一定の効果がありました。

> 参考までにこちらの環境(PenV800 512MB)で23,000件のデータ(1件あたり50バイト)
> を表示するのにかかった時間は約0.3秒です。
端末の構成(CPU?)に左右されてしまうみたいです。
あくまで構成に左右されているだけでスペックの違いというわけではなさそうです。
別の端末でやったところ、表示するまで0.3秒でいけました。

結局導入先の構成によってより良い方法を使えば良いということです。
実機マシンでテストしたところ、ListBoxでも0.23秒で表示できたので解決としました。

# ついでに、実機マシンでVB単独の方法を色々ためしてみましたが、やはり遅いです。

投稿時間:2004/03/05(Fri) 09:11
投稿者名:K.J.K.
Eメール:akiya@koalanet.ne.jp
URL :
タイトル:
Re: リストボックスへの高速追加
UIに関する操作を単一スレッドで行う以上、それに対応して仕様を
決めるしかありません。

連続してAddItemを呼び出して、それが3秒もかかるというのなら、
1,一度に少しずつ追加し、それをTimerのイベントなどで繰り返す。
2,そもそも、それだけ大量のデータを入れたら、ListBoxとして
  使いにくいから、根本的に仕様を見直す。
3,それほどの数ではないのに時間がかかる、という場合は、追加
  する文字列に問題がないか調べる。
のどれかになるでしょう。

3秒間というのは、UIとしては致命的なので、0.5秒程度以下で追加
できる量を見極めて、それぐらいの単位で繰り返して追加していく、
というのが無難な対応かも知れません。

ListBoxそのものは16Bits制限を受けます。ですが、その上限一杯
までデータを入れるようだと、かなり使い勝手が悪くなりますので、
その制限自体は特に問題がないと思われます。

また、VBのListBox(など標準コントロール)の特徴ですが、AddItem
などする場合、VBが、[UNICODE->Anis文字変換]し、その後に
SendMessageAを使います。この文字変換で時間がかかるケースも
存在します。元となる文字列に、変換されない文字が含まれて
いないかもチェックしてみると良いかも知れません。

投稿時間:2004/03/05(Fri) 12:47
投稿者名:Eclipse
Eメール:
URL :
タイトル:
【解決】リストボックスへの高速追加
> UIに関する操作を単一スレッドで行う以上、それに対応して仕様を
> 決めるしかありません。
> 連続してAddItemを呼び出して、それが3秒もかかるというのなら、
> 1,一度に少しずつ追加し、それをTimerのイベントなどで繰り返す。
> 2,そもそも、それだけ大量のデータを入れたら、ListBoxとして
>   使いにくいから、根本的に仕様を見直す。
我社のSEの頭自体に「脳内バグ」があっても仕様変更できない場合もあるわけでして(^^;A
PGは無理な仕様でも実現に向けて「努力」することが大事だと思っています。
(お金を貰っているのですから当然ですが)

> 3,それほどの数ではないのに時間がかかる、という場合は、追加
>   する文字列に問題がないか調べる。
> のどれかになるでしょう。
既出ですが、ちゃんと投稿する前にそれなりの調査をしています。(礼儀として)
(さすがに、あったら気付きます)

> 3秒間というのは、UIとしては致命的なので、0.5秒程度以下で追加
> できる量を見極めて、それぐらいの単位で繰り返して追加していく、
> というのが無難な対応かも知れません。
既出ですが、今回検索ダイアログの検索条件によって検索をかけるので、
少しずつというわけにはいきませんでした。

> ListBoxそのものは16Bits制限を受けます。ですが、その上限一杯
> までデータを入れるようだと、かなり使い勝手が悪くなりますので、
> その制限自体は特に問題がないと思われます。
そうなんですか、勉強になりました。

VBは手軽ですが、Cのように何でも単独で実現できるというわけではないと思います。
言語にはそれぞれの特性があるので、しょうがないと思います。(CはVBのように手軽じゃないし)
VBを簡単だとバカにするPGもいますが、限界を求めると以外に難しいと思います。
私もC++ばかりやっていたので、VBを今回始めてやって様々な驚きがありました。

色々と勉強になりました。
K.J.K.さん 花ちゃんさん akさん ありがとうございました。

投稿時間:2004/03/06(Sat) 01:43
投稿者名:K.J.K.
Eメール:akiya@koalanet.ne.jp
URL :
タイトル:
Re: 【解決】リストボックスへの高速追加
> PGは無理な仕様でも実現に向けて「努力」することが大事だと思っています。
> (お金を貰っているのですから当然ですが)

それでつき返されたら、また面倒ですし。

> VBは手軽ですが、Cのように何でも単独で実現できるというわけではないと思います。

どこまでをVBの範疇に含めるのか、にもよりますけれどもね。

で、今回の原因は、貴方が引用しなかった部分、
VBによる[Unicode<->Ansi文字列]にあるのではないか、と推測されます。
VBの文字列の内部保持形式はUNICODEである、という特徴を忘れている
と起こしがちなトラブルです。

API関数でListBoxに追加するのであれば、まずC++で作ったDLLから
VB側で受け取る段階で、文字列型ではなくByte型の配列を使って
受け取って下さい。
次にSendMessageで送る場合にも、このByte型の配列をそのまま利用
して送って下さい。

このようにすれば、ここでは余計とされる文字コード変換のプロセス
が抜けるのではないかと思われます。

投稿時間:2004/03/10(Wed) 10:53
投稿者名:Eclipse
Eメール:
URL :
タイトル:
【解決】リストボックスへの高速追加
> で、今回の原因は、貴方が引用しなかった部分、
> VBによる[Unicode<->Ansi文字列]にあるのではないか、と推測されます。
> VBの文字列の内部保持形式はUNICODEである、という特徴を忘れている
> と起こしがちなトラブルです。
残念ながら、今回の原因はそれではなかったようです。
(すいません。解決した後に書き込んだので、端折ってしまいました。
質問している身なので勝手に自己完結するのはよくなかったです。すいませんでした。)

解決はしていたのですが、興味を持って試してみましたが効果がありませんでした。
これまでの、DLL(BSTR)→VB(String)→そのままSendMessageというやり方が1番早いようです。
(しかし、これも何故かSendMessageではなくAddItemメソッドを使った方が早い端末も存在した)

> API関数でListBoxに追加するのであれば、まずC++で作ったDLLから
> VB側で受け取る段階で、文字列型ではなくByte型の配列を使って
> 受け取って下さい。
> 次にSendMessageで送る場合にも、このByte型の配列をそのまま利用
> して送って下さい。
DLL側でわけがわからんようになるので、会議にて却下されました。
(実際試してみたら、逆に遅くなってしまうこともあって)

> このようにすれば、ここでは余計とされる文字コード変換のプロセス
> が抜けるのではないかと思われます。
今回はそういうわけではなかったようです。
結局、原因はわからないのですが...。
私の開発マシンの構成に似ている端末で試すと、同様に遅くなることから、
スペックや環境うんぬんではなく、構成(CPU?)に左右されるようです。

今回のお客様での端末では、激速だったのでそのままで解決となりました。
(あまり釈然としないのですが...)
こんな事例もあるのだと、勉強にはなりました。

K.J.Kさん、貴重な意見ありがとうございました。

投稿時間:2004/03/10(Wed) 20:49
投稿者名:K.J.K.
Eメール:akiya@koalanet.ne.jp
URL :
タイトル:
Re: 【解決】リストボックスへの高速追加
> 解決はしていたのですが、興味を持って試してみましたが効果がありませんでした。
> これまでの、DLL(BSTR)→VB(String)→そのままSendMessageというやり方が1番早いようです。
> (しかし、これも何故かSendMessageではなくAddItemメソッドを使った方が早い端末も存在した)

DLLの中身ではどういう処理をしているのでしょうか?
具体的には、DLL内部での文字列処理はAnsi? Unicode? また、領域確保や
その解放の手段は? ちなみに、最初からUnicodeになっている場合は、
私が提示した方法は効き目がありません。

> DLL側でわけがわからんようになるので、会議にて却下されました。
> (実際試してみたら、逆に遅くなってしまうこともあって)

Ansi文字列を通して使っている場合は、遅くなる、ということは
まずありません。

ところで、この件に関して何度か書いてて非常に気になることがあります。
まず、具体的なコードが書かれていないことです。DLLとVB側との間で、
どういう形でやりとりしているのかが全くわかりません。また、
ListBoxにAddItemなどするときも、どんなタイミングでどこから
受け取ったデータをどのように追加するのかもわかりません。
SendMessageの一文を載せただけでは、十分な判断材料にはなりません。

こういう質問の仕方をすると、よほど運がよくない限り、まず有効な
解決策が提示されることはありません。判断材料が足りないので、
不適切な意見ばかりが出ることになりますので。

投稿時間:2004/03/05(Fri) 15:25
投稿者名:non-a-Me
Eメール:
URL :
タイトル:
質問の仕方
about No.8247
> > 3,それほどの数ではないのに時間がかかる、という場合は、追加
> >   する文字列に問題がないか調べる。
> > のどれかになるでしょう。
> 既出ですが、ちゃんと投稿する前にそれなりの調査をしています。(礼儀として)
> (さすがに、あったら気付きます)

「調査」をするのは礼儀がどうのこうのという話ではなく、自分のためにやることではありませんか?
投稿された案に対して、「そんなことは聞いていない」みたいな態度はいただけないと思います。
#そういう意図で書かれたわけではないのでしょうけれど、文章からそういう態度がにじみでています。

#例えば、
#・「既出ですが、」(説明不十分なのであなたの投稿を読んでいる側からすれば既出ではないんですけど・・・)
#・(さすがに、あったら気付きます)
#等ににじみでてます。

私の投稿もそうですが、「あなたが調査していない」と決め付けて発言しているわけではなく、
「何をどう調査したのか」の詳細な情報を提供されていないので、
私が書いたようにあなたの抱える問題の現状を把握するためにいろいろな聞き返しをしたり、
あるいは、皆さんが自分の経験から思いつく限りのいろんな可能性を上げられているだけかと思います。

#about No.8210
#>>List1.Visible = False や SendMessage(API)を使って画面に表示しないようにはしていますが、
#>>どうしてもやはり追加処理が遅いです。(GetTickCountで計測すると3秒くらいかかっている)

#この文章あたりで『何をどう調査したのか」の詳細な情報を提供』したと主張されるかもしれませんが、
#この説明では不十分でした。

about No.8213
>> そこは遅くなく、ListBoxにAddItemで追加するところが遅い、
>> ということは調査してはっきりさせているのでしょうか?
>はっきりしているので質問しているのですが...

あなたの投稿からは「はっきり」していなかったから聞き返したのです。

about No.8213
>> 純粋にListBoxにAddItemしているだけなんでしょうか?
>そうですね、あまり余計なことをするのは処理が遅くなる原因となるので。

私の質問に対して「感想」ではなく、実際のコードを提示して欲しかったです。

No.8213の投稿文のこの辺を読んだあたりで放置を決めていたのですが、
あんまりな質問の仕方なので書き込みします。

技術系メーリングリストで質問するときのパターン・ランゲージ
http://www.hyuki.com/writing/techask.html

投稿時間:2004/03/10(Wed) 11:26
投稿者名:Eclipse
Eメール:
URL :
タイトル:
Re: 質問の仕方

今回、この掲示板を初めて利用致しました。
これまで、何回か他のC,C++関係で掲示板を利用したことがあったのですが、
そこでは説明をだらだら書いたり、コードを貼り付けるのが厳禁ってわけではないのですが、
まあ、嫌われる掲示板(名前出してないけど、バレてしまいそう・・・)だったのです。
どこまで調査したのかも、あまり書かない(

しかし、普通に考えればわかる話でここはVB関係の掲示板なので、
ソースを掲示したりするべきだったと思っております。
ただ、今回は「VB側はアイテムを追加するだけなので必要なし」と「C++のコードはここでは意味がない」
と勝手に決め付け口頭だけのような説明(しかもそれも説明不足だった)をしてしまいました。

さらに、納期などのこちらの事情(勝手な事情ですが)もあったので、
正直焦っていて、説明を要約した「つもり」でいたのだと思います。
そういうこともあって、

> #そういう意図で書かれたわけではないのでしょうけれど、文章からそういう態度がにじみでています。
確かに、そういう意図で書いたわけではないですが、今、私自身読んでみても・・・最悪ですね。
礼儀だとか言っておいて、自分が礼儀をわきまえていない・・・。

そのため、大変、不愉快な思いをされたと思います。
許していただけないかもしれませんが、これ以降はこの掲示板を利用しないことを誓います。

管理人の花ちゃん様にもご迷惑おかけしました。

投稿時間:2004/03/10(Wed) 11:40
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
今後もご利用下さい
> そのため、大変、不愉快な思いをされたと思います。
> 許していただけないかもしれませんが、これ以降はこの掲示板を利用しないことを誓います。

皆さん決して怒っておられるのではありませんよ!
レスが早く付くように貴方の為を思ってあえて苦言を呈しておられるだけです。
ご理解頂けたのなら今後も多いにご利用願います。(回答の方もお願いします)