-
Notifications
You must be signed in to change notification settings - Fork 383
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
Perf improvements part 6: startup time #1654
Conversation
…st common scenarios
… methods for it. -3ms for startup!
…vided (0.4 ms of JIT time)
…ple (struct). -4 JIT compilaitons
…educe the number of compilations and type loading
… time ArgumentConverter was used, no matter if we wanted to create a list or not)
# Conflicts: # src/System.CommandLine/Binding/ArgumentConverter.cs
src/System.CommandLine/Binding/ArgumentConverter.DefaultValues.cs
Outdated
Show resolved
Hide resolved
src/System.CommandLine/Binding/ArgumentConverter.DefaultValues.cs
Outdated
Show resolved
Hide resolved
@@ -25,14 +22,21 @@ private static Array CreateEmptyArray(Type itemType, int capacity = 0) | |||
private static IList CreateEmptyList(Type listType) | |||
{ | |||
#if NET6_0_OR_GREATER | |||
var ctor = (ConstructorInfo)listType.GetMemberWithSameMetadataDefinitionAs(_listCtor.Value); | |||
ConstructorInfo? listCtor = _listCtor; |
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.
Are there reflection-based argument conversions used with the source generator support?
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.
Source generator support is still pending. The original source generator work we did was superseded by improvements we've made to support trimming.
argument, | ||
argument.Arity.MinimumNumberOfValues, | ||
argument.Arity.MaximumNumberOfValues) is ArgumentConversionResult failed && | ||
failed is not null) // returns null on success |
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.
failed is not null
check isn't needed. I think it's redundant with is ArgumentConversionResult failed
which won't match if the return value of Validate
is null
.
The best way to review this PR is most probably to look at each commit separately. The changes belong to few categories:
ICommandHandler
with synchronousInvoke
method: this allows to avoid the need of loading and jitting all async machinery for users who don't want to useasync
overloads (I would imagine that most users don't need it as async should be used for potentially blocking IO operations)static Lazy<T>
fields, which get jitted when given type is referenced for the firs time. I've just moved the logic to getters and it's compiled when it's used. In worst case scenario users who for some reason use multiple threads to parse command line args are going to duplicate the initialization work.structs
. Every struct is of a different size and because of that, the JIT compiler needs to prepare a dedicated version of each generic collection (or other generic type that uses struct and type argument) for each unique value type. ChangingToken
fromstruct
toclass
reduced the number of JIT compilations reported by Perfview by 20!For the following app that mimics @jkotas example:
the total execution time measured with
Measure-Command
for--bool true -s test
arguments went down from 73 ms to 60-62 ms (Windows)