PostgreSQL

今進めている案件で初めてPostgreSQLを使用しました。

いつもはSQLServerを使用することが多いので、下調べから始めましたがなんとか使用できるようになりました。
管理ソフトはHeidiSQLを使用しています。特に問題なしです。
C#のライブラリはEntityFramework6.Npgsqlを使用しています。EntityFrameworkはシンプルで良いですね。

思っていたより敷居が低くで良かった。

PLINQ(Parallel LINQ)の結果の要素順

以前にPLINQ(Parallel LINQ)の実行速度を調査し、簡単にLINQを並列化して速度改善できることが分かりました。

しかし、PLINQを使用した場合、結果の要素順はどうなるのでしょう?
本来なら元の要素順に取り出したいのですが、並列化されているので順不同なのでしょうか?
調べてみた結果、PLINQを使用しても元の順番通りに要素が取得できました。すばらしい。

詳しくは調査していませんが、PLINQのメソッドの戻り値はParallelQuery型になっており、たぶんこのクラスか、これを継承したQueryOperatorクラスあたりでうまいこと取出し順序を調整しているのでしょう。

PLINQ(Parallel LINQ)の実行速度

.netのPLINQ(Parallel LINQ)による並列実行の効果がどれほどなのか理解していなかったのでテストしました。

Select、Where、AverageをLINQとPLINQで実行し、速度を確認します。


var items = Enumerable.Range(1, 100_000_000).ToArray();

var sw1 = Stopwatch.StartNew();
var results1 = items.Select(x => Math.Pow(x, 0.5)).ToArray();
Debug.Print($"Select LINQ {sw1.Elapsed}");

var sw2 = Stopwatch.StartNew();
var results2 = items.AsParallel().Select(x => Math.Pow(x, 0.5)).ToArray();
Debug.Print($"Select PLINQ {sw2.Elapsed}");

var sw3 = Stopwatch.StartNew();
var results3 = items.Where(x => Math.Pow(x, 0.5) >= 100).ToArray();
Debug.Print($"Where LINQ {sw3.Elapsed}");

var sw4 = Stopwatch.StartNew();
var results4 = items.AsParallel().Where(x => Math.Pow(x, 0.5) >= 100).ToArray();
Debug.Print($"Where PLINQ {sw4.Elapsed}");

var sw5 = Stopwatch.StartNew();
var results5 = items.Average(x => Math.Pow(x, 0.5));
Debug.Print($"Average LINQ {sw5.Elapsed}");

var sw6 = Stopwatch.StartNew();
var results6 = items.AsParallel().Average(x => Math.Pow(x, 0.5));
Debug.Print($"Average PLINQ {sw6.Elapsed}");

結果


Select LINQ 00:00:04.9831283
Select PLINQ 00:00:01.1474103

Where LINQ 00:00:04.7858871
Where PLINQ 00:00:00.7447430

Average LINQ 00:00:03.8039131
Average PLINQ 00:00:00.3454058

今回のテストプログラムの場合、4倍~11倍の速度改善になっています。
.AsParallel()を追加するだけで、これだけの速度改善になるので、処理が遅くて困った場合にはまずPLINQを試すのが良さそうです。

モータ制御のエミュレート

インフォテックの案件ではサーボモータなどをPCで制御することが良くあります。
今作成しているソフトもモータ制御を行うのですが、モータそのものやPCのモーションボードが無くてもソフトの動作検証が行えるように、エミュレート機能を社内ライブラリに組み込んであります。

今回はエミュレート機能をさらに強化し、移動速度に合わせてパルス出力数がカウントされたり、パルス出力状態や停止要因が正しく変化するようにしました。
この改造により、今までより細かく社内での動作検証が行えるようになりました。

下は3軸の原点復帰動作のエミュレートです。実機無しで状態が変化しています。

WindowsデスクトップアプリのGUIフレームワーク

WindowsデスクトップアプリのGUIフレームワーク(の中でXAMLを使用しているもの)について、以下のサイトに現在の状況が記載されており参考になりました。
https://www.kekyo.net/2021/02/23/7230

インフォテックの利用状況は、過去の案件はWindowsForms、新規案件はWPF、まれにUWPといったところです。
実運用でAvaloniaが使い物になるなら試してみたいですね。

現在実行しているメソッドを取得

C#で現在実行しているメソッドを取得するプロパティを作ってみました。
何かと役に立ちそう。
インライン化されないようにMethodImpl(MethodImplOptions.NoInlining)を指定するのがポイントです。

public static class Current {
    public static MethodBase Method {
        [MethodImpl(MethodImplOptions.NoInlining)]
        get {
            var stackFrame = new StackFrame(1);
            return stackFrame.GetMethod();
        }
    }
}

HTMLからPDFに変換

あるC#案件でHTMLからPDFファイルに変換する必要があった時の話。

C#で使用できるPDFライブラリを探し、PdfSharpにたどり着きました。
少し面倒だが日本語フォントにも対応できます。
しかし、PDFドキュメントの作成方法がGraphicsオブジェクト並のローレベルな描画メソッドなので、HTMLから変換するのは手間がかかりすぎ。

次に見つけたのが、HtmlRenderer.PdfSharp。
これは今回したいHTMLからPDFをそのまま実現できるライブラリ。ありがたい。
ですが、日本語フォントの出力方法が不明。
内部的にPdfSharpを使用しているが、バージョンが古いため日本語フォントを使用する方法が異なり、方法がわからない。

他に良いライブラリも無く、どうしたものかと思っていたが、別に変換が出来れば方法は何でも良いので、
コマンドラインでHTMLからPDFに変換できるソフトを探し、wkhtmltopdfを見つけました。
日本語フォントにも対応でき、正しくPDFに変換できました。

実装がC#なので、C#から使用できるライブラリを探しましたが、こだわる必要が有りませんでした。

忙しくなりました。

コロナ禍の影響による案件停滞も落ち着き、反動で急激に忙しくなりました。
手が空いている間に進めていました評価用画像処理ソフトは一旦置いといて、納期がある通常業務の開発を進めています。
なんとか前倒しして、評価用画像処理ソフトの開発を進めたいところです。