1

Delphi 7 32 ビット アプリケーションがあります。ウィンドウズ7 64ビット。

すべてが正常に動作します。私は最近、気づいたパフォーマンスの問題を調査しています。

アプリケーションの簡単な概要 -->

Delphi で記述された、コマンドライン/コンソール アプリの実行可能ファイルがあります。これにより、マルチスレッドの接続セットが作成され、データベースの作業が行われます。見つかったジョブのスケジュールに基づいて、Delphi で記述された (コマンドライン アプリケーションを呼び出す) NT サービス。これは、コマンドライン アプリケーションの CreateProcess を見つけて実行する DLL への呼び出しと、それが終了するための WaitForSingleObject によって行われます。事実上、このサービスは、いつ作業を行う必要があるかを見つけ、それを行うために実行可能/コンソール アプリを呼び出します。

これが私の問題です、私は理解できないようです。

コマンド ライン アプリケーションを実行すると、NT サービスが CreateProcess を介して呼び出した場合よりも約 4 倍速く結果が得られます。これは IDENTICAL コードです。1 つは EXE の DOS プロンプト発行で、もう 1 つは NT サービスで、DLL をロードし、同じ実行可能ファイルの CreateProcess を呼び出します。

私はバナナに行きます。これには理由が見当たりません。

これまでのところ、どのシステム構成でもこれを再現できます。

これまでに気づいたこと(科学的ではありませんが、確かに関連するものです)。

CPU コアを CPU 時間とカーネル時間で監視すると、コンソール アプリの実行期間中、カーネル時間の一部が残ります。スケジューラ サービスがこれを実行すると、カーネル時間は、取得している CPU 使用率の 50 ~ 70%% 以上を表します。

いくつかの実際の結果 (他のすべては事実上無関係だと思います) - コンソール アプリ、コマンドラインからの実行: 26 秒 - コンソール アプリ、CreateProcess 経由のサービスからの実行: 113 秒

何を与える?

FastMM が適切に共有されていない可能性があることを調べました。私はそう信じています。私もそれを削除しました。同じ異常。おそらくFastCode、FastMoveのものがサービスの下で機能していないことを調べました(起動時に、コアRTL関数を動的にフック/置換しようとしていたため、方程式からそれらを削除しましたが、同じ異常です。パッチを適用したRTLを削除することを検討しました(System.dcu/SysInit.dcu) ファイル。

すべて役に立たない。

それで、私の質問(および考えられる理由による勧誘)は...

NT サービスは、自動化/フック置換機能を実行する機能を排除しますか? Delphi サービスは、これを引き起こす何かを作成しますか? サービスには何らかの固有のオーバーヘッドがありますか (そして、それは莫大な量です)? この性質のために他の人が使用した FastMM、FastCode、FastMove を使用する代替手段はありますか?

ここでのガイダンス/ヘルパーに感謝します。

NT サービスからアプリを起動するために使用されるコードのスニペットを次に示します。

FillChar(si, SizeOf(si), 0);
si.dwFlags := SW_HIDE;
FillChar(pi, SizeOf(pi), 0);

sCommandLine := Format('"%s" "%d"', [ExtractFilePath(ParamStr(0)) + 'MYAPP.EXE', AJobID]);

If CreateProcess(PChar(sFilename),
    PChar(sCommandLine),
    Nil,
    Nil,
    False,
    0,
    Nil,
    Nil,
    si,
    pi) Then Begin

    WaitForSingleObject(pi.hProcess, INFINITE);
    GetExitCodeProcess(pi.hProcess, ExitCode);
    Result := (ExitCode = 0);

End Else Begin

    AddEventLogMessage(SysErrorMessage(GetLastError));

End;
4

1 に答える 1

1

この問題は、特に接続の使用と接続の共有に関連していることが判明しました。

CreateProcess を起動する前にスケジューラで接続を破棄するというアプローチを取ると、カーネルの使用状況は、コンソールから直接実行したときに見たものと同じになりました。

コマンドラインが行っていたことと接続が共有されていないことを考えると、非常に驚​​くべきことです。

今後の参考: 2 つのアプローチが同一であると言う前に、すべての変数を削除してください。これでは、そうではありませんでした。スケジューラには接続がありましたが、コンソール アプリにはありませんでした。そして、それがすべての違いでした。

于 2013-02-07T04:38:54.437 に答える