2012-04-04 31 views
1

私はメモリスキャナで作業していますが、スキャンが非常に遅いです。誰でも助けてくれますか?私は、私は新しいページを必要とするまで、別の4096バイトのページを取得し、その後、メモリのものを保存する時に4096本のバイトのページを読む必要があり、その上で操作を行うことを学んできた 低速スキャンのメモリスキャナ

procedure FirstScan(scantype, scanvalue: string); 
var 
value :integer; 
dwEndAddr : dword; 
i:dword; 
mbi : TMemoryBasicInformation; 
begin 
    while (VirtualQuery(Pointer(DWORD(mbi.BaseAddress) + MBI.RegionSize), MBI, SizeOf(MEMORY_BASIC_INFORMATION))=SizeOf(TMemoryBasicInformation)) do begin 
    if (MBI.State = MEM_COMMIT) and (MBI.Protect = PAGE_READWRITE) then begin 
    dwEndAddr := DWORD(mbi.BaseAddress) + MBI.RegionSize; 
    for i := DWORD(MBI.BaseAddress) to (dwEndAddr - 1 - sizeof(DWORD)) do begin 
     Application.ProcessMessages; 
     try 
     if scantype = '1 Byte' then begin 
     value := PBYTE(i)^; 
     if scanvalue = IntToStr(value) then ListBox1.Items.Add(IntToHex(i,8)); 
     end; 
     //others scantypes here... 
     except 
     Break; 
     end; 
    end; 
    end; 
    end; 
end; 

...

しかし私はそれをどうすればいいのか分かりません...

誰でも助けてくれませんか?コードはCまたはC++にすることができます...

+3

質問が本当に「なぜこの特定のコードが遅いのですか?」代わりにhttp://codereview.stackexchange.comに持って行きましょう。あなたの質問があまりにもローカライズされて、Stack Overflowに関する一般的な興味があるからです。しかし、あなたの質問がちょうど一般的な場合、「どのように私は任意の遅いコードをより速くするのですか?代わりにそれを直接求めてください。 –

+0

mbi.BaseAddressおよびMBI.RegionSizeは、VirtualQuery()への入力時に未定義 - 未初期化のスタックデータです。 –

答えて

8

遅いコードを速くするには、できることがいくつかあります。最初に、あなたのコードがであることを確認して、正しいにしてください。間違った結果は間違った結果になります。そのためには、VirtualQueryを呼び出すときに、すべてのパラメータに対して有効な値を渡していることを確認してください。この関数の開始時にmbiは初期化されていないので、DWORD(mbi.BaseAddress) + MBI.RegionSizeの結果は誰にでも分かります。

  1. が遅い部分を見つけ、それらを高速に行います。

    あなたがコードを正しく働いていたら、それはより速く作るために2つの方法があります。これを正しく行うには、プロファイラが必要です。プロファイラは実行中のプログラムを観察し、プログラムが各パートの実行に費やした時間の割合を示します。それはあなたの努力をどこに集中させるかを教えてくれる。

  2. 低速アルゴリズムをより高速なアルゴリズムに置き換えます。これは、関数全体を捨てることを意味するかもしれないし、コードの特定の部分だけを修正することを意味するかもしれない。

例えば、プロファイリングを使用すると、時間通話ProcessMessagesの多くを費やすことを示しているかもしれません。 VCLの一部であるため、実際にはその機能を高速化することはできませんが、の場合はと呼ぶ頻度が少なくなります。このコードを実行しているスレッドが処理を必要とするメッセージを受け取らないと思われる場合は、それをまったく呼び出す必要はありません。

プロファイリングでは、文字列比較を行うのに多くの時間を費やしていることがわかります。 があなたの文字列のが頻繁に等しく、通常は最後だけが異なる場合は、文字列比較アルゴリズムを変更して最初の文字ではなく最後の文字の比較を開始したい場合があります。

プロファイリングでは、整数を比較する前に文字列に変換するのに多くの時間を費やしていることがわかります。ほとんどのプログラミング言語は、整数を直接比較することをサポートしているため、文字列比較アルゴリズムを使用する代わりに、代わりに整数比較アルゴリズムを使用できます。 scanvalueStrToInt(scanvalue)で整数に変換し、直接valueと比較することができます。

プロファイリングでは、同じ入力から同じ結果が繰り返し計算されていることがわかります。値がプログラムのある部分で変更されない場合、その値から計算された値も変更されません。値が変更された場合にのみ値を変換することで、値の変換コストを削減できます。たとえば、整数比較を行う場合、整数バージョンのscanvalueは関数内で変更されないことがあります。関数の先頭でscanvalueを整数に変換してから、StrToInt(scanvalue)を何度も呼び出す代わりに、valueをループ内の値と比較してください。

+0

ありがとう、私はこれらの間違いを修正し、ここに戻って結果を掲載します。 – paulohr

+0

質問が編集されました。今すぐ確認できますか? – paulohr

+0

もちろん、私はその変化を見ることができます。しかし、質問全体を変更して元の質問にした回答を完全に無効にしたので、私はあなたに投票しました。 –

10

私はあなたにちょっとお手伝いできます... Application.ProcessMessagesを内側のループの外に出してください。あなたは毎日それを呼んでいます。シングル。バイト。君は。スキャン。ウィンドウメッセージに応じて、のようにに応答する必要はありません。 :)

外側のループに移動すると、速度が大幅に向上するはずです。私は、スレッドを生成し、Application.ProcessMessagesを完全に取り除くと、本当にこのコードの処理の仕事ではありませんが、どのように/ Delphiがスレッドを実行するかはわかりません。

また、スキャンパラメータを文字列として渡していますか?そのようなことを主張する場合は、使用するスキャンタイプを示すループを開始する前にintまたはenumなどを設定し、値を有用なタイプに変換して比較します。文字列の比較は整数比較よりも遅くなる傾向があります(特に、毎回新しい文字列を作成する場合)。

+0

これは、すべてのアプリケーションの完全な削除の山です。プロセスメッセージ。これをスレッディングすることは、デルファイではかなり簡単です。 –

1

また、現在のポインタを文字列に変換すると、すべてのバイトがにアクセスします。 Yech、ひどく遅い。代わりに、プロシージャの開始時にscanvalueをBYTEに変更し、直接BYTEで比較を行います。

最後に、i:= DWORD(MBI.BaseAddress)ループのif scantype = '1バイト'を取り出します。代わりに、すべてのバイトの "if"ステートメントを実行する必要はありません。代わりに、

if scantype = '1 byte' then 
    for i:= DWORD(...) 
else if scantype='other scan type' then... 

などを実行します。 (そして、そうであれば、 "scantype"なら列挙型やその他のものと比較してください)

+0

よかった、ありがとう! – paulohr

関連する問題