読者です 読者をやめる 読者になる 読者になる

ぽにょろん

思いついたこととメモ

c#からFirebirdのDBにアクセスした後、Exeの終了が遅い

c#からFirebirdのDBにアクセスした後のExeの終了が遅いということがありまして、少し調べてみました。

結論が正しいのかわかりませんがメモとして残しておきます。
※検証甘いです。

環境

  • Firebird Embedded 2.5.4
  • FirebirdSql.Data.FirebirdClient 4.8.0

現象

諸事情で、A.exe → B.exe といった呼び出しが複数回あるようなアプリ構造がありました。
B.exeの終了が遅いので、全体の処理がとても緩慢な感じに。
ということで、ミニマムコードを。

static void Main()
{
    using (var connection = new FbConnection(接続文字列))
    {
        connection.Open();
        connection.Close();
    }
}

これだけで、私の環境だとMainを抜けた後に3秒程かかりました。
ConnectionをOpenしなければ1秒未満です。

分析

まずは時間を。

var process = Process.Start(@"D:\tmp\FirebirdClient\FirebirdClient.exe);
process.WaitForExit();

//ExitCodeでHHmmss形式で終了時間をReturnするようにして、
//DateTime.NowをHHmmss形式にしたので差分をとる。
var elapsed = Utility.Subtract60(DateTime.Now.ToIntTime(), process.ExitCode);

Console.WriteLine($"Path: {path} / Seconds: {elapsed}");

f:id:kowill:20150927232141p:plain

ProcessMonitorで見てみると、

f:id:kowill:20150927230852p:plain

もしかして、また君ですか。
fb_trace_xxxには時折苦しめられておるのですが(笑)

解決策(??)

動作を見ている限り、fb_trace_xxxやfb_Lock_xxxなどのTempデータはNetProvider経由の場合、プロセス終了時にクリアされているようでした。
DelphiXE + FireDAC だと接続切っただけでクリアされていたような気がするんだけどなぁ。

ってなわけで、

[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);

手動でアンロードしてみる。

  • FirebirdSql.Data.FirebirdClient → × (そりゃそうだよね..)
  • fbembed.dll → ○ パリィ(°▽°)
static void Main()
{
    using (var connection = new FbConnection(接続文字列))
    {
        connection.Open();
        connection.Close();
    }
    UnloadDll(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), @"fbembed.dll"));
}
[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);

public static void UnloadDll(string path)
{
    foreach (ProcessModule dll in Process.GetCurrentProcess().Modules)
    {
        if (dll.FileName.Equals(path, StringComparison.OrdinalIgnoreCase))
        { 
            FreeLibrary(dll.BaseAddress);
        }
    }
}

f:id:kowill:20150927233213p:plain

これで良いのだろうか(笑)
動作に問題はなさそうなんですが、確かなことが分からず。
とりあえず、これで妥協してみようかなぁ。

試しにサンプル上げてみた。

github.com