Rect.Containsもreadonly struct + in で高速化できる
RectとImmutableRectのContainsのベンチマークです。 IsEmptyの判定を排除できればもっと速度が出るのですが、互換性を重視してあえて削除していません。
なんでこれほどRectに拘るかといいますと、仮想化は矩形の判定の塊だからです。仮想化を高速化したいのに矩形の判定を横着するのは勿体無い、というわけです。
Method | Mean | Error | StdDev |
---|---|---|---|
Rect_Rect_Contains | 117.81 us | 0.2385 us | 0.1862 us |
ImmutableRect_ImmutableRect_Contains | 39.04 us | 0.1703 us | 0.1593 us |
ImmutableRect_Rect_Contains | 62.09 us | 0.3684 us | 0.3446 us |
これが、今回の範囲に関係するソースコードです。
[Benchmark] public void Rect_Rect_Contains() { var rect1 = new Rect(0, 0, 5000, 5000); for (int idx = 0; idx < 10000; idx++) { _contains_results[idx] = rect1.Contains(new Rect(0, 0, idx, idx)); } } [Benchmark] public void ImmutableRect_ImmutableRect_Contains() { var rect1 = new ImmutableRect(0, 0, 5000, 5000); for (int idx = 0; idx < 10000; idx++) { _contains_results[idx] = rect1.Contains(new ImmutableRect(0, 0, idx, idx)); } } [Benchmark] public void ImmutableRect_Rect_Contains() { var rect1 = new ImmutableRect(0, 0, 5000, 5000); for (int idx = 0; idx < 10000; idx++) { _contains_results[idx] = rect1.Contains(new Rect(0, 0, idx, idx)); } } public readonly struct ImmutableRect : IEquatable<ImmutableRect> { public readonly double X; public readonly double Y; public readonly double Width; public readonly double Height; public ImmutableRect(double x, double y, double width, double height) => (X, Y, Width, Height) = (x, y, width, height); public static implicit operator ImmutableRect(Rect source) => new ImmutableRect(source.X, source.Y, source.Width, source.Height); public static implicit operator Rect(in ImmutableRect source) => new Rect(source.X, source.Y, source.Width, source.Height); // 2018/08/20 より高速なコードに更新 public bool Contains(in ImmutableRect rect) { return Width >= 0 && Height >= 0 // !IsEmpty && X <= rect.X && Y <= rect.Y && X + Width >= rect.X + rect.Width && Y + Height >= rect.Y + rect.Height; } }