Skip to content
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

Faster Guard APIs #7

Merged
merged 8 commits into from
Mar 6, 2020
Merged

Faster Guard APIs #7

merged 8 commits into from
Mar 6, 2020

Conversation

Sergio0694
Copy link
Member

As discussed with @antonfirsov, this PR restructures the Guard APIs to reduce the inlined asm code. Goes from this to this.

@Sergio0694 Sergio0694 added the enhancement New feature or request label Feb 28, 2020
@Sergio0694 Sergio0694 self-assigned this Feb 28, 2020
Copy link
Member

@antonfirsov antonfirsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot! But let's not stop here, we still may improve a few things.

@JimBobSquarePants
Copy link
Member

So what's missing here?

@Sergio0694
Copy link
Member Author

@JimBobSquarePants The PR itself is done for now, but @antonfirsov mentioned he wanted me to use T4 to add more type-specific implementations of the APIs. I could do that now if you wont, otherwise we can just merge this as is and then add those later on. Up to you 👍

@JimBobSquarePants
Copy link
Member

@Sergio0694 A single PR would be easier for us to update across all the repositories. If you could do the T4 changes that would be great. Thanks!

@Sergio0694
Copy link
Member Author

@JimBobSquarePants I've added the T4 template, and I've tested it with a local .NET Core template to make sure it works. I can't get it to generate the .cs file properly from the test project though, I suspect it's because T4 templates don't really play that well with shared projects. A solution would be to generate it externally and manually include the generated file in the shared project, but that of course wouldn't be ideal (could be a good enough temporary workaround though). If you'd like to go that way, I have the generated file ready, so just let me know.

Feel free to take a look if you have an idea on how to get the T4 generator to work here! 😊

@JimBobSquarePants
Copy link
Member

@Sergio0694 I'll have a look for you tomorrow. Thanks for the update!

@Sergio0694
Copy link
Member Author

No problem, happy to help! 😄

@JimBobSquarePants
Copy link
Member

@Sergio0694 I fixed the T4 templates and did some other cleanup. There's a couple of failing Guard tests though that need to fixed though. I couldn't do them as I didn't know what the intended message was.

To build the template you need to use the Build -> Transform All T4 Templates command.

public const MethodImplOptions ShortMethod = MethodImplOptions.NoInlining;
#else
#if SUPPORTS_HOTPATH
public const MethodImplOptions HotPath = MethodImplOptions.AggressiveOptimization;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JimBobSquarePants Possibly dumb quesiton, why are we just using MethodImplOptions.AggressiveOptimization in this case instead of MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization? I've seen them used at the same time quote often around CoreCLR, and I don't think that the optimization flag implies inlining as well - don't we want both those JIT perks for hot paths? 🤔

Copy link
Member

@JimBobSquarePants JimBobSquarePants Mar 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've only seen them used as flags

MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization

I haven't managed to find any documentation on the new attribute at all, nor could I find the issue that introduced it so I thought I better keep them separate as the original enum defines.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should combine them. @antonfirsov Do you have any insight?

Copy link
Member

@JimBobSquarePants JimBobSquarePants Mar 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found the original CoreFX issue.

dotnet/runtime#27370

Dunno why I couldn't before.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sergio0694 Looks like you definitely want to keep them separate. Relevant conversation starts here.

dotnet/runtime#27370 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JimBobSquarePants I'm not sure what you mean there, what exception message? I mean, I can see the throw methods for the out of range errors with a formatted message already, what are you referring to here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sergio0694 I suppose inlining is not the only magic provided by AggressiveOptimization, but you're right Guard methods are so short, there really isn't anything to agressively optimize, and if you say it might bring other risks, let's leave it out for now!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure since that conversation was really long and I could just read up to some point, but apparently there were a lot of various implications depending on the scenario. The main takeaway I got was this:

AggressiveInlining just pushes the JIT to inline the (marked) callee into its caller
AggressiveOptimization pushes the JIT to try to inline callees from their (marked) caller (the one with the attribute). It also suggests to go straight to the best JIT tiering possible.

In out case, the Guard APIs don't call functions that could benefit from inlinig, in fact all the helpers should not be inlined, and are marked as such. We only care about those Guard APIs themselves being inlined into their callers, so yeah I'd say (at least for now) the safe bet would be to just use AggressiveInlining 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sergio0694 What I mean is that the unit tests expect a different value for the message than the actual output. Shall I just update the test to match?

https://github.com/SixLabors/SharedInfrastructure/pull/7/files#diff-f73475a089d950d0e0a672480a854ebcR45

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah my bad, I didn't consider the fact the tests were also matching the exact error message as well. Sure thing, yeah that would be perfect then 👍

@JimBobSquarePants JimBobSquarePants merged commit 8dfef29 into master Mar 6, 2020
@JimBobSquarePants JimBobSquarePants deleted the sp/faster-guard-apis branch March 6, 2020 04:43
@antonfirsov
Copy link
Member

So did you figure out how to make VS generate the .cs for .tt? If yes, why didn't you push the .cs? We usually add the generated files.

@JimBobSquarePants
Copy link
Member

If you push the cs then any time you ask VS to rebuild templates it alters the cs file line endings and causes the submodule to be marked dirty. You then have to reset the submodule which is a chore.

I figured out a hack whereby we deliberately ignore the generated file in the submodule but use a pre build target to copy the file into the solution so that we have a tracked copy.

I'm looking at an xplat solution that will allow the consuming library to convert all T4 templates on build and save the copy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants