c#からFirebirdのDBにアクセスした後、Exeの終了が遅い。その2。
Firebird Embeddedを使用した後、プロセスの終了が遅い件ですが、
その後色々調べたところ、似たような件で悩んでいる人はいるようでした。
ただ、解決にはいたっていないようです。
試しに FbConnection.ClearAllPools() がどれくらい効果あるのか試してみました。
結論から言えば、ConnectionをPoolしているときはそれなりに効果ありますが、
やはり3秒は超えられない。
なにかのタイムアウト待ちなのか、どうなのか。
環境
- Firebird Embedded 2.5.4
- FirebirdSql.Data.FirebirdClient 4.8.0
検証
前回利用したものの最後に、ClearAllPools と Connection作る時にPooling を true にする処理を追加。
static void Main() { var i = 0; var max = 2000; while (i < max) { var connectionBuilder = new FbConnectionStringBuilder(); //.....諸々 connectionBuilder.Pooling = true; using (var connection = new FbConnection(connectionBuilder.ConnectionString)) { connection.Open(); connection.Close(); } i++; } FbConnection.ClearAllPools(); }
FbConnection.ClearAllPools() を呼ぶ場合と呼ばない場合の2種類を用意して、時間計測。
FirebirdClient2 : FbConnection.ClearAllPools()を呼ぶ方。
FirebirdClient : FbConnection.ClearAllPools()を呼ばない方。
あまり厳密ではないですが、手元で何度かやってみたけど、結果は変わらず。
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}");
ProcessMonitorで見てみると、
もしかして、また君ですか。
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); } } }
これで良いのだろうか(笑)
動作に問題はなさそうなんですが、確かなことが分からず。
とりあえず、これで妥協してみようかなぁ。
試しにサンプル上げてみた。
.NET Framework 4.5.2 でXmlReaderのDTD読み込みの挙動が変わっていた
以前、少しはまってしまったので、メモしておきます。
先に解決策書いておくと、ちゃんとXmlResolverのインスタンス作成しておきましょう!です。
問題点
TargetFramworkを4から4.6に上げた際に、DTDの外部実体参照が読み込まれなくなってしまっていた。
その時の読み込み部分。
var reader = XmlReader.Create(path, new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse })
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE Samples[ <!ENTITY Sub1 SYSTEM "Body\Sub1.txt"> ]> <Samples> <Title>あいうえお</Title> <Body>&Sub1;</Body> </Samples>
Titleは取れるが、Body部分が取れてこない。
試しに、TargetFramworkを変更してみると、
- .NET Framework 4 → ○
- .NET Framework 4.5.1 → ○
- .NET Framework 4.5.2 → ×
- .NET Framework 4.6 → ×
という結果に。
解決
ということで、おなじみのMSDN。
XmlReader.Create メソッド (System.Xml)
書いてありました。
ありがとうMSDN。
さらに原文の方を見ると、
はひ。そうですか、そうですよね。 という感じに。
というわけで、
var reader = XmlReader.Create(path, new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse, XmlResolver = new XmlUrlResolver() })
みたいにしてあげれば良さそう。
というわけで解決。 そもそもの構造が良くなさそうってのもありますが、良い勉強になりました(笑)
ソースサンプル
Postfix, Dovecotのversionを取得する
CentOS7でテスト用のメールサーバーを立てる
仕事でプログラムからMail送信する機能があったため、テスト用のメールサーバー立てました。
手順を残しておきたかったので、メモしておきます。
公開するような設定にはなっていないです。
検証環境
postfix Install
まずはPostfixのインストール。
yum install postfix cp -p /etc/postfix/main.cf /etc/postfix/main.cf_yyyymmdd
postfix Settings
設定は必要そうなものだけ。
/etc/postfix/main.cf
myhostname = mail.hoge.test mydomain = hoge.test ient_interfaces = all mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain home_mailbox = Maildir/
自動起動
systemctl enable posrfix.service
保存先
mkdir /etc/skel/Maildir chmod 700 /etc/skel/Maildir
サービスの再起動
サービスを一応Reload。
service postfix reload
dovecot Install
つづいてDovecotをインストール。
yum install -y dovecot cp -p /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf_yyyymmdd cp -p /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf_yyyymmdd cp -p /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf_yyyymmdd cp -p /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl_yyyymmdd
dovecot Settings
こちらも必要なところだけ。
sslとかも切っておく。
/etc/dovecot/dovecot.conf
protcols = imap pop3
/etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:~/Maildir
/etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = no auth_mechanisms = plain login
/etc/dovecot/conf.d/10-ssl.conf
ssl = no
自動起動
systemctl enable dovecot.service
サービスの再起動
service dovecot reload
Firewall
ファイヤーウォールは必要なポートを開けておく。
firewall-cmd --add-port=25/tcp --permanent firewall-cmd --add-port=110/tcp --permanent firewall-cmd --reload
UserCreate
ユーザーは適当に追加。
useradd test passwd test
最後に
これで完了かと思って、動作確認してみたら、うまくいかず。
一度、rebootしたらつながったので問題ないはず。