-
Notifications
You must be signed in to change notification settings - Fork 810
Don't use readonly struct in enumerator #74
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
Conversation
If not mistaken, a readonly field value is only copied when the field is of value type. |
Yep, wrong fields :) Should have been the |
Replaced with better change than just making it not readonly, improved MoveNext. Before
After .method public hidebysig newslot virtual final
instance bool MoveNext() cil managed
{
// Code size 96 (0x60)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_0006: ldc.i4.0
IL_0007: bge.s IL_000b
IL_0009: ldc.i4.0
IL_000a: ret
IL_000b: ldarg.0
IL_000c: ldfld string[] Microsoft.Extensions.Primitives.StringValues/Enumerator::_values
IL_0011: brfalse.s IL_004f
IL_0013: ldarg.0
IL_0014: ldfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_0019: ldarg.0
IL_001a: ldfld string[] Microsoft.Extensions.Primitives.StringValues/Enumerator::_values
IL_001f: ldlen
IL_0020: conv.i4
IL_0021: bge.s IL_0046
IL_0023: ldarg.0
IL_0024: ldarg.0
IL_0025: ldfld string[] Microsoft.Extensions.Primitives.StringValues/Enumerator::_values
IL_002a: ldarg.0
IL_002b: ldfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_0030: ldelem.ref
IL_0031: stfld string Microsoft.Extensions.Primitives.StringValues/Enumerator::_current
IL_0036: ldarg.0
IL_0037: ldarg.0
IL_0038: ldfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_003d: ldc.i4.1
IL_003e: add
IL_003f: stfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_0044: ldc.i4.1
IL_0045: ret
IL_0046: ldarg.0
IL_0047: ldc.i4.m1
IL_0048: stfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_004d: ldc.i4.0
IL_004e: ret
IL_004f: ldarg.0
IL_0050: ldc.i4.m1
IL_0051: stfld int32 Microsoft.Extensions.Primitives.StringValues/Enumerator::_index
IL_0056: ldarg.0
IL_0057: ldfld string Microsoft.Extensions.Primitives.StringValues/Enumerator::_current
IL_005c: ldnull
IL_005d: cgt.un
IL_005f: ret
} // end of method Enumerator::MoveNext Shorter code path for default single value; doesn't duplicate |
Also changed the enumerator ctor to take StringValues by Removed the
Made
|
_values = values; | ||
_current = null; | ||
_values = values._values; | ||
_current = values._value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When is this ever correct? Why not just leave it null, which is equally 'undefined'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StringValue with 0 and 1 count; where the array is not set. Changed move next to fit the behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha
@benaadams - this seems innocuous, but is there any big picture impact here other than counting instructions? It's likely |
Are we still making |
@rynowak yeah, MoveNext is a player aspnet/KestrelHttpServer#528 its (RPS * header count) is half the cost of the current encoding the current headers to ascii (is a higer percentage more with improved version aspnet/KestrelHttpServer#527) |
@benaadams - have you tried just using indexing? |
@halter73 might want to remeasure |
|
@rynowak no; will give it a go. Still a high cost enumerator currently though :) And much much worse if any extra fields are added to StringValues. |
Still seems to me that making StringValues a class is better: Baseline (dev)
Baseline w/ 4 extra fields
StringValues ref enumerator
StringValues ref enum w/ 4 extra fields
StringValues class
StringValues class w/ 4 extra fields
|
Generally only one value
@rynowak sped up |
Merged for now. If this becomes a class again, we can simplify the enumerator code. |
Ref: http://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/