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

First prototype of Performance Annotations #39902

Merged
merged 10 commits into from Oct 29, 2021

Conversation

eeckstein
Copy link
Member

The purpose of performance annotations are to give the developer a tool to ensure that a certain piece of code meets certain performance characteristics.
If an annotated function contains some code which requires unwanted runtime operations, the compilation will fail with an error explaining the reason.

This PR contains a first prototype implementation of the feature:

  • two new attributes: @_noLocks and @_noAllocation
  • a SIL tool which predicts/estimates the runtime effects for SIL instructions.
  • a "mandatory generic specializer" pass which performs generic specializations for annotated functions.
  • a new diagnostic pass which prints "performance errors" in case an annotated function (or its callees) violate the specified performance constraints.

For now, the new feature is gated with an option -experimental-performance-annotations.

rdar://83882635

Copy link
Contributor

@mikeash mikeash left a comment

Choose a reason for hiding this comment

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

Really cool stuff. I did not look closely at all of the effects annotations on the runtime functions to make sure they're correct. Let me know if and when you'd like me to do that. I figured we might at least want to wait until you're farther along before we put in that effort.

ERROR(performance_arc,none,
"this code performs reference counting operations which can cause locking", ())
ERROR(performance_objectivec,none,
"calls of Objective-C methods can have unpredictable performance", ())
Copy link
Contributor

Choose a reason for hiding this comment

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

objc_msgSend will also take a lock on the slow path, and the slow path can happen unpredictably due to cache invalidation. Not sure if that's also worth calling out.

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 think "unpredictable performance" is a strong enough term which IMO includes locks, etc.


// Class objc_lookUpClass(const char *name);
FUNCTION(LookUpClass, objc_lookUpClass, C_CC, AlwaysAvailable,
RETURNS(ObjCClassPtrTy),
ARGS(Int8PtrTy),
ATTRS(NoUnwind, ReadNone))
ATTRS(NoUnwind, ReadNone),
EFFECT(MetaData))
Copy link
Contributor

Choose a reason for hiding this comment

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

Wow, adding all of these effects annotations was a big job.

@@ -311,6 +311,34 @@ WARNING(warn_dead_weak_store,none,
"weak reference will always be nil because the referenced object is "
"deallocated here", ())

// performance diagnostics
ERROR(performance_annotations_not_enabled,none,
"use -experimental-performance-annotations to enabled performance annotations", ())

Choose a reason for hiding this comment

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

“enable”

@mix174
Copy link

mix174 commented Oct 27, 2021

looks pretty good

Define the possible runtime effects of an instruction in an enum `RuntimeEffect`.
Add a new utility `swift:getRuntimeEffect` to estimate the runtime effects of an instruction.

Also, add a mechanism to validate the correctness of the analysis in IRGen: annotate all runtime functions in RuntimeFunctions.def with the actual effect what the runtime function has or can have. Then check if the effects of emitted runtime functions for an instruction match what `getRuntimeEffect` predicts.
This check is only enabled on demand by defining the CHECK_RUNTIME_EFFECT_ANALYSIS macro in RuntimeEffect.h
…rrorHandlingBlocks

* ReachingReturnBlocks: computes the set of blocks from which a path to the return-block exists (does not include paths to a throw-block)
* NonErrorHandlingBlocks: computes the set of blocks which are not used for error handling, i.e. not (exclusively) reachable from the error-block of a try_apply
This pass is only used for functions with performance annotations (@_noLocks, @_noAllocation).
It runs in the mandatory pipeline and specializes all function calls in performance-annotated functions and functions which are called from such functions.
In addition, the pass also does some other related optimizations: devirtualization, constant-folding Builtin.canBeClass, inlining of transparent functions and memory access optimizations.
…ions in annotated functions.

The PerformanceDiagnostics pass issues performance diagnostics for functions which are annotated with performance annotations, like @_noLocks, @_noAllocation.
This is done recursively for all functions which are called from performance-annotated functions.

rdar://83882635
@eeckstein
Copy link
Member Author

@swift-ci test

@swift-ci
Copy link
Collaborator

Build failed
Swift Test Linux Platform
Git Sha - 9f8b155

@eeckstein
Copy link
Member Author

@swift-ci smoke test linux

@eeckstein
Copy link
Member Author

@swift-ci test Windows

@eeckstein eeckstein merged commit d5ae511 into apple:main Oct 29, 2021
@eeckstein eeckstein deleted the performance-annotations branch October 29, 2021 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants