-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Serialization] Do less work checking if a value can be deserialized. #9666
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
[Serialization] Do less work checking if a value can be deserialized. #9666
Conversation
@swift-ci Please test |
Build failed |
@swift-ci Please test macOS |
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.
Some minor suggestions for improvement.
nameAndDependencyIDs.slice(numNameComponentsBiased); | ||
} else { | ||
name = baseName; | ||
nameAndDependencyIDs = nameAndDependencyIDs.drop_front(); |
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.
The change of meaning of nameAndDependencyIDs
here really threw me. The code is correct, but kinda hard to read. What about just defining
auto dependencyIDs = nameAndDependencyIDs.slice(numNameComponentsBiased);
?
lib/Serialization/Serialization.cpp
Outdated
SmallVector<Type, 2> result; | ||
ty.visit([&](CanType next) { | ||
if (auto *nominal = next->getAnyNominal()) | ||
result.push_back(nominal->getDeclaredType()); |
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.
How about getDeclaredInterfaceType
here, so we don't have any archetypes in there that would force deserialization of a generic environment?
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.
getDeclaredType should already be using UnboundGenericType, no? I wanted the absolute smallest type.
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.
…but that probably doesn't make sense for nested types. Okay, getDeclaredInterfaceType it is.
lib/Serialization/Serialization.cpp
Outdated
if (auto *nominal = next->getAnyNominal()) | ||
result.push_back(nominal->getDeclaredType()); | ||
}); | ||
return result; |
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.
Should you unique the types in result
?
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.
Ah, good idea.
Previously we recorded the canonical type of the declaration and made sure we could deserialize that, but that's a lot of extra work building up intermediate types that we mostly don't need. Instead, record smaller types that represent the possible points of failure--- right now, just the nominal types that are referenced by the value (function, variable/constant, subscript, or initializer). I chose to use types instead of declarations here because types can potentially encode more complicated constraints later (such as generic types checking that their arguments still conform). This gains us back 20% of type-checking time on a compile-time microbenchmark: `let _ = [1, 2]`. I expect the effect is less dramatic the more expressions you have, since we only need to deserialize things once.
1d905b1
to
fe4f8d4
Compare
macOS full test on prior version (passed!) @swift-ci Please smoke test |
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.
LGTM, thank you!
https://ci.swift.org/job/swift-PR-osx-smoke-test/8231/
|
@swift-ci Please smoke test macOS |
@jrose-apple Strange... I'll disable the test. |
@jrose-apple Should be clear now. |
@swift-ci Please smoke test macOS |
…swiftlang#9666) Previously we recorded the canonical type of the declaration and made sure we could deserialize that, but that's a lot of extra work building up intermediate types that we mostly don't need. Instead, record smaller types that represent the possible points of failure--- right now, just the nominal types that are referenced by the value (function, variable/constant, subscript, or initializer). I chose to use types instead of declarations here because types can potentially encode more complicated constraints later (such as generic types checking that their arguments still conform). This gains us back 20% of type-checking time on a compile-time microbenchmark: `let _ = [1, 2]`. I expect the effect is less dramatic the more expressions you have, since we only need to deserialize things once.
Previously we recorded the canonical type of the declaration and made sure we could deserialize that, but that's a lot of extra work building up intermediate types that we mostly don't need. Instead, record smaller types that represent the possible points of failure—right now, just the nominal types that are referenced by the value (function, variable/constant, subscript, or initializer). I chose to use types instead of declarations here because types can potentially encode more complicated constraints later (such as generic types checking that their arguments still conform).
This gains us back 20% of type-checking time on a compile-time microbenchmark:
let _ = [1, 2]
. I expect the effect is less dramatic the more expressions you have, since we only need to deserialize things once.