効率的なソフトウェアとは何ですか?効率的なソフトウェアは、同じ機能を実行するソフトウェアよりも高速に動作するだけでなく、消費するシステム リソースも少なくなければなりません。この記事では、ソフトウェア開発に VB を使用する際に著者が蓄積した経験の一部をまとめ、いくつかの簡単な例を使用して効率的な VB コードを作成する方法を示します。 VB プログラマーにとって非常に役立つテクニックがいくつか含まれています。始める前に、いくつかの概念を明確にさせてください。
コードをすぐに形にする: 私が接したプログラマーの中には、最初に機能要件に従ってコードを作成し、次にそれに基づいてコードを最適化することを好む人が多くいます。最終的に、最適化を達成するにはコードを書き直す必要があることがわかりました。したがって、コードを記述する前に最適化の問題を考慮することをお勧めします。
最適化の結果と必要な作業の関係を理解します。通常、コードの一部が完成したら、それを検査して変更する必要があります。コードを検査する過程で、一部のループのコード効率をさらに改善できることが見つかる場合があります。この場合、完璧を追求する多くのプログラマーはすぐにコードを変更する可能性があります。私の提案は、このコードを変更することでプログラムの実行時間が 1 秒短縮されるのであれば、変更してもよいということです。パフォーマンスが 10 ミリ秒程度しか向上しない場合は、変更は行われません。これは、コードを書き直すと必ず新しいエラーが発生し、新しいコードのデバッグにはある程度の時間がかかるためです。プログラマーはソフトウェアのパフォーマンスとソフトウェアの開発に必要な作業量との間のバランスを見つける必要がありますが、10 ミリ秒の違いはユーザーには理解できません。
オブジェクト指向メソッドを使用する必要がある場合は、オブジェクト指向メソッドを使用するようにしてください。VB が提供するメカニズムはオブジェクト指向の設計とコーディングを完全にはサポートしていませんが、VB は単純なクラスを提供します。ほとんどの人は、オブジェクトを使用するとコードの効率が低下すると考えています。この点については、個人的にはいくつかの意見があります。コードの効率は、実行速度の観点だけから評価することはできません。また、ソフトウェアが占有するリソースも考慮する必要があります。クラスを使用すると、ソフトウェアの全体的なパフォーマンスを向上させることができます。これについては、後の例で詳しく説明します。
VB コードを記述するときは、上記の点をコーディングの指針として原則として活用していただければ幸いです。この記事は、コードの実行速度を向上させる方法とコンパイルの最適化の 2 つの部分に分けました。
コードの実行を高速化する方法
次の方法は、コードの速度を向上させるのに役立ちます。
1. 整数 (Integer) と長整数 (Long) を使用します。
コードの実行を高速化する最も簡単な方法は、適切なデータ型を使用することです。信じられないかもしれませんが、正しいデータ型を選択すると、コードのパフォーマンスが大幅に向上します。 VB の Integer および Long の処理能力は他のデータ型よりもはるかに高いため、ほとんどの場合、プログラマは Single、Double、Currency 型の変数を Integer または Long 型の変数に置き換えることができます。
ほとんどの場合、プログラマが Single または Double を使用する理由は、小数点を保存できるためです。ただし、小数は整数型の変数に格納することもできます。たとえば、プログラム内で小数点以下 3 桁が合意されている場合は、Integer 変数に格納されている値を 1000 で割るだけで結果が得られます。私の経験では、Single、Double、Currency の代わりに Integer と Long を使用すると、コードはほぼ 10 倍高速に実行できます。
2. バリアントの使用を避ける
VB プログラマにとって、これは明らかです。バリアント型の変数はデータを保存するために 16 バイトのスペースを必要としますが、整数 (Integer) は 2 バイトしか必要としません。通常、バリアント型を使用する目的は、設計の作業負荷とコードの量を削減することです。プログラマによっては、トラブルを避けるためにバリアント型を使用することもあります。しかし、ソフトウェアが仕様に従って厳密に設計およびコーディングされている場合は、バリアント型の使用を完全に回避できます。
ちなみに、同じ問題は Object オブジェクトにも存在します。以下のコードを見てください。
mFSO
SetFSO=NewScripting.FileSystemObject
または
DimFSOasオブジェクト
SetFSO=NewScripting.FileSystemObject
上記のコードは宣言時にデータ型を指定していないため、代入中にメモリと CPU 時間が無駄になります。正しいコードは次のようになります。
DimFSOasNewFileSystemObject
3. 属性の使用を避けるようにしてください
日常的なコードで最も一般的な非効率なコードは、変数が使用できる場合、特にループ内でプロパティ (Property) を繰り返し使用することです。変数へのアクセス速度は属性へのアクセス速度の約 20 倍であることを知っておく必要があります。次のコードは、多くのプログラマーによってプログラムで使用されています。
DimintConasInteger
ForintCon=0toUbound(SomVar())
Text1.Text=Text1.Text&vbcrlf&SomeVar(intCon)
NextintCon
以下のコードは、上のコードより 20 倍高速に実行されます。
DimintConasInteger
DimsOutputasString
ForintCon=0toUbound(SomeVar())
sOutput=sOutput&vbCrlf&
SomeVar(intCon)
次
Text1.Text=sOutput
4. セットの使用を避け、配列を使用するようにしてください
コレクションを使用する必要がない限り、常に配列を使用する必要があります。テストによると、配列のアクセス速度はコレクションの 100 倍に達する可能性があります。この数字は少し衝撃的に聞こえますが、コレクションがオブジェクトであると考えると、なぜ差がこれほど大きいのかが理解できるでしょう。
5. 小さなループ本体を展開します
コーディング中に、ループ本体が 2 回または 3 回しかループせず、ループ本体が数行のコードで構成されているという状況に遭遇することがあります。この場合、ループを展開できます。その理由は、ループが余分な CPU 時間を消費するためです。ただし、ループがより複雑な場合は、これを行う必要はありません。
6. 非常に短い関数の使用を避ける
小さなループを使用する場合と同様、わずか数行のコードで関数を呼び出すのは不経済です。関数の呼び出しには、関数内のコードを実行するよりも時間がかかる可能性があります。この場合、関数内のコードを、関数が最初に呼び出された場所にコピーできます。
7. サブオブジェクトへの参照を減らす
VB では、オブジェクト参照は を使用して実装されます。例えば:
フォーム1.テキスト1.テキスト
上記の例では、プログラムは Form1 と Text1 の 2 つのオブジェクトを参照します。この方法を使用した引用は非効率的です。しかし、残念ながらそれを避ける方法はありません。プログラマができる唯一のことは、With を使用するか、子オブジェクト (Text1) を別のオブジェクトとともに保存することです。
注: と一緒に使用してください
withfrmMain.Text1
.Text="VB を学ぶ"
.Alignment=0
.Tag="イッツマイライフ"
.BackColor=vbBlack
.ForeColor=vbWhite
EndWith
または
注: 子オブジェクトを保存するには別のオブジェクトを使用してください
DimtxtTextBoxasTextBox
SettxtTextBox=frmMain.Text1
TxtTextBox.Text="VB を学ぶ"
TxtTextBox.Alignment=0
TxtTextBox.Tag="イッツマイライフ"
TxtTextBox.BackColor=vbBlack
TxtTextBox.ForeColor=vbWhite
上記の方法は、オブジェクトのサブオブジェクトを操作する必要がある場合にのみ適用できることに注意してください。次のコードは正しくありません。
テキストあり1
.Text="VB を学ぶ"
.Alignment=0
.Tag="イッツマイライフ"
.BackColor=vbBlack
.ForeColor=vbWhite
EndWith
残念ながら、実際のコードでは上記と同様のコードが頻繁に見つかります。そうすると、コードの実行が遅くなるだけです。その理由は、With ブロックがコンパイル後に分岐を形成し、追加の処理作業が追加されるためです。
8. 文字列が空かどうかを確認します
ほとんどのプログラマは、文字列が空かどうかを確認するときに次の方法を使用します。
IfText1.Text=""then
注: 操作を実行する
エンディフ
残念ながら、文字列比較を行うには、プロパティを読み取るよりもさらに多くの処理が必要になります。したがって、次の方法を使用することをお勧めします。
IfLen(Text1.Text)=0then
注: 操作を実行する
エンディフ
9. Nextキーワードを削除した後の変数名
Next キーワードの後に変数名を追加すると、コードの効率が低下します。なぜそうなるのかは分かりませんが、ただの経験です。しかし、余分な情報を追加するプログラマはほとんどいないと思います。結局のところ、ほとんどのプログラマは言葉を金のように大切にする人たちです。
コメント: コードが間違っています
ForiCount=1to10
注: 操作を実行する
NextiCount
注: 正しいコード
ForiCount=1to10
注: 操作を実行する
次
10. 複数の変数の代わりに配列を使用する
同様のデータを保持する変数が複数ある場合は、それらを配列に置き換えることを検討してください。 VB では、配列は最も効率的なデータ構造の 1 つです。
11. 静的配列の代わりに動的配列を使用する
動的配列の使用はコードの実行速度に大きな影響を与えませんが、場合によっては大量のリソースを節約できます。
12. オブジェクトを破壊する
どのような種類のソフトウェアを作成する場合でも、プログラマは、ユーザーがソフトウェアを終了することを決定した後、ソフトウェアが占有しているメモリ空間を解放することを考慮する必要があります。しかし、残念なことに、多くのプログラマーはこのことをあまり気にしていないようです。正しいアプローチは、プログラムを終了する前に、プログラムで使用されているオブジェクトを破棄することです。例えば:
DimFSOasNewFileSystemObject
注: 操作を実行する
注: オブジェクトを破壊します
SetFSO=なし
フォームの場合は、次のものをアンインストールできます。
UnloadfrmMain
または
SetfrmMain=なし
13. 可変長文字列と固定長文字列
技術的に言えば、固定長文字列は可変長文字列よりも必要な処理時間とスペースが少なくなります。ただし、固定長文字列の欠点は、多くの場合、Trim 関数を呼び出して文字列の末尾の NULL 文字を削除する必要があり、コード効率が低下することです。したがって、文字列の長さが変わらない場合を除き、可変長文字列を使用してください。
14. ActiveX コントロールの代わりにクラス モジュールを使用する
ActiveX コントロールにユーザー インターフェイスが含まれていない限り、クラスなどの軽量オブジェクトを使用するようにしてください。両者の間には効率に大きな違いがあります。
15. 内部オブジェクトを使用する
ActiveX コントロールと DLL を使用する場合、多くのプログラマはそれらをコンパイルしてプロジェクトに追加することを好みます。 VB から外部オブジェクトに接続するには大量の CPU 処理能力が必要となるため、これは行わないことをお勧めします。メソッドを呼び出したり、プロパティにアクセスしたりするたびに、大量のシステム リソースが無駄になります。 ActiveX コントロールまたは DLL のソース コードがある場合は、それらをプロジェクト内のプライベート オブジェクトにします。
16. モジュールの数を減らす
共通の機能をモジュールに保持することを好む人もいますが、私もそれに同意します。しかし、モジュールにわずか 20 ~ 30 行のコードを記述するのは少しばかげています。本当にモジュールが必要ない場合は、使用しないようにしてください。その理由は、VB はモジュール内の関数または変数が呼び出された場合にのみモジュールをメモリにロードし、VB アプリケーションの終了時にこれらのモジュールがメモリからアンロードされるためです。コード内にモジュールが 1 つしかない場合、VB はロード操作を 1 つだけ実行するため、コードの効率が向上します。逆に、コード内に複数のモジュールがある場合、VB は複数のロード操作を実行し、コードが減ります。
17. オブジェクト配列を使用する
ユーザー インターフェイスを設計するとき、プログラマは同じタイプのコントロールにオブジェクト配列を使用するように努める必要があります。実験を行うことができます。それぞれ異なる名前を付けて 100 個の PictureBox をウィンドウに追加し、プログラムを実行します。次に、新しいプロジェクトを作成し、ウィンドウに 100 個の PictureBox を追加します。ただし、今回はオブジェクト配列を使用し、プログラムを実行すると、2 つのプログラムの読み込み時間の違いに気づくことができます。
18. Move メソッドを使用する
オブジェクトの位置を変更するとき、プログラマの中には、Width、Height、Top、および Left プロパティを使用することを好む人もいます。例えば:
画像1.幅=100
画像1.高さ=100
画像1.トップ=0
画像1.左=0
実際、プログラムは 4 つのプロパティを変更し、変更するたびにウィンドウが再描画されるため、これは非常に非効率的です。正しいアプローチは、Move メソッドを使用することです。
画像1.移動0,0,100,100
19. 画像の使用を減らす
画像は大量のメモリを消費し、画像の処理には大量の CPU リソースも必要になります。ソフトウェアでは、可能であれば、画像の代わりに背景色を使用することを検討してください。もちろん、これはこの問題に関する単なる技術者の見解です。
20. ActiveX コントロールの代わりに ActiveXDLL を使用する
設計している ActiveX オブジェクトにユーザー インターフェイスが含まれていない場合は、ActiveXDLL を使用します。
コンパイルの最適化
私が会った多くの VB プログラマは、コンパイル オプションを使用したことがなく、オプション間の違いを理解しようとしたこともありませんでした。各オプションの具体的な意味を見てみましょう。
1.Pコード(擬似コード)とネイティブコード
ソフトウェアを P コードまたはネイティブ コードにコンパイルすることを選択できます。デフォルトのオプションはネイティブ コードです。では、P コードとネイティブ コードとは何でしょうか?
P コード: VB でコードを実行する場合、VB はまずコードを P コードにコンパイルし、次にコンパイルされた P コードを解釈して実行します。コンパイルされた環境では、このコードを使用すると、ネイティブ コードよりも高速になります。 P コードを選択すると、VB はコンパイル時に疑似コードを EXE ファイルに配置します。
ネイティブ コード: ネイティブ コードは、VB6 以降にのみ導入されたオプションです。 EXE ファイルにコンパイルすると、ネイティブ コードは P コードよりも高速に実行されます。ネイティブ コードを選択すると、VB はコンパイル時に機械語命令を使用して EXE ファイルを生成します。
ネイティブ コードでコンパイルすると、時々説明できないエラーが発生することがあります。コードはコンパイル環境では完全に正しく実行されますが、ネイティブ コード オプションを使用して生成された EXE ファイルは正しく実行されません。通常、これはウィンドウがアンロードされるか、印刷ウィンドウがポップアップするときに発生します。コードに DoEvent ステートメントを追加することで、この問題を解決しました。もちろん、これが起こる可能性は非常にまれですが、VB プログラマの中にはこれに遭遇したことがない人もいるかもしれませんが、実際には存在します。
ネイティブ コードにはいくつかのオプションもあります。
a) コード速度の最適化: このオプションを使用すると、より高速な実行可能ファイルをコンパイルできますが、実行可能ファイルのサイズは大きくなります。推奨
b) コード サイズの最適化: このオプションを使用すると、より小さい実行可能ファイルをコンパイルできますが、速度が犠牲になるため、お勧めできません。
c) 最適化なし: このオプションは、最適化を行わずに P コードのみをネイティブ コードに変換します。コードをデバッグするときに使用できます。
d) Pentium Pro 用に最適化: このオプションはネイティブ コードのデフォルト オプションではありませんが、通常はこのオプションを使用します。このオプションでコンパイルされた実行可能プログラムは、PentiumPro および Pentium2 以降のマシンではより高速に実行できますが、古いマシンではわずかに遅くなります。現在では Pentium2 を使用するのは時代遅れであることを考慮すると、誰でもこのオプションを使用することをお勧めします。
e) シンボリック デバッグ情報の生成: この項目はコンパイル プロセス中にいくつかのデバッグ情報を生成し、ユーザーが Visual C++ などのツールを使用してコンパイルされたコードをデバッグできるようにします。このオプションを使用すると、実行可能ファイル内のフラグ情報を記録する .pdf ファイルが生成されます。このオプションは、プログラムに API 関数または DLL 呼び出しがある場合に役立ちます。
2. 高度な最適化
[高度な最適化] の設定はソフトウェアの速度を向上させるのに役立ちますが、場合によってはバグが発生する可能性があるため、できるだけ慎重に使用することをお勧めします。コード内に比較的大きなループ本体または複雑な数学的演算がある場合、高度な最適化で特定の項目を選択すると、コードのパフォーマンスが大幅に向上します。高度な最適化機能を使用する場合は、コンパイルされたファイルを厳密にテストすることをお勧めします。
a) エイリアスを想定しない: これにより、ループ本体内のコードの実行効率が向上しますが、メソッドの呼び出しなど、変数参照を通じて変数値が変更される場合、変数参照はメソッドのパラメーターとして使用されます。メソッド値で変数の値が変更されると、エラーが発生します。単に返された結果が間違っているだけである可能性もあれば、プログラムの中断を引き起こす重大なエラーである可能性もあります。
b) 配列バインディング チェックのキャンセル、整数オーバーフロー チェックのキャンセル、および浮動小数点エラー チェックのキャンセル: プログラムの実行中に、これらのチェックでエラーが見つかった場合、エラー処理コードがこれらのエラーを処理します。ただし、これらのチェックがキャンセルされると、プログラムはエラーを処理できなくなります。これらのオプションは、コード内で上記のエラーが発生しないことが確実な場合にのみ使用してください。これらはソフトウェアのパフォーマンスを大幅に向上させます。
c) 丸めなしで浮動小数点演算を許可する: このオプションを選択すると、コンパイルされたプログラムで浮動小数点演算をより高速に処理できるようになります。唯一の欠点は、2 つの浮動小数点数を比較するときに不正確な結果が生じる可能性があることです。
d) PentiumFDIV セキュリティ チェックをキャンセルする: このオプションは一部の古い Pentium チップに設定されており、現在は古いようです。