プログラムを実行するとリソースの空きが6%前後しか無くなってしまっていたため、使わなくなったフォームやグローバル変数をかなり削除してコンパイルしなおした所、逆にリソースの空きが1%になってしまいました。(他の部分は特に変更はしていません)
コンパイル環境も実行(テスト)環境も同じなのですが、リソースの消費はフォームの数や変数には因らないのでしょうか?どうすればメモリ不足を解消できるのでしょうか?
すいませんがこれだけでは、コメントのしようがありません。
因みに、メモリリソースの空きと言うのは、物理メモリ+仮想メモリの
合計量から、システムと起動しているアプリ等に占有されているメモリ
量を差し引いた残メモリ量のことを言っておられるのでyそうか?
何を持って残りが6%とか言っておられるのか・・・
EXEのサイズが小さくても、メモリを食いつぶすプログラムや、巨大な
EXEのサイズのプログラムでも、メモリを消費しないようなプログラム
も書けます。プログラム的構造や使っている機能、フォーム数や、各
フォームに張りつけられているコントロ−ルの数や種類・・・
それらが皆関係してきますので・・・
あと、環境は?OSの種類や使用言語のバージョンや・・・
何も解らないので・・・
以上。
情報が足りなくて申し訳ございませんでした。
開発環境はVB6.0で、Windows XPです。
テスト環境は、Windows Me(メモリ64MB)のPCです。
メインアプリから呼び出されるEXEなのですが、状況を分かり易くする為に単体起動した場合の状態でご説明しますと、テストPC(Me)でEXEを実行し、メインフォームのみ表示された状態(何も処理は始まっていません。メインフォーム以外はロードされていない・・・ハズです)で、デスクトップのマイコンピュータのプロパティを表示してリソース残量を確認したところ、残り17%と表示されました。(EXE起動前は83%でした)
そこで、使っていないフォームと使っていないグローバル変数を削除してコンパイルし直した所、EXEのサイズは400KBほど小さくなりましたが、同じ環境で実行し、リソース残量を表示したところ、10%になっていました。
単純にフォームと変数を減らしただけなのにリソースを喰ってしまうのです。VB6.0のコンパイル環境はプロジェクトのサイズによって動的に変化するような機能でもあるのでしょうか?
上記で説明いただいた検証手順では、不十分なような気がします。
まず、テスト環境のMeには、何かしらの常駐プログラムが動作していないでしょうか。
プログラムの中には、起動(常駐)しているだけで動的に使用リソースを変更するものがあります。
次に、Meの起動直後・状態が落ち着いたところでテストを開始されたでしょうか。
また、1回目と2回目以降のテストの間に何らかの形でリソースを使用するような操作を行っていないでしょうか。(たとえばエクスプローラを起動してアイコンを表示するだけでもリソースは消費されます。)
さらに、自作プログラムの起動直後の残リソース量のみに着目されているようですが、終了した時点で残リソース量は元に戻っているでしょうか。
私でしたら、まずMeの電源を入れるところから操作をまったく同じくし、1度のマシン起動ごとに自作プログラムの起動→終了を10回ほど繰り返し、起動前後・終了後の残リソース量を記録し、グラフ化します。
これを数回繰り返し、残リソース量以前に、リソースがどう消費されていくかの流れを見ようと思います。
その上で、明らかにリソースの消費量が増えているかどうかの判断をします。
たぶん、このくらいやらないと、他の方が追証比較できるデータにならないと思いますよ。
#単にコントロールの総使用量かEXE内部に埋め込んだアイコン・画像等のリソース量が多いだけのような気もしますが。
ご回答ありがとうございます。
ご指摘頂いた点について追加説明させていただきますと、
>テスト環境のMeには、何かしらの常駐プログラムが動作していないでしょうか。
テスト環境ではテストEXE以外は常駐の類も含め、起動していません。
>自作プログラムの起動直後の残リソース量のみに着目されているようですが、終了した時点で残リソース量は元に戻っているでしょうか。
確認方法なんですが、Me起動(リソース残り83%)→修正前のEXE起動(17%)→修正前のEXE終了(83%)→修正後のEXE起動(10%)→修正後のEXE終了(83%)→修正前のEXE起動(17%)・・・以下交互に繰り返し・・・Me終了
このような方法でMe再起動後もEXEの起動順序を入れ替えたりして何度もテストしたのですが、パーセントは±1%程度の誤差はありましたが、ほぼ一定でした。また、EXEをコンパイルし直しても同じでした。(P-Codeとネイティブコードどちらも試しましたが同じでした)
>単にコントロールの総使用量かEXE内部に埋め込んだアイコン・画像等のリソース量が多いだけのような気もしますが。
そうなんです。確かにフォームやコントロールは多いのですが、そう思ってフォームとグローバル変数を減らしたのですが・・・上記のとおりなんです。
他のOSはすぐに用意できないのでまだ試していないです。
>確かにフォームやコントロールは多いのですが、そう思ってフォームとグローバル変数を減らしたのですが
まだどういった情報を相手に伝えれば判断の基準になるか分かっておられないようですが、
『多い』とか『減らした』とか言ってもそれは NT さんの主観ですよね?具体的にフォームを
どのくらい用意してて、同時にメモリにロードされるフォームは幾つで、その上に乗ってる
コントロールは何が、幾つなのか?…客観的な判断ができる情報がないと話が進みません。
『減らした』…にしても何を?幾つ?どうやって?減らしたか(使用するフォームを減らした
とか言って同じフォームを使いまわすためにロードを繰り返してたりしないとも限らない)
NT さんにしか分かりません。もっと問題を単純になるように分解して具体的な調査を多く
行って下さい。…全然足りません。
グローバル変数は…先に指摘があるような画像などを扱っていなければ、それほど劇的に
変わるようにも思いませんが(ってゆーか変数宣言をちゃんとしてるならサイズは分かって
いるのでは?)…例えばソースコードを全て削除して、現在使用してるフォームのロード
のみ実行するアプリで調べてみるとか。…さらにフォームのロードを1つ1つ減らして
いって乗ってるコントロールの数を考慮に入れた上で、順調にフォームの数に比例して
使用リソースが減っていけば…仕方ないのかなぁ?という予想もつくと思います。
そこまできて初めて経験の豊富な方にご意見願うのです。単純に調べ方が足りません。
重ね重ねすみません。
プロジェクト全体では103個のフォームがあり、上記実験で『EXEを起動しただけの状態』というのは、MDIの親フォーム1つと、メインメニューの子フォーム1つ、合計2つのフォームがロードされた状態で比較しています。残りの101個のフォームはメインメニューから呼び出されて使うフォームですのでロードはされていません。フォームを減らしたというのは、残り101個中で、既にメニューからの呼び出しボタンすらなく使っていないフォームが4個あったので、プロジェクトから開放しました。
それだけなんですが・・・仰るとおり、まだ調べ方がたりないですね。もう少し自分で調べてみます。
最後に、一番知りたかった事なので、ここだけは教えて欲しいのですが、
>フォームのロードを1つ1つ減らしていって乗ってるコントロールの数を考慮に入れた上で、順調にフォームの数に比例して使用リソースが減っていけば…仕方ないのかなぁ?という予想もつくと思います。
フォームの数に比例して使用リソースが減っていく事を願っていたのですが、その逆になりました。「仕方ないのかなぁ?という予想」が意味するところは、調査を突き詰めていくと、フォームを減らしても逆にリソースを圧迫するという事実がある事に直面するかもしれないぞ、という事なのでしょうか?
…なんだろう…難しく考えすぎ?(^^;)物事はもっと単純だと思いますが…
>フォームを減らしても逆にリソースを圧迫するという事実がある事に直面するかもしれないぞ、という事なのでしょうか?
さぁ?そんな事が今の段階で予想つくんですか?じゃあ、その場合のリソースを
圧迫している原因は何?そう判断した理由は?まだ判断できる段階じゃないと
思いますが?…言っておきますが、
>MDIの親フォーム1つと、メインメニューの子フォーム1つ、合計2つの
>フォームがロードされた状態で比較しています。残りの101個のフォームは
>メインメニューから呼び出されて使うフォームですのでロードはされていません。
あたりも
>101個のフォームはメインメニューから呼び出されて使うフォーム
という仕様上、テストが完璧だったと思ってませんので。…十分な判断が
行える情報が集まっておらず、原因の予想範囲も
>EXEのサイズが小さくても、メモリを食いつぶすプログラムや、巨大な
>EXEのサイズのプログラムでも、メモリを消費しないようなプログラム
>も書けます。プログラム的構造や使っている機能、フォーム数や、各
>フォームに張りつけられているコントロ−ルの数や種類・・・
>それらが皆関係してきますので・・・
広いままの状況で、今は一つ一つ考えられる可能性を調べる段階です。
何か結論が得られると思ってるなら、ボクはその脳みその構造に大変
興味がありますので是非研究させて下さい。
質問であげたプログラムを使います。ソースを消すのでプロジェクト
ごとコピーしておいて下さい。メインフォームのコードを全て削除して下さい。
変数も関数も全てです。メインフォーム起動の EXE を作って実行して下さい。
リソース使用量を報告して下さい。更にメインフォーム上のコントロールを
全て削除して下さい。EXE を作って実行して下さい。リソース使用量を報告
して下さい。
プロジェクトにフォーム以外のオブジェクトはありますか?
モジュールとかクラス…はまぁ、いいか(汗) DataEnvironment とか?
他に原因があるような気がしてならないんですよね…
LoadもしないFormが100程度あったからといって、そんなに劇的にリソースを消費するような気がしないんです。
# 従って不要なFormを排除してもさほど改善されるとも思えず。
なにか他に主要因がある気がするんですが…
たとえばSpreadなどリソースを食いまくるコンポーネントなどを使っていて、今回期待している解決策とは関係ないからと説明から省いたりはしていないでしょうか。
お手数をおかけします。
確かにその通りです。残りの101個のフォーム内ではSpreadとかActiveToolBarなどたくさん使っています。ただ、MDI親フォームとメインフォームでは使っていなくて、その2フォームしかロードされていない状態でのテストだったので、他のフォームは一切ロードされていない=関係無いと思っておりました。
その辺りに私の認識違いがあるようですね・・・
なんか、質問のタイトルと実際にお聞きしたい内容が噛み合っていなくて申し訳ございません。
とりあえず、『Form1〜Form500が存在するアプリ』を作ってみました。
参照設定等も一切無し。コードも空です。
実際にロードされるのは、スタートアップにあるForm1だけです。
exeにコンパイルして実行してみましたが、
リソース消費量は微々たる物でしたよ。
私の環境は XP なので、比較にはならないでしょうけれども。
参考までに、実験用コードを書いておきます。。
1. [アドイン プロジェクト]を用意し、下記を frmAddIn.OKButton_Click に記述。
2. そのアドインプロジェクトを、デバッグ環境で実行。
3. 別途、VB6をもうひとつ起動し、[標準 EXE プロジェクト]を用意。
4. アドインメニューから、先ほどの MyAddIn を選択。
5. フォームが大量生成されるので、そのまま exe を作って終了。
'==== ====================================
Dim P As VBProject, W As Window
Dim L As Long
Set P = VBInstance.ActiveVBProject
For L = 1 To 500
P.VBComponents.Add vbext_ct_VBForm
For Each W In VBInstance.Windows
If W.Type = vbext_wt_Designer Or W.Type = vbext_wt_CodeWindow Then
W.Close
End If
Next
Next
> exeにコンパイルして実行してみましたが、
> リソース消費量は微々たる物でしたよ。
わー、やっぱり。
> 確かにその通りです。
> 残りの101個のフォーム内ではSpreadとかActiveToolBarなどたくさん使っています。
うわ、やっぱり?
えーと。
VBの拡張コントロールやサードパーティ製のコンポーネントは、標準コントロールとはまったく実装のされ方が異なります。
というか、コンポーネントごとにどんなふうに作られどう動作するのかは、ひとつずつ調べていかなければ本当のところはわかりません。
某帳票コントロールは、実際にはVB泊まった区無関係なところに独自の印刷エンジンを起動しておき、VBフォームに貼るコントロールはそのエンジンとの通信機能しか持たなかったりします。
ので、そのコントロールを貼ったフォームのインスタンスを2つ立ち上げて同時に印刷動作をさせると、1つのエンジンに2系統からの指示が混在し、ハングアップしたりしました。
上記の私のコメントで真っ先にSpreadを例に挙げたのは、私自身あまりにがメモリを食いすぎるので、私が担当したシステムで泣く泣く使用をあきらめたことのある思い出のあるコンポーネントだからです。多機能で使い出があるんですけどねぇ。
また、業務システムなど受注製造するシステムがSDIを採用することが多いのは、単機能のEXE(またはDLL)をメニューから呼ぶ構造にすることにより、瞬間メモリ消費量を最小に抑える(またはメモリ消費をなるべく意識せずに済ませる)というのが大きな理由のひとつです。
MDIのシステムにも参加したことがありますが、やはりメモリ消費が激しく、NT系(2000/XP)限定との条件が付いていました。(95系は動作未保証…つか現実動作しませんでした。)
残リソース量も、今回のシステムのような「VB以外」(拡張コントロールやコンポーネントは「VBではありません」)の部分の立ち居振る舞いを全部洗い出さない限り、その原因を突きとめることはできないように思います。
---
申し訳ありませんが、今回のNTさんのシステムは、なるべくしてなったリソース不足のような気がします。
デッドコードやデッドフォーム(?)を整理する程度では解決できる問題でもなさそうです。
今のままで動作環境をNT系に限るか、MDIをあきらめて単機能SDI EXEの集合にするか、拡張コンポーネントをいくつか間引くか。
この場合の「間引く」は「Spreadを使用するフォームを減らす」のではなく、「このシステムではSpreadを使わない」などという意味でです。
いずれにせよ、苦渋の選択になりそうですね…
単純にメモリーを増設すれば良いだけの話の様に思われ。
SDRAMだったらまだ中古で買えるよ。
ちょっとアクセスしないうちに、かなりのコメントがありましたネ!〜
まずシステムリソ−スの不足の問題としては・・・
http://support.microsoft.com/default.aspx?scid=kb;ja;882847
こちら参照。
搭載メモリを増やしても影響が無いので、WinMeを絶対に使う場合は、
プログラムの構造を変更するか、メモリリソースを食うコンポーネン
トを使うのをやめるか・・・
ですが、あくまで私的見解ですが、MDIで100個を超えると言うか、そ
こまで多くの子フォームを抱えるVBアプリが、正常に動作し続けるか
どうか・・・と思います。
次に御使いのActiveXコンポーネントですが、メモリリークを発生させ
る極悪なものも製品として販売され、流通していますので、その辺の
考慮も必要です。
以前、こちらの掲示板にも書きましたが、メモリ消費の原因になる機
能の使用箇所の特定やリーク箇所を特定するようなツールを使っての
デバッグも必要かと・・・日本コンピュウェアのサイトを見て下さい。
以上。
なるほど、フォームのロード状況だけでなく、サードパーティ製品の仕様も分析しないと今回問題とさせていただいた挙動の本当の解析はできないのですね。もっと根本的な問題もありそうですし・・・大変参考になりました。時間を割いていただいた皆様ありがとうございました。
>単純にメモリーを増設すれば良いだけの話の様に思われ
必ずNT系の環境で使っていただけるとは限らないので、98系の過酷な(?)環境でも試しているんです。