utf8リテラルの使い方

.Net7.0 C#Ver11.0がリリースされました。
.Net7.0にすると、パフォーマンスが上がります。
いくつかベンチマークを流してみた感じでも、あちこち、少しずつ早くなっていますね。
ありがたいことです。

さて、同時期にリリースされた、C#Ver11.0
私が今、一番気になっているのは、utf8リテラルです。

例えば、OrderのJsonを作る場合、Jsonの中に、”buy”,”sell”とかを埋め込むわけです。
この”buy”,”sell”をstringで作ってしまうと、シリアライズするときに、UTF16→UTF8の変換が発生するので、stringは避けたいです。
じゃあどうするかというと、ReadOnlySpanか、byte[]かという感じです。
ReadOnlySpanの方が速いですが、Httpのリクエストするときに、asyncを使うわけで、asyncを使うとReadOnlySpanを引数で渡せません。

static ReadOnlySpan<byte> RosBuy() => new byte[] { (byte)'b', (byte)'u', (byte)'y' };

public Task Buy(double price, double size) => Order(RosBuy(), price, size);

public async Task Order(ReadOnlySpan<byte> side, double price, double size)
{
    // ここでいろいろ処理
    return;
}

こう書きたいのだけれども、OrderのReadOnlySpanはasyncで使えないと怒られる。
なので、byte[]を使って、次の様に書いていました。

static byte[] _buy = Encoding.UTF8.GetBytes("buy");

public Task Buy(double price, double size) => Order(_buy, price, size);

public async Task Order(byte[] side, double price, double size)
{
    // ここでいろいろ処理
    return;
}

byte[]をstaticで作っておくことで、UTF16→UTF8の変換は初回のみになっています。
その代わり、byte[]分のメモリを起動後ずっと使うことになります。まあ量はたいしたことはありませんが。
new byte[] { (byte)’b’, (byte)’u’, (byte)’y’ };
って書けば、初回の変換コストも外せるのですが、コードの書きやすさを優先しました。

さて、今回、utf8リテラルが入ったことで、まずこう変えられそうです。

static byte[] _buy = Encoding.UTF8.GetBytes("buy");
// ↓
static byte[] _buy = "buy"u8.ToArray();

書きやすさは似たようなものですが、悪化はしていないです。
初回のみなので、誤差のようなものですが、Utf16→Utf8の変換が無い分、速いです。
(気になってベンチマークも取りましたが、早くなっています。)

さて次に、”buy”をbyte[]ではなく、u8定数で渡すには、asynとReadOnlySpan のあたりを何とかしないといけません。
改造したものがこちら

public Task Buy(double price, double size) => Order("buy"u8, price, size);

public Task Order(ReadOnlySpan<byte> side, double price, double size)
{
    byte[] json = GetJson(side, price, size);
    return OrderCore(json);
}

public async Task OrderCore(byte[] json)
{
    // ここでいろいろ処理
    return;
}

パラメータから、Jsonを作る部分までは、asynを使わずに、同期プログラムで処理。
byte[]のjsonになってから、asyncのメインのプログラムを呼び出します。
これでやっとstaticのbyte[]を作っておくのから解放されました。
まあ、jsonのbyte[]も、キャッシュしたりいろいろ速度上げられますが、こちらは割愛。
なお、メソッド呼出のコストが増えるので、パフォーマンスとしては似たようなものにはなってしまいましたが。

utf8リテラルの使い方で、もっと良い方法とかご存じの方は、コメントとかで教えてもらえると嬉しいです。

投稿日:
カテゴリー: C#

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です