-
Notifications
You must be signed in to change notification settings - Fork 606
Minor WireFormatting code cleanups and optimizations. #981
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
ce66c43
to
4ef4266
Compare
Updating comments after rebase. |
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.
I get a test failure in RabbitMQ.Client.Unit.TestFieldTableFormatting
on this branch:
RABBITMQ_RABBITMQCTL_PATH=rabbitmqctl dotnet test projects/Unit --filter "FullyQualifiedName~RabbitMQ.Client.Unit.TestFieldTableFormatting
Yeah, I'll fix it in a couple hours, know what the problem is :) |
I like the change 👍 didn't yet think about it yet now that we have the new APIs available. One question though: How likely is a null / empty string being passed for real world examples? |
Likely given that it's a valid Exchange for example (the default exchange) :) also, people initializing arrays or lists, aiming to put stuff into and sometimes omitting data, so I think it's a valid use-case. |
ef8720a
to
d7c5663
Compare
return WriteShortStrImpl(span, val, maxLength); | ||
} | ||
|
||
private static int WriteShortStrImpl(Span<byte> span, string val, int maxLength) |
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.
Now I'm hooked =) Was it beneficial to extract this part in it's own method? (I assume this won't be inlined)
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.
A little. Anything containing exception handling won't be inlined. You can use the InliningDiagnoser from benchmarksdotnet to see inlining errors. :)
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.
Example using this attribute [BenchmarkDotNet.Diagnostics.Windows.Configs.InliningDiagnoser(true, true)]
--------------------
WireFormatting_ReadWritePrimitives.WriteDecimal: ShortRun(IterationCount=3, LaunchCount=1, WarmupCount=3)
--------------------
Inliner: Benchmarks.WireFormatting.WireFormatting_ReadWritePrimitives.WriteDecimal - instance int32 ()
Inlinee: System.ThrowHelper.ThrowArgumentOutOfRangeException - void ()
Fail Reason: does not return
--------------------
Inliner: Benchmarks.WireFormatting.WireFormatting_ReadWritePrimitives.WriteDecimal - instance int32 ()
Inlinee: System.Decimal.GetBits - int32[] (value class System.Decimal)
Fail Reason: unprofitable inline
--------------------
Inliner: Benchmarks.WireFormatting.WireFormatting_ReadWritePrimitives.WriteDecimal - instance int32 ()
Inlinee: RabbitMQ.Client.Impl.WireFormatting.ThrowWireFormattingException - void (value class System.Decimal)
Fail Reason: unprofitable inline
--------------------
Inliner: Benchmarks.WireFormatting.WireFormatting_ReadWritePrimitives.WriteDecimal - instance int32 ()
Inlinee: System.ThrowHelper.ThrowArgumentOutOfRangeException - void ()
Fail Reason: does not return
--------------------
Inliner: Benchmarks.WireFormatting.WireFormatting_ReadWritePrimitives.WriteDecimal - instance int32 ()
Inlinee: System.ThrowHelper.ThrowInvalidTypeWithPointersNotSupported - void (class System.Type)
Fail Reason: unprofitable inline
--------------------
Inliner: Benchmarks.WireFormatting.WireFormatting_ReadWritePrimitives.WriteDecimal - instance int32 ()
Inlinee: System.ThrowHelper.ThrowArgumentOutOfRangeException - void (value class System.ExceptionArgument)
Fail Reason: does not return
--------------------
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.
I'm surprised that it it is faster, not quite get why...
WriteShortstr2 is fully inlined without the extra method.
Method | Length | Mean | Error | StdDev | Ratio | RatioSD | Code Size |
---|---|---|---|---|---|---|---|
WriteShortstr | 0 | 0.7690 ns | 0.0710 ns | 0.0039 ns | 1.00 | 0.00 | 115 B |
WriteShortstr2 | 0 | 2.6724 ns | 0.1118 ns | 0.0061 ns | 3.48 | 0.02 | 405 B |
WriteShortstr | 1 | 12.9989 ns | 0.0236 ns | 0.0013 ns | 1.00 | 0.00 | 364 B |
WriteShortstr2 | 1 | 13.3813 ns | 0.5709 ns | 0.0313 ns | 1.03 | 0.00 | 405 B |
WriteShortstr | 10 | 13.8706 ns | 1.0501 ns | 0.0576 ns | 1.00 | 0.00 | 364 B |
WriteShortstr2 | 10 | 15.4745 ns | 0.5192 ns | 0.0285 ns | 1.12 | 0.01 | 405 B |
WriteShortstr | 100 | 21.8589 ns | 0.5577 ns | 0.0306 ns | 1.00 | 0.00 | 364 B |
WriteShortstr2 | 100 | 21.0526 ns | 0.1686 ns | 0.0092 ns | 0.96 | 0.00 | 405 B |
WriteShortstr | 255 | 28.5284 ns | 0.9557 ns | 0.0524 ns | 1.00 | 0.00 | 364 B |
WriteShortstr2 | 255 | 29.3146 ns | 4.7681 ns | 0.2614 ns | 1.03 | 0.01 | 405 B |
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.
What does WriteShortstr2 look like?
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.
Same as the other but without the call to the impl method
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.
That doesn't inline actually :) It refuses to do so because of the try/catch which never inlines.
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.
Is this still the case in the newer frameworks? (I've not checked the disassembly in that detail.)
This is done now I think :) |
I'm going to abandon this PR in favour of other smaller PRs that are easier to review and compare :) |
Proposed Changes
Code cleanups to simplify/optimize code for WireFormatting.
Types of Changes
Checklist
CONTRIBUTING.md
documentFurther Comments
A simple change, performance benchmarks shows considerable improvements to serialization times for empty/null strings and objects. Getting rid of "unsafe" code for the
netcoreapp
target.Before:
After: