-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C# backend generates unoptimized enumerator pattern #48
Comments
Thanks for the suggestion. Maybe I misunderstand, but would you want to return a About |
Thanks for the response! I was mostly shooting for class SliceUseAsciiStringPattern : IEnumerable<UseAsciiStringPattern>
{
public IEnumerator<UseAsciiStringPattern> GetEnumerator()
{
for (var i = 0; i < (int)len; ++i)
{
yield return this[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
} The above would be turned into something like the below, and it's likely not everything is needed, I just adapted the implementation of dotnet's List.cs. class SliceUseAsciiStringPattern : IEnumerable<UseAsciiStringPattern>
{
// Writing this, I wonder if it's easier to just `new ReadOnlySpan<T>(this.data.ToPointer(), (int)this.len).GetEnumerator()`
public Enumerator GetEnumerator() =>
new Enumerator(this);
IEnumerator<UseAsciiStringPattern> IEnumerable<UseAsciiStringPattern>.GetEnumerator() =>
new Enumerator(this);
IEnumerator IEnumerable.GetEnumerator() =>
new Enumerator(this);
public struct Enumerator : IEnumerator<UseAsciiStringPattern>, IEnumerator
{
private readonly SliceUseAsciiStringPattern _list;
private int _index;
private UseAsciiStringPattern? _current;
internal Enumerator(SliceUseAsciiStringPattern list)
{
_list = list;
_index = 0;
_current = default;
}
public void Dispose()
{
}
public bool MoveNext()
{
var localList = _list;
if ((uint)_index < (uint)localList.len)
{
_current = localList[_index];
_index++;
return true;
}
_index = localList.len + 1;
_current = default;
return false;
}
public UseAsciiStringPattern Current => _current!;
object? IEnumerator.Current => _current;
void IEnumerator.Reset()
{
_index = 0;
_current = default;
}
}
}
} I also think the Enumerator implementation can be deduplicated if an |
Ah, yes, I'm generally open to that. I don't have so much time to test this right now, but I'd accept PRs. The only question / caveat I have, is this really faster than the KISS version existing right now? You'd have to pay for the bounds check anyway as you just move that cost to
Doesn't this need In any case, checklist for PRs implementing this
|
If you look at the generated IEnumerable code, it generates a plain yield return enumerator. That means there's an allocation on every GetEnumerator call - which is normally avoided by providing a concrete
StructEnumerator GetEnumerator()
overload. The code seems to do a lot of redundant work (exception is checked on the indexer hot path, so indexer will never be inlined).Would it make a bit more sense to return a
ReadOnlySpan<T>
view over the data? That would also give a bit of flexibility to the caller at no performance expense. That would also remove the inheritance information from the struct,s.The text was updated successfully, but these errors were encountered: