6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#でSpan<byte>の全ての要素が同じ値かを素早く判断する

Last updated at Posted at 2025-02-26

結論

IndexOfAnyExceptを使えば速い
(追記:有り無しを調べるだけならContainsAnyExceptがあるみたいです)

動機

ReadOnlySpan<byte>があったとして、その要素がすべて0xffかどうかを判断したかった。

やってみたこと

foreachを使う

一番シンプルなやり方はforeachを使うやり方。

public bool ForeachLoop()
{
    var span = data.AsSpan();
    foreach (var byteData in span)
    {
        if (byteData != 0xff)
        {
            return false;
        }
    }
    return true;
}

foreachではなくてforを使う

foreachを使わずにforを使ってインデックスで参照した場合

public bool ForLoop()
{
    var span = data.AsSpan();
    for (var i = 0; i < span.Length; i++)
    {
        if (span[i] != 0xff)
        {
            return false;
        }
    }
    return true;
}

IndexOfAnyExceptを使う

この記事の本命。引数で与えられた数値以外のデータが見つかったらそのインデックスを返すという関数。見つからなかった場合は-1を返します。MemoryExtensionsの中にあるみたいです。他にも便利そうなやつが色々定義されてました。

public bool IndexOfAnyExcept()
{
    var span = data.AsSpan();
    return span.IndexOfAnyExcept((byte)0xff) == -1;
}

ベンチマーク

.NET 9でBenchmarkdotnetを使って計測してみました。32KBの大きさの全てが0xffバイト配列を渡してます。

// * Summary *

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3194)
Intel Core i5-14500, 1 CPU, 20 logical and 14 physical cores
.NET SDK 9.0.101
  [Host]     : .NET 9.0.0 (9.0.24.52809), X64 AOT AVX2
  DefaultJob : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2


| Method           | Mean       | Error    | StdDev   |
|----------------- |-----------:|---------:|---------:|
| ForeachLoop      | 9,071.5 ns | 93.23 ns | 82.64 ns |
| ForLoop          | 9,069.3 ns | 82.11 ns | 76.81 ns |
| IndexOfAnyExcept |   391.2 ns |  7.70 ns |  7.57 ns |

// * Hints *
Outliers
  Bench.ForeachLoop: Default      -> 1 outlier  was  removed (9.29 us)
  Bench.IndexOfAnyExcept: Default -> 1 outlier  was  removed (415.33 ns)

// * Legends *
  Mean   : Arithmetic mean of all measurements
  Error  : Half of 99.9% confidence interval
  StdDev : Standard deviation of all measurements
  1 ns   : 1 Nanosecond (0.000000001 sec)

IndexOfAnyExceptが圧倒的に速かったです。byte型でしか試していませんが、他の数値型でも速くなるのかな。

6
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?