Skip to content

Poor performance/code-gen with struct enumerators, especially when containing ReadOnlySpan #71510

Closed
@Chicken-Bones

Description

@Chicken-Bones

Description

Struct enumerators have a lot of potential for high-performance iteration of custom structures. I've seen 'struct-linq' discussed in several places. The following is a simple but practical example.

Try changing the type of arr to T[] and inds to ReadOnlySpan<int> and observe differences in stack spill and x86.

I'd love a way to write this code fully with spans and have it be performant.

Even the T[] and int[] version doesn't compare to the equivalent hand-written version (Test2). It looks like loop-cloning doesn't see the enumerator as eligible.

public ref struct FilteredSpanEnumerator<T>
{
	private readonly ReadOnlySpan<T> arr;
	private readonly int[] inds;

	private T current;
	private int i;

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public FilteredSpanEnumerator(ReadOnlySpan<T> arr, int[] inds) {
		this.arr = arr;
		this.inds = inds;
		current = default;
		i = 0;
	}

	public T Current => current;

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public bool MoveNext() {
		if (i >= inds.Length)
			return false;

		current = arr[inds[i++]];
		return true;
	}

	public FilteredSpanEnumerator<T> GetEnumerator() => this;

	public static void Test() => Test3(new T[100], new int[] {0, 5, 6, 12, 47, 99});

	public static void Test(ReadOnlySpan<T> elements, int[] inds) {
		foreach (var s in new FilteredSpanEnumerator<T>(elements, inds)) {
			Console.WriteLine(s);
		}
	}

	public static void Test2(ReadOnlySpan<T> elements, ReadOnlySpan<int> inds) {
		int i = 0;
		while (i < inds.Length) {
			Console.WriteLine(elements[inds[i++]]);
		}
	}
}

Configuration

.NET 6.0.6, Win x64

Analysis

Probably a duplicate of a number of issues like #68797 #9977 related to struct promotion and loop cloning heuristics.

category:cq
theme:structs
skill-level:expert
cost:large
impact:medium

Metadata

Metadata

Assignees

Labels

Priority:2Work that is important, but not critical for the releasearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions