投稿

ラベル(C#)が付いた投稿を表示しています

PostgreSQLとNpgsqlのコネクションプールの挙動

Npgsqlを用いてPostgreSQLと接続したときのコネクションプールの挙動について検証したものをトピック形式でメモしておく。 バージョン ・PostgreSQL 13 ・Npgsql 8.0.1 Npgsqlの接続プールは各プロセス内のメモリで管理される NpgsqlのコネクションプールはNpgsql名前空間内のstaticなクラスで管理されている。プロセスを複数立ち上げればそれぞれ別々にプールされる。 接続プールは接続文字列ごとに管理される 接続プールは接続文字列ごとに管理され同じ接続文字列の場合にのみ再利用される。またプールされる数も接続文字列ごとにカウントされる。 これは仮に接続先が同じでもパラメータが違うだけで別々となる。 接続プール数、保持時間は接続文字列で指定する パラメータ名 意味 未指定時 Pooling プール有無 true MinPoolSize 最小数 1 MaxPoolSize 最大数 100 ConnectionLifeTime 保持時間(秒) 500 接続の再利用時、セッションパラメータはリセットされる プールされた接続は再利用前に次の文を発行して状態をリセットしている。 SET SESSION AUTHORIZATION DEFAULT RESET ALL 不意の停止でサーバ側にセッションが残る場合がある コネクションプールはプロセスの終了時にすべて切断される。ただしプロセスの強制中断などで解放処理が走らないとサーバ側でセッションが残ってしまう。残ったセッションはサーバの同時接続数の枠を埋めてしまう。 接続がプールされた状態でDBを再起動すると次の利用時にエラーになる コネクションプールが残った状態でPostgreSQLサーバを停止・再起動してもプールされた接続のインスタンスは破棄されない。そして次にその接続が再利用されるとNpgsqlException (0x80004005)が発生する。 DBのみ再起動すると予期せぬタイミングで接続エラーとなってしてしまう可能性がある。 最大プール数を超えた場合は待機状態になる MaxPoolSizeを超えてOpenを行ったとき、接続数に空きが出るまで他の処理の終了を待機する。待機する時間は通常の接続タイムアウトと同じで接続文字列(Timeout)で指定できる。 タイム...

システム時刻を変更したときの.Netプログラムの時間関係への影響

サーバー系のプログラムでは一定時間ごとに処理を行う定期処理を組む場合がある。もし動作中にOSのシステム時刻を変更された場合にどうなるのか。今回は.NetでのWindowsのシステム時刻を変更したときの動作を確認した。 SleepとDelay まずはSleep系の挙動を確認する。恐らくクロックカウントを利用しているのでシステム時刻の影響は無いと想定される。 Thread.SleepとTask.Delayで次のようなコードを書いた。なお環境は.Net Core3.1だ。 void TestSleep() { while (true) { Thread.Sleep(10000); Debug.WriteLine("tick"); } } async Task TestDelay() { while (true) { await Task.Delay(10000); Debug.WriteLine("tick"); } } プログラムを起動した状態でシステム時刻を適当にずらす。ストップウォッチを持って計測したところ、システム時刻を進めても戻してもきちんと10秒ごとにデバッグ文が出力された。 Thread.SleepとTask.Delayはシステム時刻に影響を受けないことが確認できた。 DateTime.Now 次にDateTimeの現在日時を確認する。Sleepが定期動作することが分かったので次のコードを書く。 void TestDateTime() { while (true) { Thread.Sleep(10000); Debug.WriteLine($"{DateTime.Now:MM/dd HH:mm:ss}"); } } 結果 11/12 21:40:33 11/12 21:40:43 _ここで5秒時間を戻す 11/12 21:40:48 11/12 21:40:58 当然ではあるがシステム時刻に合わせて日時が変わった。このことからDateTime.Nowを経過時間の判定に利用する場合は、時刻飛びや遡りが起きることに注意が必要だ。 Stopwatch 次は高性能...

ClosedXMLで時間値を取得したときの値とEXCELの仕様(特に24時間以上の場合)

イメージ
ClosedXMLで「15:00」のようなセルから、データ値をDateTime型で取得した際の戻り値について。 この記事の内容はClosedXML Ver0.95を対象に書いている。しかしVer0.100で結果が変わったため、誤解の無いように結果のみ先に書いておく。 ・Ver 0.100.0 より前 1899/12/30 HH:mm:ss ・Ver0.100.0 以降 1899/12/31 HH:mm:ss 本文 Excelの時間が入力されたセルから、ClosedXMLで値を取得したとき、TimeSpan型となる場合とDateTime型となる場合がある。これはこれで面倒ではある※が、今回の問題はDateTime型のときだ。 ※ 例えばセルのフォーマットが"[h]:mm:ss"だとTimeSpan型、"[h]:mm"だとDateTime型になったりする Excelでは時刻も日時も内部では同じシリアル値で管理されている。時刻を入力したセルのフォーマットを変更して日付を表示してみると「1900/1/0 ~」と表示される。日付としては不正だが、1日未満という意味で0日なんだろう。 C#のDateTime型では当然0日という日付は表現できない。ではどのような値になるかというと 1899/12/30 ~ そう1899/12/31 ではない のだ。これはExcelの仕様バグに起因する。 1900年2月29日が存在するExcelのバグ 1900年は100の倍数であり400の倍数でないため、本来うるう年ではないのだが、Excelでは仕様バグとして2月29日が存在している。「仕様バグ」と書いたのは、正しくはないが意図的に組み込まれた動作だからだ。 詳しくは以下に公式のアナウンスがある Excel では、1900 年が閏年であると誤って想定されています Windowsが存在する前のソフトとの互換性が、2023年現在でも尾を引いてるというのは面白い。 ちなみにGoogleスプレッドシートでは日時をExcelと同様シリアル値で管理しているが、上記は切り捨てられていて1900年2月29日は存在しない。 ClosedXMLのGetValue ClosedXMLのGetValueでは、DateTime型を生成する際にこの補正などを特にしていないため、1...

WPF DataGridで列選択できるようにする

イメージ
WPFのDataGridはSelectionUnitプロパティをCellOrRowHeaderにすると行ヘッダのクリックで行選択ができる。一方で列選択は用意されていない。必要になったので自前で再現してみたが、案外面倒くさかったので残しておく。 XAML <DataGrid x:Name="MyGrid" SelectionMode="Extended" SelectionUnit="CellOrRowHeader" CanUserSortColumns="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False"> <DataGrid.ColumnHeaderStyle> <Style TargetType="DataGridColumnHeader"> <EventSetter Event="PreviewMouseDown" Handler="Column_MouseDown" /> <EventSetter Event="PreviewMouseMove" Handler="Column_MouseMove" /> <EventSetter Event="PreviewMouseUp" Handler="Column_MouseUp" /> </Style> </DataGrid.ColumnHeaderStyle> </DataGrid> セルの複数選択が必要なので、SelectionModeをExtended、SelectionUnitをCellまたはCellOrRowHeaderにする。...

クリップボード履歴 & 定型文ツール Kourin Snippet

イメージ
Windows用のクリップボード拡張系のスニペットツール。既存のツールも色々あるけど、なかなかしっくりくるものが無かったので自分で作って使っていた。 マニュアルとかも作ったし、せっかくなので公開します。 特徴 履歴と定型文の2つの機能 Kourin Snippetはクリップボードのコピー履歴と、定型文の登録機能がひとつになったアプリです。 アプリを起動するとシステムに常駐して、キーボードの[Ctrl+Shift+V]で履歴、[Ctrl+Alt+V]で定型文を呼び出し、テキストを選んで貼り付けを行うことができます。 定型文を階層化して登録 定型文はグループを5階層まで入れ子にして登録できます。沢山のスニペットを登録しておきたい人に便利です。 登録はテキストファイルの配置で、フォルダの構造がそのまま階層になるため素早く簡単に登録できます。 スクリプトによるテキスト作成 定型文にスクリプトを記述することで、動的に文章を作成できます。スクリプトでは日付や数値計算などテキスト操作以外も記述できます。 InputDialog["苗字", "名前"] "私の名前は" & $$Input1 & $$Input2 & "です。" ランチャーとしての利用 他のアプリを起動するスクリプトを登録することで、ランチャーとしても利用できます。よく使う管理コマンドなどを登録することも可能です。 プラグイン機能 .Net Framework のプログラミング知識があれば、DLLを作成して定型文のスクリプトに任意の処理を追加することができます。 利用方法 Kourin Snippet は Windows用のフリーソフトです。 インストーラはありませんのでダウンロードしたzipファイルを解凍してください。詳細な使い方は同梱のマニュアルに記載があります。 ダウンロード 最新のリリースは GitHub の Releases よりダウンロードしてください。 kuma0223/KourinSnippet もしくはこちら Ver3.0 ダウンロード直リンク

有理数を分数精度のまま計算するクラス(C#)

別に計算用途があったわけでもないけど、有理数を分数のまま計算するためのクラスを作成してみた。1/3が0.333...にならずに1/3のまま計算できるもの。 ソースコード ちょっと長いけど全文載せる。 class RationalNumber : IEquatable<RationalNumber>, IEquatable<long>, IComparable<RationalNumber> { private bool sign = true; private long a = 0; private long b = 1; private static Regex Pattern = new Regex("&#92s*(-?[0-9]+)&#92s*(/&#92s*([0-9]+)&#92s*)?"); //-------------------- /// <summary> /// 分子の絶対値を取得します。 /// </summary> public long Numerator { get { return a; } } /// <summary> /// 分母の絶対値を取得します。 /// </summary> public long Denominator { get { return b; } } /// <summary> /// 小数値を取得します。 /// </summary> public double DoubleValue { get { var v = (double)a / (double)b; return SignValue * v; } } /// <summary> /// 値が0であるかを取得します。 /// </summary> ...

競技プログラミング用コピペコード集(C#)

主にAtcoderでやる競技プログラミングで再利用するために、C#で書いたコードたちを載せてみる。どれも既知のアルゴリズムなのでコピペとかして構わないけど、もし間違っていても責任はとらない。 また何かあれば追加するかも。 公約数/公倍数 最大公約数 static long Gcd(long m, long n) { if (m < n) {var t=m; m=n; n=t;} while (true) { var mod = m % n; if (mod == 0) return n; m = n; n = mod; } } ユークリッド互除法 の実装。 最小公倍数 ※2020/5/13 計算途中でのオーバーフローに対策 static long Lcm(long m, long n) { var x1 = Math.Max(m, n); var x2 = Math.Min(m, n); var gcd = Gcd(x1, x2); return x1 / gcd * x2; } 上のGcdが必要。最大公約数から最小公倍数を求める公式。 演算 累乗 ※2020/5/31 2^32でOFしてたのに対応 static long Pow(long x, long n) { long ans = 1; while (n > 0) { if (n % 2 == 1) { ans = ans * x; } n /= 2; if(n == 0) break; x = x * x; } return ans; } 通常はMath.powを使う累乗の手書き実装。n<0には対応しない。単純ループするとO(n)だが、2乗を入れ子にするアルゴリズムで実装してO(log n)。いわゆる繰り返し二乗法。 x^20 = (((x^2)^2)^2)^2 * (x^2)^2 累乗(Mod) ※2020/5/31 2^32でOFしてたのに対応 static long ModPow(long x1, long x2){ l...

WPF FrameがPageのインスタンスを保持してる件

イメージ
WPFでページ遷移を作る場合、XAMLでFrameコントロールを置いてナビゲーションするのが手っ取り早い。しかし今回はちょっとした罠に掛かってしまった。 ページ遷移でメモリリーク? なんか画面移動するたびにメモリが増えていく。まあPageのインスタンスをその都度newしてるので一時的には増えるが、そのうちGCされるだろう。そう思ってたがいつまでも減らない。試しにGC.Collect()してみても減らない。Page内で残ってる参照なども心当たりがない。はて。 犯人はナビゲーション機能 Frameコントロールにはナビゲーションの機能が付いている。NavigationUIVisibility="Visible"を付けると[戻る]とか[進む]のボタンが出てくる。 こういうやつ。見た目がいまいちだしあまり使われてる気はしない。しかしどうもこの[戻る][進む]機能のために、Frameは表示したインスタンスの参照を保持しているようだった。 これはNavigationUIを非表示にしてもやめないし、履歴保持数などのプロパティも設定できない。いったいどの程度持ち続けるのだろうか。まさかメモリが枯渇するまで残し続けることは無いと信じたいが。 対策 前述の通りプロパティなどで無効化することはできないので、履歴を手で消してやる。以下のようなコードをどこかしらに実装する。 while (Frame.CanGoBack) { Frame.RemoveBackEntry(); } RemoveBackEntry()は最後の履歴を1件削除する。全クリアなどのメソッドは無いらしい。しかも履歴が一件も無い状態で呼ぶと例外が発生する。 これをページ遷移の処理部なりで呼んでやれば、とりあえず延々増えてくことは回避できる。確実なのはFrameの遷移完了イベントあたりか。 しかしAddなんちゃらみたいなメソッドではなく、Content=~という代入でキューイングされるのはちょっとイマイチな実装だと思う。

競技プログラミングのAtCoderやってみた所感

空き時間に AtCoder というサービスをやってみたので感想や環境など。 概要 AtCoderは日本企業が運営している競技プログラミングのサイト。毎週主に土曜日の夜に定期コンテストが開かれていて、Webから登録すれば簡単に参加することができる。 コンテストの流れ コンテストは事前に告知された時間にみんなで一斉に行う。 開始時間になるとページに問題が表示されるので、それに沿うようにコーディングを行う。 ソースコードをWeb画面から送信するとサーバでコンパイル、テストケースが実行され成否が判定される。正解した問題数と回答時間で順位が決まるようだ。 プログラミング言語はC++やJavaなどの選択肢から選ぶが、主要なものはほぼ揃っている。COBOLなんかもあるが流石に利用者はほぼ見当たらない。自分はC#でやっている。 所感 プログラミングというよりはアルゴリズムのコンテストといった感じで、数学的な問いをプログラムで実装するようなものが基本。 評価は「インプットに対するアウトプット」「計算時間」「回答時間」でされるので、コーディングのフォーマットやエラー処理なんかは特に問われれない。 難易度 毎週やってるBeginner Contestは難易度準にA~Fまでの問題がある。 ABは初学者教本にあるような基礎。足し引きと分岐・ループができればだいたいOK。 Cは数1Aぐらいまでの内容で、プログラミング的にも再帰やコレクションの使い分け、計算量を想定した実装が必要になってくる。普通のプログラマはこのあたりが及第点だろうか。 Dからは動的計画法や漸化式みたいな考え方が出てくるし、既知のアルゴリズムをベースにしたりする必要があるので、現役理系学生以外は対策しないと厳しい。 実務に活かせるか 内容がアカデミック寄りなので、ほとんどの現場ではあまり直接的な関係はなさそう。実際の業務コーディングではアルゴリズムより機能の切り分けや将来設計、速度より安全な実装と適切なエラー処理などの方が大事になってくる。 検索エンジンやミドルウェアを作るならそういう機会もあるかもしれない。 就職アピールなら評価の対象は問題そのものよりも、プログラミングへの興味の高さや、やっていくうえでの工夫や学習法あたりになるだろうか。 コーディング環境とか 一応Webサイト上にデバッグ環境みたいなのはあるが、すべてそれで...